/*
 * Copyright (C) 2020 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.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW;
import static android.provider.Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS;
import static android.server.wm.UiDeviceUtils.pressUnlockButton;
import static android.server.wm.UiDeviceUtils.pressWakeupButton;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.overlay.Components.OverlayActivity.EXTRA_TOKEN;
import static android.view.WindowInsets.Type.navigationBars;

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

import static com.google.common.truth.Truth.assertThat;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.Instrumentation;
import android.app.NotificationManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.server.wm.overlay.Components;
import android.server.wm.overlay.R;
import android.server.wm.settings.SettingsSession;
import android.server.wm.shared.BlockingResultReceiver;
import android.server.wm.shared.IUntrustedTouchTestService;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Toast;

import androidx.annotation.AnimRes;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.rules.ActivityScenarioRule;

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

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

@Presubmit
public class WindowUntrustedTouchTest {
    private static final String TAG = "WindowUntrustedTouchTest";

    /**
     * Opacity (or alpha) is represented as a half-precision floating point number (16b) in surface
     * flinger and the conversion from the single-precision float provided to window manager happens
     * in Layer::setAlpha() by android::half::ftoh(). So, many small non-zero values provided to
     * window manager end up becoming zero due to loss of precision (this is fine as long as the
     * zeros are also used to render the pixels on the screen). So, the minimum opacity possible is
     * actually the minimum positive value representable in half-precision float, which is
     * 0_00001_0000000000, whose equivalent in float is 0_01110001_00000000000000000000000.
     *
     * Note that from float -> half conversion code we don't produce any subnormal half-precision
     * floats during conversion.
     */
    public static final float MIN_POSITIVE_OPACITY =
            Float.intBitsToFloat(0b00111000100000000000000000000000);

    private static final float MAXIMUM_OBSCURING_OPACITY = .8f;
    private static final long TIMEOUT_MS = 3000L;
    private static final long MAX_ANIMATION_DURATION_MS = 3000L;
    private static final long ANIMATION_DURATION_TOLERANCE_MS = 500L;

    private static final int OVERLAY_COLOR = 0xFFFF0000;
    private static final int ACTIVITY_COLOR = 0xFFFFFFFF;

    private static final int FEATURE_MODE_DISABLED = 0;
    private static final int FEATURE_MODE_PERMISSIVE = 1;
    private static final int FEATURE_MODE_BLOCK = 2;

    private static final String APP_SELF =
            WindowUntrustedTouchTest.class.getPackage().getName() + ".cts";
    private static final String APP_A =
            android.server.wm.second.Components.class.getPackage().getName();
    private static final String APP_B =
            android.server.wm.third.Components.class.getPackage().getName();
    private static final String WINDOW_1 = "W1";
    private static final String WINDOW_2 = "W2";

    private static final String[] APPS = {APP_A, APP_B};

    private static final String SETTING_MAXIMUM_OBSCURING_OPACITY =
            "maximum_obscuring_opacity_for_touch";

    private static SettingsSession<String> sImmersiveModeConfirmationSetting;

    private final WindowManagerStateHelper mWmState = new WindowManagerStateHelper();
    private final Map<String, FutureConnection<IUntrustedTouchTestService>> mConnections =
            new ArrayMap<>();
    private Instrumentation mInstrumentation;
    private Context mContext;
    private Resources mResources;
    private ContentResolver mContentResolver;
    private TouchHelper mTouchHelper;
    private Handler mMainHandler;
    private InputManager mInputManager;
    private WindowManager mWindowManager;
    private ActivityManager mActivityManager;
    private NotificationManager mNotificationManager;
    private TestActivity mActivity;
    private View mContainer;
    private Toast mToast;
    private float mPreviousTouchOpacity;
    private int mPreviousMode;
    private int mPreviousSawAppOp;
    private final Set<String> mSawWindowsAdded = new ArraySet<>();
    private final AtomicInteger mTouchesReceived = new AtomicInteger(0);

    @Rule
    public TestName testNameRule = new TestName();

    @Rule
    public ActivityScenarioRule<TestActivity> activityRule =
            new ActivityScenarioRule<>(TestActivity.class);

    @BeforeClass
    public static void setUpClass() {
        sImmersiveModeConfirmationSetting = new SettingsSession<>(
                Settings.Secure.getUriFor(IMMERSIVE_MODE_CONFIRMATIONS),
                Settings.Secure::getString, Settings.Secure::putString);
        sImmersiveModeConfirmationSetting.set("confirmed");
    }

    @AfterClass
    public static void tearDownClass() {
        if (sImmersiveModeConfirmationSetting != null) {
            sImmersiveModeConfirmationSetting.close();
        }
    }

    @Before
    public void setUp() throws Exception {
        ActivityOptions options = ActivityOptions.makeBasic();
        // Launch test in the fullscreen mode with navigation bar hidden,
        // in order to ensure text toast is tappable and overlays above the test app
        // on ARC++ and cf_pc devices. b/191075641.
        options.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
        activityRule.getScenario().launch(TestActivity.class, options.toBundle())
                .onActivity(activity -> {
            mActivity = activity;
            mContainer = mActivity.view;
            // On ARC++, text toast is fixed on the screen. Its position may overlays the navigation
            // bar. Hide it to ensure the text toast overlays the app. b/191075641
            mContainer.getWindowInsetsController().hide(navigationBars());
            mContainer.setOnTouchListener(this::onTouchEvent);
        });
        mInstrumentation = getInstrumentation();
        mContext = mInstrumentation.getContext();
        mResources = mContext.getResources();
        mContentResolver = mContext.getContentResolver();
        mTouchHelper = new TouchHelper(mInstrumentation, mWmState);
        mMainHandler = new Handler(Looper.getMainLooper());
        mInputManager = mContext.getSystemService(InputManager.class);
        mWindowManager = mContext.getSystemService(WindowManager.class);
        mActivityManager = mContext.getSystemService(ActivityManager.class);
        mNotificationManager = mContext.getSystemService(NotificationManager.class);

        mPreviousSawAppOp = AppOpsUtils.getOpMode(APP_SELF, OPSTR_SYSTEM_ALERT_WINDOW);
        AppOpsUtils.setOpMode(APP_SELF, OPSTR_SYSTEM_ALERT_WINDOW, MODE_ALLOWED);
        mPreviousTouchOpacity = setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
        mPreviousMode = setBlockUntrustedTouchesMode(FEATURE_MODE_BLOCK);
        SystemUtil.runWithShellPermissionIdentity(
                () -> mNotificationManager.setToastRateLimitingEnabled(false));

        pressWakeupButton();
        pressUnlockButton();
    }

    @After
    public void tearDown() throws Throwable {
        mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY);
        mTouchesReceived.set(0);
        removeOverlays();
        for (FutureConnection<IUntrustedTouchTestService> connection : mConnections.values()) {
            mContext.unbindService(connection);
        }
        mConnections.clear();
        for (String app : APPS) {
            stopPackage(app);
        }
        SystemUtil.runWithShellPermissionIdentity(
                () -> mNotificationManager.setToastRateLimitingEnabled(true));
        setBlockUntrustedTouchesMode(mPreviousMode);
        setMaximumObscuringOpacityForTouch(mPreviousTouchOpacity);
        AppOpsUtils.setOpMode(APP_SELF, OPSTR_SYSTEM_ALERT_WINDOW, mPreviousSawAppOp);
    }

    @Test
    public void testWhenFeatureInDisabledModeAndActivityWindowAbove_allowsTouch()
            throws Throwable {
        setBlockUntrustedTouchesMode(FEATURE_MODE_DISABLED);
        addActivityOverlay(APP_A, /* opacity */ .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenFeatureInPermissiveModeAndActivityWindowAbove_allowsTouch()
            throws Throwable {
        setBlockUntrustedTouchesMode(FEATURE_MODE_PERMISSIVE);
        addActivityOverlay(APP_A, /* opacity */ .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenFeatureInBlockModeAndActivityWindowAbove_blocksTouch()
            throws Throwable {
        setBlockUntrustedTouchesMode(FEATURE_MODE_BLOCK);
        addActivityOverlay(APP_A, /* opacity */ .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testMaximumObscuringOpacity() throws Throwable {
        // Setting the previous value since we override this on setUp()
        setMaximumObscuringOpacityForTouch(mPreviousTouchOpacity);

        assertEquals(0.8f, mInputManager.getMaximumObscuringOpacityForTouch());
    }

    @Test
    public void testAfterSettingThreshold_returnsThresholdSet()
            throws Throwable {
        float threshold = .123f;
        setMaximumObscuringOpacityForTouch(threshold);

        assertEquals(threshold, mInputManager.getMaximumObscuringOpacityForTouch());
    }

    @Test
    public void testAfterSettingFeatureMode_returnsModeSet()
            throws Throwable {
        // Make sure the previous mode is different
        setBlockUntrustedTouchesMode(FEATURE_MODE_BLOCK);
        assertEquals(FEATURE_MODE_BLOCK, mInputManager.getBlockUntrustedTouchesMode(mContext));
        setBlockUntrustedTouchesMode(FEATURE_MODE_PERMISSIVE);

        assertEquals(FEATURE_MODE_PERMISSIVE, mInputManager.getBlockUntrustedTouchesMode(mContext));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testAfterSettingThresholdLessThan0_throws() throws Throwable {
        setMaximumObscuringOpacityForTouch(-.5f);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testAfterSettingThresholdGreaterThan1_throws() throws Throwable {
        setMaximumObscuringOpacityForTouch(1.5f);
    }

    /** This is testing what happens if setting is overridden manually */
    @Test
    public void testAfterSettingThresholdGreaterThan1ViaSettings_previousThresholdIsUsed()
            throws Throwable {
        setMaximumObscuringOpacityForTouch(.8f);
        assertEquals(.8f, mInputManager.getMaximumObscuringOpacityForTouch());
        SystemUtil.runWithShellPermissionIdentity(() -> {
            Settings.Global.putFloat(mContentResolver, SETTING_MAXIMUM_OBSCURING_OPACITY, 1.5f);
        });
        addSawOverlay(APP_A, WINDOW_1, 9.f);

        mTouchHelper.tapOnViewCenter(mContainer);

        // Blocks because it's using previous maximum of .8
        assertTouchNotReceived();
    }

    /** This is testing what happens if setting is overridden manually */
    @Test
    public void testAfterSettingThresholdLessThan0ViaSettings_previousThresholdIsUsed()
            throws Throwable {
        setMaximumObscuringOpacityForTouch(.8f);
        assertEquals(.8f, mInputManager.getMaximumObscuringOpacityForTouch());
        SystemUtil.runWithShellPermissionIdentity(() -> {
            Settings.Global.putFloat(mContentResolver, SETTING_MAXIMUM_OBSCURING_OPACITY, -.5f);
        });
        addSawOverlay(APP_A, WINDOW_1, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        // Allows because it's using previous maximum of .8
        assertTouchReceived();
    }

    /** SAWs */

    @Test
    public void testWhenOneSawWindowAboveThreshold_allowsTouch() throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        // Opacity will be automatically capped and touches will pass through.
        assertTouchReceived();
    }

    @Test
    public void testWhenOneSawWindowBelowThreshold_allowsTouch() throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenOneSawWindowWithZeroOpacity_allowsTouch() throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, 0f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenOneSawWindowAtThreshold_allowsTouch() throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, MAXIMUM_OBSCURING_OPACITY);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenTwoSawWindowsFromSameAppTogetherBelowThreshold_allowsTouch()
            throws Throwable {
        // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
        addSawOverlay(APP_A, WINDOW_1, .5f);
        addSawOverlay(APP_A, WINDOW_2, .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenTwoSawWindowsFromSameAppTogetherAboveThreshold_blocksTouch()
            throws Throwable {
        // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
        addSawOverlay(APP_A, WINDOW_1, .7f);
        addSawOverlay(APP_A, WINDOW_2, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenTwoSawWindowsFromDifferentAppsEachBelowThreshold_allowsTouch()
            throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .7f);
        addSawOverlay(APP_B, WINDOW_2, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenOneSawWindowAboveThresholdAndSelfSawWindow_allowsTouch()
            throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .9f);
        addSawOverlay(APP_SELF, WINDOW_1, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        // Opacity will be automatically capped and touches will pass through.
        assertTouchReceived();
    }

    @Test
    public void testWhenOneSawWindowBelowThresholdAndSelfSawWindow_allowsTouch()
            throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .7f);
        addSawOverlay(APP_SELF, WINDOW_1, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenTwoSawWindowsTogetherBelowThresholdAndSelfSawWindow_allowsTouch()
            throws Throwable {
        // Resulting opacity for A = 1 - (1 - 0.5)*(1 - 0.5) = .75
        addSawOverlay(APP_A, WINDOW_1, .5f);
        addSawOverlay(APP_A, WINDOW_1, .5f);
        addSawOverlay(APP_SELF, WINDOW_1, .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenThresholdIs0AndSawWindowAtThreshold_allowsTouch()
            throws Throwable {
        setMaximumObscuringOpacityForTouch(0);
        addSawOverlay(APP_A, WINDOW_1, 0);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenThresholdIs0AndSawWindowAboveThreshold_allowsTouch()
            throws Throwable {
        setMaximumObscuringOpacityForTouch(0);
        addSawOverlay(APP_A, WINDOW_1, .1f);

        mTouchHelper.tapOnViewCenter(mContainer);

        // Opacity will be automatically capped and touches will pass through.
        assertTouchReceived();
    }

    @Test
    public void testWhenThresholdIs1AndSawWindowAtThreshold_allowsTouch()
            throws Throwable {
        setMaximumObscuringOpacityForTouch(1);
        addSawOverlay(APP_A, WINDOW_1, 1);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenThresholdIs1AndSawWindowBelowThreshold_allowsTouch()
            throws Throwable {
        setMaximumObscuringOpacityForTouch(1);
        addSawOverlay(APP_A, WINDOW_1, .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    /** Activity windows */

    @Test
    public void testWhenOneActivityWindowBelowThreshold_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowAboveThreshold_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowWithZeroOpacity_allowsTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ 0f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenOneActivityWindowWithMinPositiveOpacity_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ MIN_POSITIVE_OPACITY);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowWithSmallOpacity_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .01f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneSelfActivityWindow_allowsTouch() throws Throwable {
        addActivityOverlay(APP_SELF, /* opacity */ .9f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenTwoActivityWindowsFromDifferentAppsTogetherBelowThreshold_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .7f);
        addActivityOverlay(APP_B, /* opacity */ .7f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowAndOneSawWindowTogetherBelowThreshold_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .5f);
        addSawOverlay(APP_A, WINDOW_1, .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowAndOneSelfCustomToastWindow_blocksTouch()
            throws Throwable {
        // Toast has to be before otherwise it would be blocked from background
        addToastOverlay(APP_SELF, /* custom */ true);
        addActivityOverlay(APP_A, /* opacity */ .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowAndOneSelfSawWindow_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .5f);
        addSawOverlay(APP_SELF, WINDOW_1, .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowAndOneSawWindowBelowThreshold_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .5f);
        addSawOverlay(APP_A, WINDOW_1, .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneActivityWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch()
            throws Throwable {
        addActivityOverlay(APP_A, /* opacity */ .5f);
        addSawOverlay(APP_B, WINDOW_1, .5f);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    /** Activity-type child windows on same activity */

    @Test
    public void testWhenActivityChildWindowWithSameTokenFromDifferentApp_allowsTouch()
            throws Exception {
        IBinder token = mActivity.getWindow().getAttributes().token;
        addActivityChildWindow(APP_A, WINDOW_1, token);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenActivityChildWindowWithDifferentTokenFromDifferentApp_blocksTouch()
            throws Exception {
        // Creates a new activity with 0 opacity
        BlockingResultReceiver receiver = new BlockingResultReceiver();
        addActivityOverlay(APP_A, /* opacity */ 0f, receiver);
        // Verify it allows touches
        mTouchHelper.tapOnViewCenter(mContainer);
        assertTouchReceived();
        // Now get its token and put a child window from another app with it
        IBinder token = receiver.getData(TIMEOUT_MS).getBinder(EXTRA_TOKEN);
        addActivityChildWindow(APP_B, WINDOW_1, token);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenActivityChildWindowWithDifferentTokenFromSameApp_allowsTouch()
            throws Exception {
        // Creates a new activity with 0 opacity
        BlockingResultReceiver receiver = new BlockingResultReceiver();
        addActivityOverlay(APP_A, /* opacity */ 0f, receiver);
        // Now get its token and put a child window owned by us
        IBinder token = receiver.getData(TIMEOUT_MS).getBinder(EXTRA_TOKEN);
        addActivityChildWindow(APP_SELF, WINDOW_1, token);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    /** Activity transitions */

    @Test
    public void testLongEnterAnimations_areLimited() {
        long durationSet = mResources.getInteger(R.integer.long_animation_duration);
        assertThat(durationSet).isGreaterThan(
                MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS);
        addAnimatedActivityOverlay(APP_A, /* touchable */ false, R.anim.long_alpha_0_7,
                R.anim.long_alpha_1);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));
        long start = SystemClock.elapsedRealtime();

        assertTrue(mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY));
        long duration = SystemClock.elapsedRealtime() - start;
        assertThat(duration).isAtMost(MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS);
    }

    @Test
    public void testLongExitAnimations_areLimited() {
        long durationSet = mResources.getInteger(R.integer.long_animation_duration);
        assertThat(durationSet).isGreaterThan(
                MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS);
        addExitAnimationActivity(APP_A);
        sendFinishToExitAnimationActivity(APP_A,
                Components.ExitAnimationActivityReceiver.EXTRA_VALUE_LONG_ANIMATION_0_7);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));
        long start = SystemClock.elapsedRealtime();

        assertTrue(mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY));
        long duration = SystemClock.elapsedRealtime() - start;
        assertThat(duration).isAtMost(MAX_ANIMATION_DURATION_MS + ANIMATION_DURATION_TOLERANCE_MS);
    }

    @Test
    public void testWhenEnterAnimationAboveThresholdAndNewActivityNotTouchable_blocksTouch() {
        addAnimatedActivityOverlay(APP_A, /* touchable */ false, R.anim.alpha_0_9, R.anim.alpha_1);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));

        mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false);

        assertAnimationRunning();
        assertTouchNotReceived();
    }

    @Test
    public void testWhenEnterAnimationBelowThresholdAndNewActivityNotTouchable_allowsTouch() {
        addAnimatedActivityOverlay(APP_A, /* touchable */ false, R.anim.alpha_0_7, R.anim.alpha_1);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));

        mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false);

        assertAnimationRunning();
        assertTouchReceived();
    }

    @Test
    public void testWhenEnterAnimationBelowThresholdAndNewActivityTouchable_blocksTouch() {
        addAnimatedActivityOverlay(APP_A, /* touchable */ true, R.anim.alpha_0_7, R.anim.alpha_1);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));

        mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false);

        assertAnimationRunning();
        assertTouchNotReceived();
    }

    @Test
    public void testWhenExitAnimationBelowThreshold_allowsTouch() {
        addExitAnimationActivity(APP_A);
        sendFinishToExitAnimationActivity(APP_A,
                Components.ExitAnimationActivityReceiver.EXTRA_VALUE_ANIMATION_0_7);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));

        mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false);

        assertAnimationRunning();
        assertTouchReceived();
    }

    @Test
    public void testWhenExitAnimationAboveThreshold_blocksTouch() {
        addExitAnimationActivity(APP_A);
        sendFinishToExitAnimationActivity(APP_A,
                Components.ExitAnimationActivityReceiver.EXTRA_VALUE_ANIMATION_0_9);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));

        mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false);

        assertAnimationRunning();
        assertTouchNotReceived();
    }

    @Test
    public void testWhenExitAnimationAboveThresholdFromSameUid_allowsTouch() {
        addExitAnimationActivity(APP_SELF);
        sendFinishToExitAnimationActivity(APP_SELF,
                Components.ExitAnimationActivityReceiver.EXTRA_VALUE_ANIMATION_0_9);
        assertTrue(mWmState.waitForAppTransitionRunningOnDisplay(Display.DEFAULT_DISPLAY));

        mTouchHelper.tapOnViewCenter(mContainer, /* waitAnimations*/ false);

        assertAnimationRunning();
        assertTouchReceived();
    }

    /** Toast windows */

    @Test
    public void testWhenSelfTextToastWindow_allowsTouch() throws Throwable {
        addToastOverlay(APP_SELF, /* custom */ false);
        Rect toast = mWmState.waitForResult("toast bounds",
                state -> state.findFirstWindowWithType(LayoutParams.TYPE_TOAST).getFrame());

        mTouchHelper.tapOnCenter(toast, mActivity.getDisplayId());

        assertTouchReceived();
    }

    @Test
    public void testWhenTextToastWindow_allowsTouch() throws Throwable {
        addToastOverlay(APP_A, /* custom */ false);
        Rect toast = mWmState.waitForResult("toast bounds",
                state -> state.findFirstWindowWithType(LayoutParams.TYPE_TOAST).getFrame());

        mTouchHelper.tapOnCenter(toast, mActivity.getDisplayId());

        assertTouchReceived();
    }

    @Test
    public void testWhenOneCustomToastWindow_blocksTouch() throws Throwable {
        addToastOverlay(APP_A, /* custom */ true);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneSelfCustomToastWindow_allowsTouch() throws Throwable {
        addToastOverlay(APP_SELF, /* custom */ true);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    @Test
    public void testWhenOneCustomToastWindowAndOneSelfSawWindow_blocksTouch()
            throws Throwable {
        addSawOverlay(APP_SELF, WINDOW_1, .9f);
        addToastOverlay(APP_A, /* custom */ true);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneCustomToastWindowAndOneSawWindowBelowThreshold_blocksTouch()
            throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .5f);
        addToastOverlay(APP_A, /* custom */ true);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneCustomToastWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch()
            throws Throwable {
        addSawOverlay(APP_A, WINDOW_1, .5f);
        addToastOverlay(APP_B, /* custom */ true);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchNotReceived();
    }

    @Test
    public void testWhenOneSelfCustomToastWindowOneSelfActivityWindowAndOneSawBelowThreshold_allowsTouch()
            throws Throwable {
        addActivityOverlay(APP_SELF, /* opacity */ .9f);
        addSawOverlay(APP_A, WINDOW_1, .5f);
        addToastOverlay(APP_SELF, /* custom */ true);

        mTouchHelper.tapOnViewCenter(mContainer);

        assertTouchReceived();
    }

    private boolean onTouchEvent(View view, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mTouchesReceived.incrementAndGet();
        }
        return true;
    }

    private void assertTouchReceived() {
        mInstrumentation.waitForIdleSync();
        assertThat(mTouchesReceived.get()).isEqualTo(1);
        mTouchesReceived.set(0);
    }

    private void assertTouchNotReceived() {
        mInstrumentation.waitForIdleSync();
        assertThat(mTouchesReceived.get()).isEqualTo(0);
        mTouchesReceived.set(0);
    }

    private void assertAnimationRunning() {
        assertThat(mWmState.getDisplay(Display.DEFAULT_DISPLAY).getAppTransitionState()).isEqualTo(
                WindowManagerStateHelper.APP_STATE_RUNNING);
    }

    private void addToastOverlay(String packageName, boolean custom) throws Exception {
        // Making sure there are no toasts currently since we can only check for the presence of
        // *any* toast afterwards and we don't want to be in a situation where this method returned
        // because another toast was being displayed.
        waitForNoToastOverlays();
        if (custom) {
            if (packageName.equals(APP_SELF)) {
                // We add the custom toast here because we already have foreground status due to
                // the activity rule, so no need to start another activity.
                addMyCustomToastOverlay();
            } else {
                // We have to use an activity that will display the toast then finish itself because
                // custom toasts cannot be posted from the background.
                Intent intent = new Intent();
                intent.setComponent(repackage(packageName, Components.ToastActivity.COMPONENT));
                mActivity.startActivity(intent);
            }
        } else {
            getService(packageName).showToast();
        }
        String message = "Toast from app " + packageName + " did not appear on time";
        // TODO: WindowStateProto does not have package/UID information from the window, the current
        //  package test relies on the window name, which is not how toast windows are named. We
        //  should ideally incorporate that information in WindowStateProto and use here.
        if (!mWmState.waitFor("toast window", this::hasVisibleToast)) {
            fail(message);
        }
    }

    private boolean hasVisibleToast(WindowManagerState state) {
        return !state.getMatchingWindowType(LayoutParams.TYPE_TOAST).isEmpty()
                && state.findFirstWindowWithType(LayoutParams.TYPE_TOAST).isSurfaceShown();
    }

    private void addMyCustomToastOverlay() {
        mActivity.runOnUiThread(() -> {
            mToast = new Toast(mContext);
            View view = new View(mContext);
            view.setBackgroundColor(OVERLAY_COLOR);
            mToast.setView(view);
            mToast.setGravity(Gravity.FILL, 0, 0);
            mToast.setDuration(Toast.LENGTH_LONG);
            mToast.show();
        });
        mInstrumentation.waitForIdleSync();
    }

    private void removeMyCustomToastOverlay() {
        mActivity.runOnUiThread(() -> {
            if (mToast != null) {
                mToast.cancel();
                mToast = null;
            }
        });
        mInstrumentation.waitForIdleSync();
    }

    private void waitForNoToastOverlays() {
        waitForNoToastOverlays("Toast windows did not hide on time");
    }

    private void waitForNoToastOverlays(String message) {
        if (!mWmState.waitFor("no toast windows",
                state -> state.getMatchingWindowType(LayoutParams.TYPE_TOAST).isEmpty())) {
            fail(message);
        }
    }

    private void addExitAnimationActivity(String packageName) {
        // This activity responds to broadcasts to exit with animations and it's opaque (translucent
        // activities don't honor custom exit animations).
        addActivity(repackage(packageName, Components.ExitAnimationActivity.COMPONENT),
                /* extras */ null, /* options */ null);
    }

    private void sendFinishToExitAnimationActivity(String packageName, int exitAnimation) {
        Intent intent = new Intent(Components.ExitAnimationActivityReceiver.ACTION_FINISH);
        intent.setPackage(packageName);
        intent.putExtra(Components.ExitAnimationActivityReceiver.EXTRA_ANIMATION, exitAnimation);
        mContext.sendBroadcast(intent);
    }

    private void addAnimatedActivityOverlay(String packageName, boolean touchable,
            @AnimRes int enterAnim, @AnimRes int exitAnim) {
        ConditionVariable animationsStarted = new ConditionVariable(false);
        ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, enterAnim, exitAnim,
                mMainHandler, animationsStarted::open, /* finishedListener */ null);
        // We're testing the opacity coming from the animation here, not the one declared in the
        // activity, so we set its opacity to 1
        addActivityOverlay(packageName, /* opacity */ 1, touchable, options.toBundle());
        animationsStarted.block();
    }

    private void addActivityChildWindow(String packageName, String windowSuffix, IBinder token)
            throws Exception {
        String name = getWindowName(packageName, windowSuffix);
        getService(packageName).showActivityChildWindow(name, token);
        if (!mWmState.waitFor("activity child window " + name,
                state -> state.isWindowVisible(name) && state.isWindowSurfaceShown(name))) {
            fail("Activity child window " + name + " did not appear on time");
        }
    }

    private void addActivityOverlay(String packageName, float opacity) {
        addActivityOverlay(packageName, opacity, /* touchable */ false, /* options */ null);
    }

    private void addActivityOverlay(String packageName, float opacity, boolean touchable,
            @Nullable Bundle options) {
        Bundle extras = new Bundle();
        extras.putFloat(Components.OverlayActivity.EXTRA_OPACITY, opacity);
        extras.putBoolean(Components.OverlayActivity.EXTRA_TOUCHABLE, touchable);
        addActivityOverlay(packageName, extras, options);
    }

    private void addActivityOverlay(String packageName, float opacity,
            BlockingResultReceiver tokenReceiver) {
        Bundle extras = new Bundle();
        extras.putFloat(Components.OverlayActivity.EXTRA_OPACITY, opacity);
        extras.putParcelable(Components.OverlayActivity.EXTRA_TOKEN_RECEIVER, tokenReceiver);
        addActivityOverlay(packageName, extras, /* options */ null);
    }

    private void addActivityOverlay(String packageName, @Nullable Bundle extras,
            @Nullable Bundle options) {
        addActivity(repackage(packageName, Components.OverlayActivity.COMPONENT), extras, options);
    }

    private void addActivity(ComponentName component, @Nullable Bundle extras,
            @Nullable Bundle options) {
        Intent intent = new Intent();
        intent.setComponent(component);
        if (extras != null) {
            intent.putExtras(extras);
        }
        mActivity.startActivity(intent, options);
        String packageName = component.getPackageName();
        String activity = ComponentNameUtils.getActivityName(component);
        if (!mWmState.waitFor("activity window " + activity,
                state -> activity.equals(state.getFocusedActivity())
                        && state.hasActivityState(component, STATE_RESUMED))) {
            fail("Activity from app " + packageName + " did not appear on time");
        }
    }

    private void removeActivityOverlays() {
        Intent intent = new Intent(mContext, mActivity.getClass());
        // Will clear any activity on top of it and it will become the new top
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        mActivity.startActivity(intent);
    }

    private void waitForNoActivityOverlays(String message) {
        // Base activity focused means no activities on top
        ComponentName component = mActivity.getComponentName();
        String name = ComponentNameUtils.getActivityName(component);
        if (!mWmState.waitFor("test rule activity focused",
                state -> name.equals(state.getFocusedActivity())
                        && state.hasActivityState(component, STATE_RESUMED))) {
            fail(message);
        }
    }

    private void addSawOverlay(String packageName, String windowSuffix, float opacity)
            throws Throwable {
        String name = getWindowName(packageName, windowSuffix);
        getService(packageName).showSystemAlertWindow(name, opacity);
        mSawWindowsAdded.add(name);
        if (!mWmState.waitFor("saw window " + name,
                state -> state.isWindowVisible(name) && state.isWindowSurfaceShown(name))) {
            fail("Saw window " + name + " did not appear on time");
        }
    }

    private void waitForNoSawOverlays(String message) {
        if (!mWmState.waitFor("no SAW windows",
                state -> mSawWindowsAdded.stream().allMatch(w -> !state.isWindowVisible(w)))) {
            fail(message);
        }
        mSawWindowsAdded.clear();
    }

    private void removeOverlays() throws Throwable {
        for (FutureConnection<IUntrustedTouchTestService> connection : mConnections.values()) {
            connection.getCurrent().removeOverlays();
        }
        // We need to stop the app because not every overlay is created via the service (eg.
        // activity overlays and custom toasts)
        for (String app : APPS) {
            stopPackage(app);
        }
        waitForNoSawOverlays("SAWs not removed on time");
        removeActivityOverlays();
        waitForNoActivityOverlays("Activities not removed on time");
        removeMyCustomToastOverlay();
        waitForNoToastOverlays("Toasts not removed on time");
    }

    private void stopPackage(String packageName) {
        SystemUtil.runWithShellPermissionIdentity(
                () -> mActivityManager.forceStopPackage(packageName));
    }

    private int setBlockUntrustedTouchesMode(int mode) throws Exception {
        return SystemUtil.callWithShellPermissionIdentity(() -> {
            int previous = mInputManager.getBlockUntrustedTouchesMode(mContext);
            mInputManager.setBlockUntrustedTouchesMode(mContext, mode);
            return previous;
        });
    }

    private float setMaximumObscuringOpacityForTouch(float opacity) throws Exception {
        return SystemUtil.callWithShellPermissionIdentity(() -> {
            float previous = mInputManager.getMaximumObscuringOpacityForTouch();
            mInputManager.setMaximumObscuringOpacityForTouch(opacity);
            return previous;
        });
    }

    private IUntrustedTouchTestService getService(String packageName) throws Exception {
        return mConnections.computeIfAbsent(packageName, this::connect).get(TIMEOUT_MS);
    }

    private FutureConnection<IUntrustedTouchTestService> connect(String packageName) {
        FutureConnection<IUntrustedTouchTestService> connection =
                new FutureConnection<>(IUntrustedTouchTestService.Stub::asInterface);
        Intent intent = new Intent();
        intent.setComponent(repackage(packageName, Components.UntrustedTouchTestService.COMPONENT));
        assertTrue(mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE));
        return connection;
    }

    private static String getWindowName(String packageName, String windowSuffix) {
        return packageName + "." + windowSuffix;
    }

    private static ComponentName repackage(String packageName, ComponentName baseComponent) {
        return new ComponentName(packageName, baseComponent.getClassName());
    }

    public static class TestActivity extends Activity {
        public View view;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            view = new View(this);
            view.setBackgroundColor(ACTIVITY_COLOR);
            setContentView(view);
        }
    }
}
