/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package android.server.wm;

import static android.server.wm.ActivityManagerTestBase.launchHomeActivityNoWait;
import static android.server.wm.BarTestUtils.assumeHasStatusBar;
import static android.server.wm.UiDeviceUtils.pressUnlockButton;
import static android.server.wm.UiDeviceUtils.pressWakeupButton;
import static android.server.wm.WindowUntrustedTouchTest.MIN_POSITIVE_OPACITY;
import static android.server.wm.app.Components.OverlayTestService.EXTRA_LAYOUT_PARAMS;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.server.wm.WindowManagerState.WindowState;
import android.server.wm.app.Components;
import android.server.wm.settings.SettingsSession;
import android.util.ArraySet;
import android.util.Log;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;

import androidx.test.filters.FlakyTest;
import androidx.test.rule.ActivityTestRule;

import com.android.compatibility.common.util.CtsTouchUtils;
import com.android.compatibility.common.util.SystemUtil;

import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Ensure moving windows and tapping is done synchronously.
 *
 * Build/Install/Run:
 *     atest CtsWindowManagerDeviceTestCases:WindowInputTests
 */
@Presubmit
public class WindowInputTests {
    private static final String TAG = "WindowInputTests";
    private final int TOTAL_NUMBER_OF_CLICKS = 100;
    private final ActivityTestRule<TestActivity> mActivityRule =
            new ActivityTestRule<>(TestActivity.class);
    private static final int TAPPING_TARGET_WINDOW_SIZE = 100;
    private static final int PARTIAL_OBSCURING_WINDOW_SIZE = 30;

    private Instrumentation mInstrumentation;
    private final WindowManagerStateHelper mWmState = new WindowManagerStateHelper();
    private TestActivity mActivity;
    private InputManager mInputManager;
    private View mView;
    private final Random mRandom = new Random(1);

    private int mClickCount = 0;
    private final long EVENT_FLAGS_WAIT_TIME = 2;

    @Before
    public void setUp() {
        pressWakeupButton();
        pressUnlockButton();
        launchHomeActivityNoWait();

        mInstrumentation = getInstrumentation();
        mActivity = mActivityRule.launchActivity(null);
        mInputManager = mActivity.getSystemService(InputManager.class);
        mInstrumentation.waitForIdleSync();
        mClickCount = 0;
    }

    @Test
    @FlakyTest(bugId = 188207199)
    public void testMoveWindowAndTap() throws Throwable {
        final WindowManager wm = mActivity.getWindowManager();
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
        p.setFitInsetsTypes(WindowInsets.Type.systemBars()
                | WindowInsets.Type.systemGestures());
        p.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        p.width = p.height = 20;
        p.gravity = Gravity.LEFT | Gravity.TOP;

        // Set up window.
        mActivityRule.runOnUiThread(() -> {
            mView = new View(mActivity);
            mView.setBackgroundColor(Color.RED);
            mView.setOnClickListener((v) -> {
                mClickCount++;
            });
            mActivity.addWindow(mView, p);
        });
        mInstrumentation.waitForIdleSync();

        final WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
        final WindowInsets windowInsets = windowMetrics.getWindowInsets();
        final Rect windowBounds = new Rect(windowMetrics.getBounds());
        windowBounds.inset(windowInsets.getInsetsIgnoringVisibility(p.getFitInsetsTypes()));

        // Move the window to a random location in the window and attempt to tap on view multiple
        // times.
        final Point locationInWindow = new Point();
        for (int i = 0; i < TOTAL_NUMBER_OF_CLICKS; i++) {
            selectRandomLocationInWindow(windowBounds, locationInWindow);
            mActivityRule.runOnUiThread(() -> {
                p.x = locationInWindow.x;
                p.y = locationInWindow.y;
                wm.updateViewLayout(mView, p);
            });
            mInstrumentation.waitForIdleSync();
            int previousCount = mClickCount;

            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            mInstrumentation.waitForIdleSync();
            if (mClickCount != previousCount + 1) {
                final int vW = mView.getWidth();
                final int vH = mView.getHeight();
                final int[] viewOnScreenXY = new int[2];
                mView.getLocationOnScreen(viewOnScreenXY);
                final Point tapPosition =
                        new Point(viewOnScreenXY[0] + vW / 2, viewOnScreenXY[1] + vH / 2);
                final Rect realBounds = new Rect(viewOnScreenXY[0], viewOnScreenXY[1],
                        viewOnScreenXY[0] + vW, viewOnScreenXY[1] + vH);
                final Rect requestedBounds = new Rect(p.x, p.y, p.x + p.width, p.y + p.height);
                dumpWindows("Dumping windows due to failure");
                fail("Tap #" + i + " on " + tapPosition + " failed; realBounds=" + realBounds
                        + " requestedBounds=" + requestedBounds);
            }
        }

        assertEquals(TOTAL_NUMBER_OF_CLICKS, mClickCount);
    }

    private void dumpWindows(String message) {
        Log.d(TAG, message);
        mWmState.computeState();
        for (WindowState window : mWmState.getWindows()) {
            Log.d(TAG, "    => " + window.toLongString());
        }
    }

    private void selectRandomLocationInWindow(Rect bounds, Point outLocation) {
        int randomX = mRandom.nextInt(bounds.right - bounds.left) + bounds.left;
        int randomY = mRandom.nextInt(bounds.bottom - bounds.top) + bounds.top;
        outLocation.set(randomX, randomY);
    }

    @Test
    public void testTouchModalWindow() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        // Set up 2 touch modal windows, expect the last one will receive all touch events.
        mActivityRule.runOnUiThread(() -> {
            mView = new View(mActivity);
            p.width = 20;
            p.height = 20;
            p.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
            mView.setFilterTouchesWhenObscured(true);
            mView.setOnClickListener((v) -> {
                mClickCount++;
            });
            mActivity.addWindow(mView, p);

            View view2 = new View(mActivity);
            p.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
            p.type = WindowManager.LayoutParams.TYPE_APPLICATION;
            mActivity.addWindow(view2, p);
        });
        mInstrumentation.waitForIdleSync();

        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
        assertEquals(0, mClickCount);
    }

    // If a window is obscured by another window from the same app, touches should still get
    // delivered to the bottom window, and the FLAG_WINDOW_IS_OBSCURED should not be set.
    @Test
    public void testFilterTouchesWhenObscuredByWindowFromSameUid() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();
        // Set up a touchable window.
        mActivityRule.runOnUiThread(() -> {
            mView = new View(mActivity);
            p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
            p.width = 100;
            p.height = 100;
            p.gravity = Gravity.CENTER;
            mView.setFilterTouchesWhenObscured(true);
            mView.setOnClickListener((v) -> {
                mClickCount++;
            });
            mView.setOnTouchListener((v, ev) -> {
                touchReceived.set(true);
                eventFlags.complete(ev.getFlags());
                return false;
            });
            mActivity.addWindow(mView, p);

            // Set up an overlap window, use same process.
            View overlay = new View(mActivity);
            p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN | FLAG_NOT_TOUCHABLE;
            p.width = 100;
            p.height = 100;
            p.gravity = Gravity.CENTER;
            p.type = WindowManager.LayoutParams.TYPE_APPLICATION;
            mActivity.addWindow(overlay, p);
        });
        mInstrumentation.waitForIdleSync();
        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

        assertTrue(touchReceived.get());
        assertEquals(0, eventFlags.get(EVENT_FLAGS_WAIT_TIME, TimeUnit.SECONDS)
                & MotionEvent.FLAG_WINDOW_IS_OBSCURED);
        assertEquals(1, mClickCount);
    }

    @Test
    public void testFilterTouchesWhenObscuredByWindowFromDifferentUid() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final Intent intent = new Intent();
        intent.setComponent(Components.OVERLAY_TEST_SERVICE);
        final String windowName = "Test Overlay";
        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final int[] viewOnScreenLocation = new int[2];
        try {
            // Set up a touchable window.
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
                p.width = TAPPING_TARGET_WINDOW_SIZE;
                p.height = TAPPING_TARGET_WINDOW_SIZE;
                p.gravity = Gravity.CENTER;
                mView.setFilterTouchesWhenObscured(true);
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mView.setOnTouchListener((v, ev) -> {
                    touchReceived.set(true);
                    return false;
                });
                mActivity.addWindow(mView, p);
            });
            mInstrumentation.waitForIdleSync();
            mActivityRule.runOnUiThread(() -> {
                mView.getLocationOnScreen(viewOnScreenLocation);
                // Set up an overlap window from service, use different process.
                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                params.flags |= FLAG_NOT_TOUCHABLE;
                placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
                        viewOnScreenLocation[0], viewOnScreenLocation[1],
                        TAPPING_TARGET_WINDOW_SIZE);
                // Any opacity higher than this would make InputDispatcher block the touch
                params.alpha = mInputManager.getMaximumObscuringOpacityForTouch();
                intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                mActivity.startForegroundService(intent);
            });
            mInstrumentation.waitForIdleSync();
            waitForWindow(windowName);
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            // Touch not received due to setFilterTouchesWhenObscured(true)
            assertFalse(touchReceived.get());
            assertEquals(0, mClickCount);
        } finally {
            mActivity.stopService(intent);
        }
    }

    @Test
    public void testFlagTouchesWhenObscuredByWindowFromDifferentUid() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final Intent intent = new Intent();
        intent.setComponent(Components.OVERLAY_TEST_SERVICE);
        final String windowName = "Test Overlay";
        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();
        final int[] viewOnScreenLocation = new int[2];
        try {
            // Set up a touchable window.
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
                p.width = TAPPING_TARGET_WINDOW_SIZE;
                p.height = TAPPING_TARGET_WINDOW_SIZE;
                p.gravity = Gravity.CENTER;
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mView.setOnTouchListener((v, ev) -> {
                    touchReceived.set(true);
                    eventFlags.complete(ev.getFlags());
                    return false;
                });
                mActivity.addWindow(mView, p);
            });
            mInstrumentation.waitForIdleSync();
            mActivityRule.runOnUiThread(() -> {
                mView.getLocationOnScreen(viewOnScreenLocation);
                // Set up an overlap window from service, use different process.
                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                params.flags |= FLAG_NOT_TOUCHABLE;
                // Any opacity higher than this would make InputDispatcher block the touch
                params.alpha = mInputManager.getMaximumObscuringOpacityForTouch();
                placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
                        viewOnScreenLocation[0], viewOnScreenLocation[1],
                        TAPPING_TARGET_WINDOW_SIZE);
                intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                mActivity.startForegroundService(intent);
            });
            waitForWindow(windowName);
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            assertTrue(touchReceived.get());
            assertEquals(MotionEvent.FLAG_WINDOW_IS_OBSCURED,
                    eventFlags.get(EVENT_FLAGS_WAIT_TIME, TimeUnit.SECONDS)
                            & MotionEvent.FLAG_WINDOW_IS_OBSCURED);
            assertEquals(1, mClickCount);
        } finally {
            mActivity.stopService(intent);
        }
    }

    @Test
    public void testDoNotFlagTouchesWhenObscuredByZeroOpacityWindow() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final Intent intent = new Intent();
        intent.setComponent(Components.OVERLAY_TEST_SERVICE);
        final String windowName = "Test Overlay";
        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();

        try {
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                mView.setBackgroundColor(Color.GREEN);
                p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
                p.width = 100;
                p.height = 100;
                p.gravity = Gravity.CENTER;
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mView.setOnTouchListener((v, ev) -> {
                    touchReceived.set(true);
                    eventFlags.complete(ev.getFlags());
                    return false;
                });
                mActivity.addWindow(mView, p);

                // Set up an overlap window from service, use different process.
                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                params.flags |= FLAG_NOT_TOUCHABLE;
                params.alpha = 0;
                intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                mActivity.startForegroundService(intent);
            });
            mInstrumentation.waitForIdleSync();
            waitForWindow(windowName);
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            assertTrue(touchReceived.get());
            assertEquals(0, eventFlags.get(EVENT_FLAGS_WAIT_TIME, TimeUnit.SECONDS)
                    & MotionEvent.FLAG_WINDOW_IS_OBSCURED);
            assertEquals(1, mClickCount);
        } finally {
            mActivity.stopService(intent);
        }
    }

    @Test
    public void testFlagTouchesWhenObscuredByMinPositiveOpacityWindow() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
        final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();
        final Intent intent = new Intent();
        intent.setComponent(Components.OVERLAY_TEST_SERVICE);
        final String windowName = "Test Overlay";
        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final int[] viewOnScreenLocation = new int[2];
        try {
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                mView.setBackgroundColor(Color.GREEN);
                p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
                p.width = TAPPING_TARGET_WINDOW_SIZE;
                p.height = TAPPING_TARGET_WINDOW_SIZE;
                p.gravity = Gravity.CENTER;
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mView.setOnTouchListener((v, ev) -> {
                    touchReceived.set(true);
                    eventFlags.complete(ev.getFlags());
                    return false;
                });
                mActivity.addWindow(mView, p);
            });
            mInstrumentation.waitForIdleSync();
            mActivityRule.runOnUiThread(() -> {
                mView.getLocationOnScreen(viewOnScreenLocation);
                // Set up an overlap window from service, use different process.
                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName);
                params.flags |= FLAG_NOT_TOUCHABLE;
                params.alpha = MIN_POSITIVE_OPACITY;
                placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
                        viewOnScreenLocation[0], viewOnScreenLocation[1],
                        TAPPING_TARGET_WINDOW_SIZE);
                intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                mActivity.startForegroundService(intent);
            });
            mInstrumentation.waitForIdleSync();
            waitForWindow(windowName);
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            assertTrue(touchReceived.get());
            assertEquals(MotionEvent.FLAG_WINDOW_IS_OBSCURED,
                    eventFlags.get(EVENT_FLAGS_WAIT_TIME, TimeUnit.SECONDS)
                            & MotionEvent.FLAG_WINDOW_IS_OBSCURED);
            assertEquals(1, mClickCount);
        } finally {
            mActivity.stopService(intent);
        }
    }

    @Test
    public void testFlagTouchesWhenPartiallyObscuredByZeroOpacityWindow() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final Intent intent = new Intent();
        intent.setComponent(Components.OVERLAY_TEST_SERVICE);
        final String windowName = "Test Overlay";
        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();
        final int[] viewOnScreenLocation = new int[2];
        try {
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                mView.setBackgroundColor(Color.GREEN);
                p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
                p.width = TAPPING_TARGET_WINDOW_SIZE;
                p.height = TAPPING_TARGET_WINDOW_SIZE;
                p.gravity = Gravity.CENTER;
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mView.setOnTouchListener((v, ev) -> {
                    touchReceived.set(true);
                    eventFlags.complete(ev.getFlags());
                    return false;
                });
                mActivity.addWindow(mView, p);
            });
            mInstrumentation.waitForIdleSync();
            mActivityRule.runOnUiThread(() -> {
                mView.getLocationOnScreen(viewOnScreenLocation);
                // Set up an overlap window from service, use different process.
                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName,
                        PARTIAL_OBSCURING_WINDOW_SIZE);
                placeWindowAtLayoutCenter(params, PARTIAL_OBSCURING_WINDOW_SIZE,
                        viewOnScreenLocation[0], viewOnScreenLocation[1], TAPPING_TARGET_WINDOW_SIZE);
                // Move it off the touch path (center) but still overlap with window above
                params.y += PARTIAL_OBSCURING_WINDOW_SIZE;
                intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                mActivity.startForegroundService(intent);
            });
            mInstrumentation.waitForIdleSync();
            waitForWindow(windowName);
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            assertTrue(touchReceived.get());
            assertEquals(MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED,
                    eventFlags.get(EVENT_FLAGS_WAIT_TIME, TimeUnit.SECONDS)
                            & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
            assertEquals(1, mClickCount);
        } finally {
            mActivity.stopService(intent);
        }
    }

    @Test
    public void testDoNotFlagTouchesWhenPartiallyObscuredByNotTouchableZeroOpacityWindow()
            throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final Intent intent = new Intent();
        intent.setComponent(Components.OVERLAY_TEST_SERVICE);
        final String windowName = "Test Overlay";
        final AtomicBoolean touchReceived = new AtomicBoolean(false);
        final CompletableFuture<Integer> eventFlags = new CompletableFuture<>();

        try {
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                mView.setBackgroundColor(Color.GREEN);
                p.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
                p.width = 100;
                p.height = 100;
                p.gravity = Gravity.CENTER;
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mView.setOnTouchListener((v, ev) -> {
                    touchReceived.set(true);
                    eventFlags.complete(ev.getFlags());
                    return false;
                });
                mActivity.addWindow(mView, p);

                // Set up an overlap window from service, use different process.
                WindowManager.LayoutParams params = getObscuringViewLayoutParams(windowName, 30);
                params.flags |= FLAG_NOT_TOUCHABLE;
                // Move it off the touch path (center) but still overlap with window above
                params.y = 30;
                params.alpha = 0;
                intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                mActivity.startForegroundService(intent);
            });
            mInstrumentation.waitForIdleSync();
            waitForWindow(windowName);
            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

            assertTrue(touchReceived.get());
            assertEquals(0, eventFlags.get(EVENT_FLAGS_WAIT_TIME, TimeUnit.SECONDS)
                    & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
            assertEquals(1, mClickCount);
        } finally {
            mActivity.stopService(intent);
        }
    }

    private WindowManager.LayoutParams getObscuringViewLayoutParams(String windowName) {
        return getObscuringViewLayoutParams(windowName, 100);
    }

    private WindowManager.LayoutParams getObscuringViewLayoutParams(String windowName, int size) {
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.setTitle(windowName);
        params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        params.flags = FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN;
        params.width = size;
        params.height = size;
        params.gravity = Gravity.CENTER;
        return params;
    }

    @Test
    public void testTrustedOverlapWindow() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
        try (final PointerLocationSession session = new PointerLocationSession()) {
            session.set(true);
            session.waitForReady(mActivity.getDisplayId());

            // Set up window.
            mActivityRule.runOnUiThread(() -> {
                mView = new View(mActivity);
                p.width = 20;
                p.height = 20;
                p.gravity = Gravity.CENTER;
                mView.setFilterTouchesWhenObscured(true);
                mView.setOnClickListener((v) -> {
                    mClickCount++;
                });
                mActivity.addWindow(mView, p);

            });
            mInstrumentation.waitForIdleSync();

            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
        }
        assertEquals(1, mClickCount);
    }

    @Test
    public void testWindowBecomesUnTouchable() throws Throwable {
        final WindowManager wm = mActivity.getWindowManager();
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final View viewOverlap = new View(mActivity);

        // Set up window.
        mActivityRule.runOnUiThread(() -> {
            mView = new View(mActivity);
            p.width = 20;
            p.height = 20;
            p.gravity = Gravity.CENTER;
            mView.setOnClickListener((v) -> {
                mClickCount++;
            });
            mActivity.addWindow(mView, p);

            p.width = 100;
            p.height = 100;
            p.gravity = Gravity.CENTER;
            p.type = WindowManager.LayoutParams.TYPE_APPLICATION;
            mActivity.addWindow(viewOverlap, p);
        });
        mInstrumentation.waitForIdleSync();

        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
        assertEquals(0, mClickCount);

        mActivityRule.runOnUiThread(() -> {
            p.flags = FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE;
            wm.updateViewLayout(viewOverlap, p);
        });
        mInstrumentation.waitForIdleSync();

        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
        assertEquals(1, mClickCount);
    }

    @Test
    public void testTapInsideUntouchableWindowResultInOutsideTouches() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        final Set<MotionEvent> events = new ArraySet<>();
        mActivityRule.runOnUiThread(() -> {
            mView = new View(mActivity);
            p.width = 20;
            p.height = 20;
            p.gravity = Gravity.CENTER;
            p.flags = FLAG_NOT_TOUCHABLE | FLAG_WATCH_OUTSIDE_TOUCH;
            mView.setOnTouchListener((v, e) -> {
                // Copying to make sure we are not dealing with a reused object
                events.add(MotionEvent.obtain(e));
                return false;
            });
            mActivity.addWindow(mView, p);
        });
        mInstrumentation.waitForIdleSync();

        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);

        assertEquals(1, events.size());
        MotionEvent event = events.iterator().next();
        assertEquals(MotionEvent.ACTION_OUTSIDE, event.getAction());
    }

    @Test
    public void testTapOutsideUntouchableWindowResultInOutsideTouches() throws Throwable {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        Set<MotionEvent> events = new ArraySet<>();
        int size = 20;
        mActivityRule.runOnUiThread(() -> {
            mView = new View(mActivity);
            p.width = size;
            p.height = size;
            p.gravity = Gravity.CENTER;
            p.flags = FLAG_NOT_TOUCHABLE | FLAG_WATCH_OUTSIDE_TOUCH;
            mView.setOnTouchListener((v, e) -> {
                // Copying to make sure we are not dealing with a reused object
                events.add(MotionEvent.obtain(e));
                return false;
            });
            mActivity.addWindow(mView, p);
        });
        mInstrumentation.waitForIdleSync();

        CtsTouchUtils.emulateTapOnView(mInstrumentation, mActivityRule, mView, size + 5, size + 5);

        assertEquals(1, events.size());
        MotionEvent event = events.iterator().next();
        assertEquals(MotionEvent.ACTION_OUTSIDE, event.getAction());
    }

    @Test
    public void testInjectToStatusBar() {
        // Try to inject event to status bar.
        assumeHasStatusBar(mActivityRule);
        final long downTime = SystemClock.uptimeMillis();
        final MotionEvent eventHover = MotionEvent.obtain(
                downTime, downTime, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
        eventHover.setSource(InputDevice.SOURCE_MOUSE);
        try {
            mInstrumentation.sendPointerSync(eventHover);
            fail("Not allowed to inject to windows owned by another uid from Instrumentation.");
        } catch (RuntimeException e) {
            // Should not be allowed to inject event to a window owned by another uid from the
            // Instrumentation class.
        }
    }

    @Test
    public void testInjectFromThread() throws InterruptedException {
        // Continually inject event to activity from thread.
        final int[] decorViewLocation = new int[2];
        final View decorView = mActivity.getWindow().getDecorView();
        decorView.getLocationOnScreen(decorViewLocation);
        // Tap at the center of the view. Calculate and tap at the absolute view center location on
        // screen, so that the tapping location is always as expected regardless of windowing mode.
        final Point testPoint = new Point(decorViewLocation[0] + decorView.getWidth() / 2,
                decorViewLocation[1] + decorView.getHeight() / 2);

        final long downTime = SystemClock.uptimeMillis();
        final MotionEvent eventDown = MotionEvent.obtain(
                downTime, downTime, MotionEvent.ACTION_DOWN, testPoint.x, testPoint.y, 1);
        mInstrumentation.sendPointerSync(eventDown);

        final ExecutorService executor = Executors.newSingleThreadExecutor();
        boolean[] securityExceptionCaught = new boolean[1];
        executor.execute(() -> {
            mInstrumentation.sendPointerSync(eventDown);
            for (int i = 0; i < 20; i++) {
                final long eventTime = SystemClock.uptimeMillis();
                final MotionEvent eventMove = MotionEvent.obtain(
                        downTime, eventTime, MotionEvent.ACTION_MOVE, testPoint.x, testPoint.y, 1);
                try {
                    mInstrumentation.sendPointerSync(eventMove);
                } catch (SecurityException e) {
                    securityExceptionCaught[0] = true;
                }
            }
        });

        // Launch another activity, should not crash the process.
        final Intent intent = new Intent(mActivity, TestActivity.class);
        mActivityRule.launchActivity(intent);
        mInstrumentation.waitForIdleSync();

        executor.shutdown();
        executor.awaitTermination(5L, TimeUnit.SECONDS);

        if (securityExceptionCaught[0]) {
            // Fail the test here instead of in the executor lambda,
            // so the failure is thrown in the test thread.
            fail("Should be allowed to inject event.");
        }
    }

    private void waitForWindow(String name) {
        mWmState.waitForWithAmState(state -> state.isWindowSurfaceShown(name),
                name + "'s surface is appeared");
    }

    public static class TestActivity extends Activity {
        private ArrayList<View> mViews = new ArrayList<>();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }

        void addWindow(View view, WindowManager.LayoutParams attrs) {
            getWindowManager().addView(view, attrs);
            mViews.add(view);
        }

        void removeAllWindows() {
            for (View view : mViews) {
                getWindowManager().removeViewImmediate(view);
            }
            mViews.clear();
        }

        @Override
        protected void onPause() {
            super.onPause();
            removeAllWindows();
        }
    }

    /** Set a square window to display at the center of a square layout*/
    static void placeWindowAtLayoutCenter(WindowManager.LayoutParams windowParams, int windowWidth,
            int layoutLeft, int layoutTop, int layoutWidth) {
        windowParams.gravity = Gravity.TOP | Gravity.LEFT;
        int offset = (layoutWidth - windowWidth) / 2;
        windowParams.x = layoutLeft + offset;
        windowParams.y = layoutTop + offset;
    }

    /** Helper class to save, set, and restore pointer location preferences. */
    private static class PointerLocationSession extends SettingsSession<Boolean> {
        PointerLocationSession() {
            super(Settings.System.getUriFor("pointer_location" /* POINTER_LOCATION */),
                    PointerLocationSession::get,
                    PointerLocationSession::put);
        }

        private static void put(ContentResolver contentResolver, String s, boolean v) {
            SystemUtil.runShellCommand(
                    "settings put system " + "pointer_location" + " " + (v ? 1 : 0));
        }

        private static boolean get(ContentResolver contentResolver, String s) {
            try {
                return Integer.parseInt(SystemUtil.runShellCommand(
                        "settings get system " + "pointer_location").trim()) == 1;
            } catch (NumberFormatException e) {
                return false;
            }
        }

        // Wait until pointer location surface shown.
        static void waitForReady(int displayId) {
            final WindowManagerStateHelper wmState = new WindowManagerStateHelper();
            final String windowName = "PointerLocation - display " + displayId;
            wmState.waitForWithAmState(state -> {
                return state.isWindowSurfaceShown(windowName);
            }, windowName + "'s surface is appeared");
        }
    }
}
