Snap for 6492800 from 2037d945ae73b09724c447df48f0fcca2afeeb55 to rvc-release

Change-Id: I6bc60314a53df968cbe61846cb183b4775d54d37
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableFeatureConsistentTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableFeatureConsistentTest.java
deleted file mode 100644
index 48fddc7..0000000
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableFeatureConsistentTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.appsecurity.cts;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import static android.appsecurity.cts.AdoptableHostTest.FEATURE_ADOPTABLE_STORAGE;
-import android.platform.test.annotations.AppModeFull;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Set of tests that verify behavior of adopted storage media's consistency between the feature
- * flag and what we sniffed from the underlying fstab.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-@AppModeFull(reason = "Instant applications can only be installed on internal storage")
-public class AdoptableFeatureConsistentTest extends BaseHostJUnit4Test {
-
-    private String mHasAdoptable;
-
-    @Before
-    public void setUp() throws Exception {
-        // Caches the initial state of adoptable feature to restore after the tests
-        mHasAdoptable = getDevice().executeShellCommand("sm has-adoptable").trim();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        // Restores the initial cache value
-        getDevice().executeShellCommand("sm set-force-adoptable" + mHasAdoptable);
-    }
-
-    @Test
-    public void testFeatureTrue() throws Exception {
-        getDevice().executeShellCommand("sm set-force-adoptable true");
-        checkConsistency();
-    }
-
-    @Test
-    public void testFeatureFalse() throws Exception {
-        getDevice().executeShellCommand("sm set-force-adoptable false");
-        checkConsistency();
-    }
-
-    private void checkConsistency() throws Exception {
-        // Reboots the device and blocks until the boot complete flag is set.
-        getDevice().rebootUntilOnline();
-        assertTrue("Device failed to boot", getDevice().waitForBootComplete(120000));
-
-        final boolean hasFeature = getDevice().hasFeature(FEATURE_ADOPTABLE_STORAGE);
-        final boolean hasFstab = Boolean.parseBoolean(getDevice()
-                .executeShellCommand("sm has-adoptable").trim());
-        if (hasFeature != hasFstab) {
-            fail("Inconsistent adoptable storage status; feature claims " + hasFeature
-                    + " but fstab claims " + hasFstab);
-        }
-    }
-}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 7717623..927f9f5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -51,7 +51,6 @@
 
     public static final String FEATURE_ADOPTABLE_STORAGE = "feature:android.software.adoptable_storage";
 
-    private boolean mHasAdoptableInitialState;
     private String mListVolumesInitialState;
 
     @Before
@@ -59,16 +58,12 @@
         // Start all possible users to make sure their storage is unlocked
         Utils.prepareMultipleUsers(getDevice(), Integer.MAX_VALUE);
 
+        // Users are starting, wait for all volumes are ready
+        waitForVolumeReady();
+
         // Initial state of all volumes
         mListVolumesInitialState = getDevice().executeShellCommand("sm list-volumes");
 
-        // TODO(b/146491109): Revert this change before shipping and find long-term solution.
-        // Caches the initial state of adoptable feature and sets it to true (if not already set)
-        mHasAdoptableInitialState = Boolean.parseBoolean(
-                getDevice().executeShellCommand("sm has-adoptable").trim());
-        if (!mHasAdoptableInitialState) {
-            setForceAdoptable();
-        }
         getDevice().uninstallPackage(PKG);
 
         // Enable a virtual disk to give us the best shot at being able to pass
@@ -123,9 +118,19 @@
                 CLog.w("Volume state is not recovered: " + result);
             }
         }
-        // Restores the initial cache value (if it is different)
-        if (!mHasAdoptableInitialState) {
-            getDevice().executeShellCommand("sm set-force-adoptable false");
+    }
+
+    /**
+     * Ensure that we have consistency between the feature flag and what we
+     * sniffed from the underlying fstab.
+     */
+    @Test
+    public void testFeatureConsistent() throws Exception {
+        final boolean hasFeature = hasFeature();
+        final boolean hasFstab = hasFstab();
+        if (hasFeature != hasFstab) {
+            fail("Inconsistent adoptable storage status; feature claims " + hasFeature
+                    + " but fstab claims " + hasFstab);
         }
     }
 
@@ -134,7 +139,7 @@
         int attempt = 0;
         boolean noCheckingEjecting = false;
         String result = "";
-        while (!noCheckingEjecting && attempt++ < 20) {
+        while (!noCheckingEjecting && attempt++ < 60) {
             result = getDevice().executeShellCommand("sm list-volumes");
             noCheckingEjecting = !result.contains("ejecting") && !result.contains("checking");
             Thread.sleep(100);
@@ -216,18 +221,6 @@
         }
     }
 
-    private void setForceAdoptable() throws Exception {
-        getDevice().executeShellCommand("sm set-force-adoptable true");
-        int attempt = 0;
-        boolean hasAdoptable = false;
-        while (!hasAdoptable && attempt++ < 5) {
-            Thread.sleep(1000);
-            hasAdoptable = Boolean.parseBoolean(getDevice()
-                    .executeShellCommand("sm has-adoptable").trim());
-        }
-        assertTrue(hasAdoptable);
-    }
-
     private void verifyPrimaryInternal(String diskId) throws Exception {
         // Write some data to shared storage
         new InstallMultiple().addFile(APK).run();
@@ -255,6 +248,7 @@
         runDeviceTests(PKG, CLASS, "testPrimaryUnmounted");
         getDevice().executeShellCommand("sm mount " + vol.volId);
         waitForInstrumentationReady();
+        waitForVolumeReady();
 
         runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
         runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
@@ -305,6 +299,7 @@
         runDeviceTests(PKG, CLASS, "testPrimaryUnmounted");
         getDevice().executeShellCommand("sm mount " + vol.volId);
         waitForInstrumentationReady();
+        waitForVolumeReady();
 
         runDeviceTests(PKG, CLASS, "testPrimaryAdopted");
         runDeviceTests(PKG, CLASS, "testPrimaryDataRead");
@@ -375,6 +370,7 @@
             // Kick through a remount cycle, which should purge the adopted app
             getDevice().executeShellCommand("sm mount " + vol.volId);
             waitForInstrumentationReady();
+            waitForVolumeReady();
 
             runDeviceTests(PKG, CLASS, "testDataInternal");
             boolean didThrow = false;
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
index 620fed1..ee3a683 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
@@ -188,6 +188,18 @@
         mDevice.waitForIdle();
     }
 
+    private String replacePackageAWithPackageB(String path) {
+        return path.replace(mContext.getPackageName(), APPB_PKG);
+    }
+
+    private void testCanNotAccessAppBExternalDirs() {
+        String appBExternalDir = replacePackageAWithPackageB(
+                mContext.getExternalFilesDir("").getParentFile().getAbsolutePath());
+        String appBObbDir = replacePackageAWithPackageB(mContext.getObbDir().getAbsolutePath());
+        assertDirDoesNotExist(appBExternalDir);
+        assertDirDoesNotExist(appBObbDir);
+    }
+
     @Test
     public void testAppAUnlockDeviceAndVerifyCeDeExternalDataExist() throws Exception {
 
@@ -221,5 +233,9 @@
         testAppAExternalDirsDoExist();
         testAppACurProfileDataAccessible();
         testAppARefProfileDataNotAccessible();
+
+        // Verify after unlocking device, app a has still no access to app b dir.
+        testCannotAccessAppBDataDir();
+        testCanNotAccessAppBExternalDirs();
     }
 }
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java
index 0f069af..c1e3a53 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppB/src/com/android/cts/appdataisolation/appb/AppBTests.java
@@ -65,7 +65,7 @@
     @Test
     public void testCanNotAccessAppAExternalDirs() {
         String appAExternalDir = replacePackageBWithPackageA(
-                mContext.getExternalFilesDir("").getAbsolutePath());
+                mContext.getExternalFilesDir("").getParentFile().getAbsolutePath());
         String appAObbDir = replacePackageBWithPackageA(mContext.getObbDir().getAbsolutePath());
         assertDirDoesNotExist(appAExternalDir);
         assertDirDoesNotExist(appAObbDir);
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
index 25727f1..8bce302 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
@@ -839,9 +839,6 @@
     private static final int NETWORK_TIMEOUT_MILLIS = 15000;
     private static final String HTTPS_HOST_URL =
             "https://connectivitycheck.gstatic.com/generate_204";
-    // Minimum and Maximum of iterations of exercise host, @see #doGenerateNetworkTraffic.
-    private static final int MIN_EXERCISE_HOST_ITERATIONS = 1;
-    private static final int MAX_EXERCISE_HOST_ITERATIONS = 19;
 
     private void doGenerateNetworkTraffic(@NonNull Context context,
             @NetworkCapabilities.Transport int transport) throws InterruptedException {
@@ -862,45 +859,9 @@
 
         final long startTime = SystemClock.elapsedRealtime();
         try {
-            // Since history of network stats only have 2 hours of resolution, when it is
-            // being queried, service will assume that history network stats has uniform
-            // distribution and return a fraction of network stats that is originally
-            // subject to 2 hours. To be specific:
-            //    <returned network stats> = <total network stats> * <duration> / 2 hour,
-            // assuming the duration can fit in a 2 hours bucket.
-            // In the other hand, in statsd, the network stats is queried since boot,
-            // that means in order to assert non-zero packet counts, either the test should
-            // be run after enough time since boot, or the packet counts generated here
-            // should be enough. That is to say:
-            //   <total packet counts> * <up time> / 2 hour >= 1,
-            // or
-            //   iterations >= 2 hour / (<up time> * <packets per iteration>)
-            // Thus, iterations can be chosen based on the factors above to make this
-            // function generate enough packets in each direction to accommodate enough
-            // packet counts for a fraction of history bucket.
-            final double iterations = (TimeUnit.HOURS.toMillis(2) / startTime / 7);
-            // While just enough iterations are going to make the test flaky, add a 20%
-            // buffer to stabilize it and make sure it's in a reasonable range, so it won't
-            // consumes more than 100kb of traffic, or generates 0 byte of traffic.
-            final int augmentedIterations =
-                    (int) Math.max(iterations * 1.2, MIN_EXERCISE_HOST_ITERATIONS);
-            if (augmentedIterations > MAX_EXERCISE_HOST_ITERATIONS) {
-                throw new IllegalStateException("Exceeded max allowed iterations"
-                        + ", iterations=" + augmentedIterations
-                        + ", uptime=" + TimeUnit.MILLISECONDS.toSeconds(startTime) + "s");
-            }
-
-            for (int i = 0; i < augmentedIterations; i++) {
-                // By observing results of "dumpsys netstats --uid", typically the single
-                // run of the https request below generates 4200/1080 rx/tx bytes with
-                // around 7/9 rx/tx packets.
-                // This blocks the thread of NetworkCallback, thus no other event
-                // can be processed before return.
-                exerciseRemoteHost(cm, network, new URL(HTTPS_HOST_URL));
-            }
+            exerciseRemoteHost(cm, network, new URL(HTTPS_HOST_URL));
             Log.i(TAG, "exerciseRemoteHost successful in " + (SystemClock.elapsedRealtime()
-                    - startTime) + " ms with iterations=" + augmentedIterations
-                    + ", uptime=" + TimeUnit.MILLISECONDS.toSeconds(startTime) + "s");
+                    - startTime) + " ms");
         } catch (Exception e) {
             Log.e(TAG, "exerciseRemoteHost failed in " + (SystemClock.elapsedRealtime()
                     - startTime) + " ms: " + e);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
index 6d7d95c..3551205 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/IdleConstraintTest.java
@@ -45,12 +45,19 @@
     private JobInfo.Builder mBuilder;
     private UiDevice mUiDevice;
 
+    private String mInitialDisplayTimeout;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
         mBuilder = new JobInfo.Builder(STATE_JOB_ID, kJobServiceComponent);
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+        // Make sure the screen doesn't turn off when the test turns it on.
+        mInitialDisplayTimeout = mUiDevice.executeShellCommand(
+                "settings get system screen_off_timeout");
+        mUiDevice.executeShellCommand("settings put system screen_off_timeout 300000");
     }
 
     @Override
@@ -58,7 +65,12 @@
         mJobScheduler.cancel(STATE_JOB_ID);
         // Put device back in to normal operation.
         toggleScreenOn(true);
-        setCarMode(false);
+        if (isCarModeSupported()) {
+            setCarMode(false);
+        }
+
+        mUiDevice.executeShellCommand(
+                "settings put system screen_off_timeout " + mInitialDisplayTimeout);
 
         super.tearDown();
     }
@@ -153,6 +165,12 @@
         verifyActiveState();
     }
 
+    private boolean isCarModeSupported() {
+        // TVs don't support car mode.
+        return !getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_LEANBACK_ONLY);
+    }
+
     /**
      * Check if dock state is supported.
      */
@@ -227,6 +245,10 @@
      * Ensure car mode is considered active.
      */
     public void testCarModePreventsIdle() throws Exception {
+        if (!isCarModeSupported()) {
+            return;
+        }
+
         toggleScreenOn(false);
 
         setCarMode(true);
@@ -239,6 +261,10 @@
     }
 
     private void runIdleJobStartsOnlyWhenIdle() throws Exception {
+        if (!isCarModeSupported()) {
+            return;
+        }
+
         toggleScreenOn(true);
 
         kTestEnvironment.setExpectedExecutions(0);
@@ -276,6 +302,10 @@
     }
 
     public void testIdleJobStartsOnlyWhenIdle_carEndsIdle() throws Exception {
+        if (!isCarModeSupported()) {
+            return;
+        }
+
         runIdleJobStartsOnlyWhenIdle();
 
         setCarMode(true);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index a1a5b67..c065b1e 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -73,6 +73,8 @@
     private static final long POLL_INTERVAL = 500;
     private static final long DEFAULT_WAIT_TIMEOUT = 2000;
     private static final long SHELL_TIMEOUT = 3_000;
+    // TODO: mark Settings.System.SCREEN_OFF_TIMEOUT as @TestApi
+    private static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
 
     enum Bucket {
         ACTIVE,
@@ -99,6 +101,7 @@
     private boolean mInitialWiFiState;
     private boolean mInitialAirplaneModeState;
     private String mInitialJobSchedulerConstants;
+    private String mInitialDisplayTimeout;
 
     private TestAppInterface mTestAppInterface;
 
@@ -155,6 +158,10 @@
         // Make sure test jobs can run regardless of bucket.
         Settings.Global.putString(mContext.getContentResolver(),
                 Settings.Global.JOB_SCHEDULER_CONSTANTS, "min_ready_non_active_jobs_count=0");
+        // Make sure the screen doesn't turn off when the test turns it on.
+        mInitialDisplayTimeout =
+                Settings.System.getString(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT);
+        Settings.System.putString(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, "300000");
     }
 
     @Test
@@ -480,6 +487,9 @@
         mUiDevice.executeShellCommand(
                 "cmd jobscheduler reset-execution-quota -u " + UserHandle.myUserId()
                         + " " + TEST_APP_PACKAGE);
+
+        Settings.System.putString(
+                mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, mInitialDisplayTimeout);
     }
 
     private void setTestPackageRestricted(boolean restricted) throws Exception {
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 5a8e337..ff2fed4 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -89,6 +89,19 @@
             android:screenOrientation="locked"/>
 
         <service
+            android:name=".StubSystemActionsAccessibilityService"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" />
+                <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/stub_system_actions_a11y_service" />
+        </service>
+
+        <service
                 android:name=".StubGestureAccessibilityService"
                 android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
             <intent-filter>
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index 73ffb68..7b6be1e 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -147,6 +147,8 @@
 
     <string name="foo_bar_baz">Foo bar baz.</string>
 
+    <string name="stub_system_actions_a11y_service_description">com.android.accessibilityservice.cts.StubSystemActionsAccessibilityService</string>
+
     <string name="stub_gesture_dispatch_a11y_service_description">com.android.accessibilityservice.cts.StubGestureAccessibilityService</string>
 
     <string name="stub_gesture_detector_a11y_service_description">com.android.accessibilityservice.cts.GestureDetectionStubAccessibilityService</string>
diff --git a/tests/accessibilityservice/res/xml/stub_system_actions_a11y_service.xml b/tests/accessibilityservice/res/xml/stub_system_actions_a11y_service.xml
new file mode 100644
index 0000000..e505f5f
--- /dev/null
+++ b/tests/accessibilityservice/res/xml/stub_system_actions_a11y_service.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+                       android:description="@string/stub_system_actions_a11y_service_description"
+/>
\ No newline at end of file
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySystemActionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySystemActionTest.java
new file mode 100644
index 0000000..f53f126
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySystemActionTest.java
@@ -0,0 +1,233 @@
+/*
+ * 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.accessibilityservice.cts;
+
+import static android.accessibilityservice.cts.utils.AsyncUtils.DEFAULT_TIMEOUT_MS;
+import static android.app.UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES;
+import static org.junit.Assert.fail;
+
+import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
+import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
+import android.accessibilityservice.AccessibilityService;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
+import android.app.UiAutomation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
+import android.platform.test.annotations.AppModeFull;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+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.RuleChain;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class AccessibilitySystemActionTest {
+    // intent actions to trigger system action callbacks
+    private final static String INTENT_ACTION_SYSTEM_ACTION_CALLBACK_OVERRIDE_BACK = "android.accessibility.cts.end2endtests.action.system_action_callback_override_back";
+    private final static String INTENT_ACTION_SYSTEM_ACTION_CALLBACK_NEW = "android.accessibility.cts.end2endtests.action.system_action_callback_new";
+
+    private final static int NEW_ACTION_ID = 111;
+    private final static String MANAGE_ACCESSIBILITY_PERMISSION = "android.permission.MANAGE_ACCESSIBILITY";
+
+    private static Instrumentation sInstrumentation;
+    private static UiAutomation sUiAutomation;
+
+    private Context mContext;
+    private AccessibilityManager mAccessibilityManager;
+
+    private InstrumentedAccessibilityServiceTestRule<StubSystemActionsAccessibilityService>
+            mServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
+            StubSystemActionsAccessibilityService.class, false);
+
+    private AccessibilityDumpOnFailureRule mDumpOnFailureRule =
+            new AccessibilityDumpOnFailureRule();
+
+    @Rule
+    public final RuleChain mRuleChain = RuleChain
+            .outerRule(mServiceRule)
+            .around(mDumpOnFailureRule);
+
+    StubSystemActionsAccessibilityService mService;
+
+    @BeforeClass
+    public static void oneTimeSetup() {
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+        sUiAutomation = sInstrumentation.getUiAutomation(FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
+        sUiAutomation.adoptShellPermissionIdentity(MANAGE_ACCESSIBILITY_PERMISSION);
+    }
+
+    @AfterClass
+    public static void finalTearDown() {
+        sUiAutomation.dropShellPermissionIdentity();
+        sUiAutomation.destroy();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mAccessibilityManager =
+                (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        // Start stub accessibility service.
+        mService = mServiceRule.enableService();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mService.setLatch(null);
+    }
+
+    @Test
+    @AppModeFull
+    public void testRegisterOverriddenLegacyAction() {
+        assertRegisterAction(AccessibilityService.GLOBAL_ACTION_BACK, null);
+    }
+
+    @Test
+    @AppModeFull
+    public void testUnregisterAction() {
+        assertRegisterAction(AccessibilityService.GLOBAL_ACTION_BACK, null);
+        assertUnregisterAction(AccessibilityService.GLOBAL_ACTION_BACK);
+    }
+
+    @Test
+    @AppModeFull
+    public void testNewActionInGetSystemActions() {
+        assertRegisterAction(NEW_ACTION_ID, null);
+        if (!mService.getSystemActions().contains(
+                new AccessibilityAction(NEW_ACTION_ID, null))) {
+            fail("new action should be in getSystemActions() list");
+        }
+    }
+
+
+    @Test
+    @AppModeFull
+    public void testNewActionNotInGetSystemActions() {
+        assertRegisterAction(NEW_ACTION_ID, null);
+        assertUnregisterAction(NEW_ACTION_ID);
+        if (mService.getSystemActions().contains(
+                new AccessibilityAction(NEW_ACTION_ID, null))) {
+            fail("new action should not be in getSystemActions() list");
+        }
+    }
+
+    @Test
+    @AppModeFull
+    public void testPerformOverriddenLegacyAction() {
+        assertRegisterAction(
+                AccessibilityService.GLOBAL_ACTION_BACK,
+                INTENT_ACTION_SYSTEM_ACTION_CALLBACK_OVERRIDE_BACK);
+        assertPerformGlobalAction(
+                AccessibilityService.GLOBAL_ACTION_BACK,
+                INTENT_ACTION_SYSTEM_ACTION_CALLBACK_OVERRIDE_BACK);
+    }
+
+    @Test
+    @AppModeFull
+    public void testPerformNewAction() {
+        assertRegisterAction(NEW_ACTION_ID, INTENT_ACTION_SYSTEM_ACTION_CALLBACK_NEW);
+        assertPerformGlobalAction(NEW_ACTION_ID, INTENT_ACTION_SYSTEM_ACTION_CALLBACK_NEW);
+    }
+
+    private void assertRegisterAction(int actionID, String pendingIntent) {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mService.setLatch(latch);
+        try {
+            RemoteAction r = getRemoteAction(pendingIntent);
+            mAccessibilityManager.registerSystemAction(r, actionID);
+            if (!latch.await(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                fail("did not register " + actionID);
+            }
+        } catch (InterruptedException e) {
+            fail("latch.await throws exception");
+        }
+    }
+
+    private void assertUnregisterAction(int actionID) {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mService.setLatch(latch);
+        try {
+            mAccessibilityManager.unregisterSystemAction(actionID);
+            if (!latch.await(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                fail("did not unregister " + actionID);
+            }
+        } catch (InterruptedException e) {
+            fail("latch.await throws exception");
+        }
+    }
+
+    private void assertPerformGlobalAction(int actionId, String pendingIntent) {
+        final CountDownLatch receiverLatch = new CountDownLatch(1);
+        BroadcastReceiver receiver = new SystemActionBroadcastReceiver(
+                receiverLatch,
+                pendingIntent);
+        mContext.registerReceiver(receiver, new IntentFilter(pendingIntent));
+        try {
+            mService.performGlobalAction(actionId);
+            if (!receiverLatch.await(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                fail("action not triggered; did not receive callback intent");
+            }
+        } catch (InterruptedException e) {
+            fail("latch.await throws exception");
+        } finally {
+            mContext.unregisterReceiver(receiver);
+            mAccessibilityManager.unregisterSystemAction(actionId);
+        }
+    }
+
+    private RemoteAction getRemoteAction(String pendingIntent) {
+        Intent i = new Intent(pendingIntent);
+        PendingIntent p = PendingIntent.getBroadcast(mContext, 0, i, 0);
+        return new RemoteAction(Icon.createWithContentUri("content://test"), "test1", "test1", p);
+    }
+
+    private static class SystemActionBroadcastReceiver extends BroadcastReceiver {
+        private final CountDownLatch mLatch;
+        private final String mExpectedAction;
+
+        public SystemActionBroadcastReceiver(CountDownLatch latch, String expectedAction) {
+            super();
+            mLatch = latch;
+            mExpectedAction = expectedAction;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (mExpectedAction.equals(action)) {
+                mLatch.countDown();
+            }
+        }
+    }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/StubSystemActionsAccessibilityService.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubSystemActionsAccessibilityService.java
new file mode 100644
index 0000000..b32dc8e
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubSystemActionsAccessibilityService.java
@@ -0,0 +1,37 @@
+/*
+ * 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.accessibilityservice.cts;
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService;
+import android.content.Intent;
+
+import java.util.concurrent.CountDownLatch;
+
+public class StubSystemActionsAccessibilityService  extends InstrumentedAccessibilityService {
+    private CountDownLatch latch;
+
+    @Override
+    public void onSystemActionsChanged() {
+        if  (latch != null) {
+            latch.countDown();
+        }
+    }
+
+    void setLatch(CountDownLatch latch) {
+        this.latch = latch;
+    }
+}
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index dbb3c2b..fe642c3 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -410,7 +410,7 @@
         <activity android:name="android.server.wm.StartActivityAsUserActivity"
                   android:directBootAware="true"/>
 
-        <activity android:name="android.server.wm.WindowInsetsAnimationTests$TestActivity"
+        <activity android:name="android.server.wm.WindowInsetsAnimationTestBase$TestActivity"
                   android:theme="@android:style/Theme.Material.NoActionBar" />
 
         <activity android:name="android.server.wm.ForceRelayoutTestBase$TestActivity"
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java b/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java
index 9617c7b..5e3e030 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java
@@ -29,6 +29,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.content.ComponentName;
+import android.platform.test.annotations.FlakyTest;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.server.wm.WindowManagerState.DisplayContent;
@@ -46,6 +47,7 @@
  *     atest CtsWindowManagerDeviceTestCases:VrDisplayTests
  */
 @Presubmit
+@FlakyTest
 @android.server.wm.annotation.Group3
 public class VrDisplayTests extends MultiDisplayTestBase {
     private static final int VR_VIRTUAL_DISPLAY_WIDTH = 700;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index 7b38972..6e21f4b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -44,7 +44,7 @@
 import android.graphics.Insets;
 import android.os.CancellationSignal;
 import android.platform.test.annotations.Presubmit;
-import android.server.wm.WindowInsetsAnimationTests.TestActivity;
+import android.server.wm.WindowInsetsAnimationTestBase.TestActivity;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowInsetsAnimation;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
new file mode 100644
index 0000000..32255d2
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
@@ -0,0 +1,156 @@
+/*
+ * 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.graphics.Insets.NONE;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsets;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.cts.mockime.ImeSettings;
+import com.android.cts.mockime.MockImeSessionRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+/**
+ * Same as {@link WindowInsetsAnimationTests} but IME specific.
+ *
+ * Build/Install/Run:
+ *     atest CtsWindowManagerDeviceTestCases:WindowInsetsAnimationImeTests
+ */
+@Presubmit
+public class WindowInsetsAnimationImeTests extends WindowInsetsAnimationTestBase {
+
+    @Rule
+    public final MockImeSessionRule mMockImeSessionRule = new MockImeSessionRule(
+            InstrumentationRegistry.getInstrumentation().getContext(),
+            InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+            new ImeSettings.Builder()
+    );
+
+    @Before
+    public void setup() throws Exception {
+        super.setUp();
+        assumeTrue("MockIme cannot be used for devices that do not support installable IMEs",
+                mInstrumentation.getContext().getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_INPUT_METHODS));
+        mActivity = startActivity(TestActivity.class);
+        mRootView = mActivity.getWindow().getDecorView();
+    }
+
+    @Test
+    public void testImeAnimationCallbacksShowAndHide() {
+        WindowInsets before = mActivity.mLastWindowInsets;
+        getInstrumentation().runOnMainSync(
+                () -> mRootView.getWindowInsetsController().show(ime()));
+
+        waitForOrFail("Waiting until animation done", () -> mActivity.mCallback.animationDone);
+        commonAnimationAssertions(mActivity, before, true /* show */, ime());
+        mActivity.mCallback.animationDone = false;
+
+        before = mActivity.mLastWindowInsets;
+
+        getInstrumentation().runOnMainSync(
+                () -> mRootView.getWindowInsetsController().hide(ime()));
+
+        waitForOrFail("Waiting until animation done", () -> mActivity.mCallback.animationDone);
+
+        commonAnimationAssertions(mActivity, before, false /* show */, ime());
+    }
+
+    @Test
+    @FlakyTest(detail = "Promote once confirmed non-flaky")
+    public void testAnimationCallbacks_overlapping_opposite() {
+        WindowInsets before = mActivity.mLastWindowInsets;
+
+        MultiAnimCallback callbackInner = new MultiAnimCallback();
+        MultiAnimCallback callback = mock(MultiAnimCallback.class,
+                withSettings()
+                        .spiedInstance(callbackInner)
+                        .defaultAnswer(CALLS_REAL_METHODS)
+                        .verboseLogging());
+        mActivity.mView.setWindowInsetsAnimationCallback(callback);
+
+        getInstrumentation().runOnMainSync(
+                () -> mRootView.getWindowInsetsController().hide(navigationBars()));
+        getInstrumentation().runOnMainSync(
+                () -> mRootView.getWindowInsetsController().show(ime()));
+
+        waitForOrFail("Waiting until animation done", () -> callback.animationDone);
+
+        WindowInsets after = mActivity.mLastWindowInsets;
+
+        InOrder inOrder = inOrder(callback, mActivity.mListener);
+
+        inOrder.verify(callback).onPrepare(eq(callback.navBarAnim));
+
+        inOrder.verify(mActivity.mListener).onApplyWindowInsets(any(), argThat(
+                argument -> NONE.equals(argument.getInsets(navigationBars()))
+                        && NONE.equals(argument.getInsets(ime()))));
+
+        inOrder.verify(callback).onStart(eq(callback.navBarAnim), argThat(
+                argument -> argument.getLowerBound().equals(NONE)
+                        && argument.getUpperBound().equals(before.getInsets(navigationBars()))));
+
+        inOrder.verify(callback).onPrepare(eq(callback.imeAnim));
+        inOrder.verify(mActivity.mListener).onApplyWindowInsets(
+                any(), eq(mActivity.mLastWindowInsets));
+
+        inOrder.verify(callback).onStart(eq(callback.imeAnim), argThat(
+                argument -> argument.getLowerBound().equals(NONE)
+                        && !argument.getUpperBound().equals(NONE)));
+
+        inOrder.verify(callback).onEnd(eq(callback.navBarAnim));
+        inOrder.verify(callback).onEnd(eq(callback.imeAnim));
+
+        assertAnimationSteps(callback.navAnimSteps, false /* showAnimation */);
+        assertAnimationSteps(callback.imeAnimSteps, false /* showAnimation */);
+
+        assertEquals(before.getInsets(navigationBars()),
+                callback.navAnimSteps.get(0).insets.getInsets(navigationBars()));
+        assertEquals(after.getInsets(navigationBars()),
+                callback.navAnimSteps.get(callback.navAnimSteps.size() - 1).insets
+                        .getInsets(navigationBars()));
+
+        assertEquals(before.getInsets(ime()),
+                callback.imeAnimSteps.get(0).insets.getInsets(ime()));
+        assertEquals(after.getInsets(ime()),
+                callback.imeAnimSteps.get(callback.imeAnimSteps.size() - 1).insets
+                        .getInsets(ime()));
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
new file mode 100644
index 0000000..404fd70
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
@@ -0,0 +1,320 @@
+/*
+ * 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.graphics.Insets.NONE;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.spy;
+
+import android.os.Bundle;
+import android.util.ArraySet;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
+import android.server.wm.WindowInsetsAnimationTestBase.AnimCallback.AnimationStep;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.junit.Assert;
+import org.mockito.InOrder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * Base class for tests in {@link WindowInsetsAnimation} and {@link WindowInsetsAnimation.Callback}.
+ */
+public class WindowInsetsAnimationTestBase extends WindowManagerTestBase {
+
+    protected TestActivity mActivity;
+    protected View mRootView;
+
+    protected void commonAnimationAssertions(TestActivity activity, WindowInsets before,
+            boolean show, int types) {
+
+        AnimCallback callback = activity.mCallback;
+
+        InOrder inOrder = inOrder(activity.mCallback, activity.mListener);
+
+        WindowInsets after = activity.mLastWindowInsets;
+        inOrder.verify(callback).onPrepare(eq(callback.lastAnimation));
+        inOrder.verify(activity.mListener).onApplyWindowInsets(any(), any());
+
+        inOrder.verify(callback).onStart(eq(callback.lastAnimation), argThat(
+                argument -> argument.getLowerBound().equals(NONE)
+                        && argument.getUpperBound().equals(show
+                        ? after.getInsets(types)
+                        : before.getInsets(types))));
+
+        inOrder.verify(callback, atLeast(2)).onProgress(any(), argThat(
+                argument -> argument.size() == 1 && argument.get(0) == callback.lastAnimation));
+        inOrder.verify(callback).onEnd(eq(callback.lastAnimation));
+
+        if ((types & systemBars()) != 0) {
+            assertTrue((callback.lastAnimation.getTypeMask() & systemBars()) != 0);
+        }
+        if ((types & ime()) != 0) {
+            assertTrue((callback.lastAnimation.getTypeMask() & ime()) != 0);
+        }
+        assertTrue(callback.lastAnimation.getDurationMillis() > 0);
+        assertNotNull(callback.lastAnimation.getInterpolator());
+        assertBeforeAfterState(callback.animationSteps, before, after);
+        assertAnimationSteps(callback.animationSteps, show /* increasing */);
+    }
+
+    private void assertBeforeAfterState(ArrayList<AnimationStep> steps, WindowInsets before,
+            WindowInsets after) {
+        assertEquals(before, steps.get(0).insets);
+        assertEquals(after, steps.get(steps.size() - 1).insets);
+    }
+
+    protected void assertAnimationSteps(ArrayList<AnimationStep> steps, boolean showAnimation) {
+        assertTrue(steps.size() >= 2);
+        assertEquals(0f, steps.get(0).fraction, 0f);
+        assertEquals(0f, steps.get(0).interpolatedFraction, 0f);
+        assertEquals(1f, steps.get(steps.size() - 1).fraction, 0f);
+        assertEquals(1f, steps.get(steps.size() - 1).interpolatedFraction, 0f);
+        if (showAnimation) {
+            assertEquals(1f, steps.get(steps.size() - 1).alpha, 0f);
+        } else {
+            assertEquals(1f, steps.get(0).alpha, 0f);
+        }
+
+        assertListElements(steps, step -> step.fraction,
+                (current, next) -> next >= current);
+        assertListElements(steps, step -> step.interpolatedFraction,
+                (current, next) -> next >= current);
+        assertListElements(steps, step -> step.alpha, alpha -> alpha >= 0f);
+        assertListElements(steps, step -> step.insets, compareInsets(systemBars(), showAnimation));
+    }
+
+    private BiPredicate<WindowInsets, WindowInsets> compareInsets(int types,
+            boolean showAnimation) {
+        if (showAnimation) {
+            return (current, next) ->
+                    next.getInsets(types).left >= current.getInsets(types).left
+                            && next.getInsets(types).top >= current.getInsets(types).top
+                            && next.getInsets(types).right >= current.getInsets(types).right
+                            && next.getInsets(types).bottom >= current.getInsets(types).bottom;
+        } else {
+            return (current, next) ->
+                    next.getInsets(types).left <= current.getInsets(types).left
+                            && next.getInsets(types).top <= current.getInsets(types).top
+                            && next.getInsets(types).right <= current.getInsets(types).right
+                            && next.getInsets(types).bottom <= current.getInsets(types).bottom;
+        }
+    }
+
+    private <T, V> void assertListElements(ArrayList<T> list, Function<T, V> getter,
+            Predicate<V> predicate) {
+        for (int i = 0; i <= list.size() - 1; i++) {
+            V value = getter.apply(list.get(i));
+            assertTrue("Predicate.test failed i=" + i + " value="
+                    + value, predicate.test(value));
+        }
+    }
+
+    private <T, V> void assertListElements(ArrayList<T> list, Function<T, V> getter,
+            BiPredicate<V, V> comparator) {
+        for (int i = 0; i <= list.size() - 2; i++) {
+            V current = getter.apply(list.get(i));
+            V next = getter.apply(list.get(i + 1));
+            assertTrue(comparator.test(current, next));
+        }
+    }
+
+    public static class AnimCallback extends WindowInsetsAnimation.Callback {
+
+        public static class AnimationStep {
+
+            AnimationStep(WindowInsets insets, float fraction, float interpolatedFraction,
+                    float alpha) {
+                this.insets = insets;
+                this.fraction = fraction;
+                this.interpolatedFraction = interpolatedFraction;
+                this.alpha = alpha;
+            }
+
+            WindowInsets insets;
+            float fraction;
+            float interpolatedFraction;
+            float alpha;
+        }
+
+        WindowInsetsAnimation lastAnimation;
+        volatile boolean animationDone;
+        final ArrayList<AnimationStep> animationSteps = new ArrayList<>();
+
+        public AnimCallback(int dispatchMode) {
+            super(dispatchMode);
+        }
+
+        @Override
+        public void onPrepare(WindowInsetsAnimation animation) {
+            animationSteps.clear();
+            lastAnimation = animation;
+        }
+
+        @Override
+        public WindowInsetsAnimation.Bounds onStart(
+                WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) {
+            return bounds;
+        }
+
+        @Override
+        public WindowInsets onProgress(WindowInsets insets,
+                List<WindowInsetsAnimation> runningAnimations) {
+            animationSteps.add(new AnimationStep(insets, lastAnimation.getFraction(),
+                    lastAnimation.getInterpolatedFraction(), lastAnimation.getAlpha()));
+            return WindowInsets.CONSUMED;
+        }
+
+        @Override
+        public void onEnd(WindowInsetsAnimation animation) {
+            animationDone = true;
+        }
+    }
+
+    protected static class MultiAnimCallback extends WindowInsetsAnimation.Callback {
+
+        WindowInsetsAnimation statusBarAnim;
+        WindowInsetsAnimation navBarAnim;
+        WindowInsetsAnimation imeAnim;
+        volatile boolean animationDone;
+        final ArrayList<AnimationStep> statusAnimSteps = new ArrayList<>();
+        final ArrayList<AnimationStep> navAnimSteps = new ArrayList<>();
+        final ArrayList<AnimationStep> imeAnimSteps = new ArrayList<>();
+        Runnable startRunnable;
+        final ArraySet<WindowInsetsAnimation> runningAnims = new ArraySet<>();
+
+        public MultiAnimCallback() {
+            super(DISPATCH_MODE_STOP);
+        }
+
+        @Override
+        public void onPrepare(WindowInsetsAnimation animation) {
+            if ((animation.getTypeMask() & statusBars()) != 0) {
+                statusBarAnim = animation;
+            }
+            if ((animation.getTypeMask() & navigationBars()) != 0) {
+                navBarAnim = animation;
+            }
+            if ((animation.getTypeMask() & ime()) != 0) {
+                imeAnim = animation;
+            }
+        }
+
+        @Override
+        public WindowInsetsAnimation.Bounds onStart(
+                WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) {
+            if (startRunnable != null) {
+                startRunnable.run();
+            }
+            runningAnims.add(animation);
+            return bounds;
+        }
+
+        @Override
+        public WindowInsets onProgress(WindowInsets insets,
+                List<WindowInsetsAnimation> runningAnimations) {
+            if (statusBarAnim != null) {
+                statusAnimSteps.add(new AnimationStep(insets, statusBarAnim.getFraction(),
+                        statusBarAnim.getInterpolatedFraction(), statusBarAnim.getAlpha()));
+            }
+            if (navBarAnim != null) {
+                navAnimSteps.add(new AnimationStep(insets, navBarAnim.getFraction(),
+                        navBarAnim.getInterpolatedFraction(), navBarAnim.getAlpha()));
+            }
+            if (imeAnim != null) {
+                imeAnimSteps.add(new AnimationStep(insets, imeAnim.getFraction(),
+                        imeAnim.getInterpolatedFraction(), imeAnim.getAlpha()));
+            }
+
+            assertEquals(runningAnims.size(), runningAnimations.size());
+            for (int i = runningAnimations.size() - 1; i >= 0; i--) {
+                Assert.assertNotEquals(-1,
+                        runningAnims.indexOf(runningAnimations.get(i)));
+            }
+
+            return WindowInsets.CONSUMED;
+        }
+
+        @Override
+        public void onEnd(WindowInsetsAnimation animation) {
+            runningAnims.remove(animation);
+            if (runningAnims.isEmpty()) {
+                animationDone = true;
+            }
+        }
+    }
+
+    public static class TestActivity extends FocusableActivity {
+
+        AnimCallback mCallback =
+                spy(new AnimCallback(WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP));
+        WindowInsets mLastWindowInsets;
+
+        View.OnApplyWindowInsetsListener mListener;
+        LinearLayout mView;
+        View mChild;
+        EditText mEditor;
+
+        public class InsetsListener implements View.OnApplyWindowInsetsListener {
+
+            @Override
+            public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+                mLastWindowInsets = insets;
+                return WindowInsets.CONSUMED;
+            }
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            mListener = spy(new InsetsListener());
+            mView = new LinearLayout(this);
+            mView.setWindowInsetsAnimationCallback(mCallback);
+            mView.setOnApplyWindowInsetsListener(mListener);
+            mChild = new TextView(this);
+            mEditor = new EditText(this);
+            mView.addView(mChild);
+
+            getWindow().setDecorFitsSystemWindows(false);
+            getWindow().getAttributes().layoutInDisplayCutoutMode =
+                    LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+            setContentView(mView);
+            mEditor.requestFocus();
+        }
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
index 86fc5ee..e3a5328 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
@@ -17,54 +17,37 @@
 package android.server.wm;
 
 import static android.graphics.Insets.NONE;
-import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowInsets.Type.systemBars;
 import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
-import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.withSettings;
 
-import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
-import android.server.wm.WindowInsetsAnimationTests.AnimCallback.AnimationStep;
-import android.util.ArraySet;
-import android.view.View;
-import android.view.View.OnApplyWindowInsetsListener;
 import android.view.WindowInsets;
 import android.view.WindowInsetsAnimation;
 import android.view.WindowInsetsAnimation.Bounds;
 import android.view.WindowInsetsAnimation.Callback;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.InOrder;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.function.BiPredicate;
-import java.util.function.Function;
-import java.util.function.Predicate;
 
 import androidx.test.filters.FlakyTest;
 
@@ -75,13 +58,10 @@
  *     atest CtsWindowManagerDeviceTestCases:WindowInsetsAnimationTests
  */
 @Presubmit
-public class WindowInsetsAnimationTests extends WindowManagerTestBase {
-
-    TestActivity mActivity;
-    View mRootView;
+public class WindowInsetsAnimationTests extends WindowInsetsAnimationTestBase {
 
     @Before
-    public void setUp() throws Exception {
+    public void setup() throws Exception {
         super.setUp();
         mActivity = startActivity(TestActivity.class);
         mRootView = mActivity.getWindow().getDecorView();
@@ -118,26 +98,6 @@
     }
 
     @Test
-    public void testImeAnimationCallbacksShowAndHide() {
-        WindowInsets before = mActivity.mLastWindowInsets;
-        getInstrumentation().runOnMainSync(
-                () -> mRootView.getWindowInsetsController().show(ime()));
-
-        waitForOrFail("Waiting until animation done", () -> mActivity.mCallback.animationDone);
-        commonAnimationAssertions(mActivity, before, true /* show */, ime());
-        mActivity.mCallback.animationDone = false;
-
-        before = mActivity.mLastWindowInsets;
-
-        getInstrumentation().runOnMainSync(
-                () -> mRootView.getWindowInsetsController().hide(ime()));
-
-        waitForOrFail("Waiting until animation done", () -> mActivity.mCallback.animationDone);
-
-        commonAnimationAssertions(mActivity, before, false /* show */, ime());
-    }
-
-    @Test
     @FlakyTest(detail = "Promote once confirmed non-flaky")
     public void testAnimationCallbacks_overlapping() {
         WindowInsets before = mActivity.mLastWindowInsets;
@@ -199,67 +159,6 @@
     }
 
     @Test
-    @FlakyTest(detail = "Promote once confirmed non-flaky")
-    public void testAnimationCallbacks_overlapping_opposite() {
-        WindowInsets before = mActivity.mLastWindowInsets;
-
-        MultiAnimCallback callbackInner = new MultiAnimCallback();
-        MultiAnimCallback callback = mock(MultiAnimCallback.class,
-                withSettings()
-                        .spiedInstance(callbackInner)
-                        .defaultAnswer(CALLS_REAL_METHODS)
-                        .verboseLogging());
-        mActivity.mView.setWindowInsetsAnimationCallback(callback);
-
-        getInstrumentation().runOnMainSync(
-                () -> mRootView.getWindowInsetsController().hide(navigationBars()));
-        getInstrumentation().runOnMainSync(
-                () -> mRootView.getWindowInsetsController().show(ime()));
-
-        waitForOrFail("Waiting until animation done", () -> callback.animationDone);
-
-        WindowInsets after = mActivity.mLastWindowInsets;
-
-        InOrder inOrder = inOrder(callback, mActivity.mListener);
-
-        inOrder.verify(callback).onPrepare(eq(callback.navBarAnim));
-
-        inOrder.verify(mActivity.mListener).onApplyWindowInsets(any(), argThat(
-                argument -> NONE.equals(argument.getInsets(navigationBars()))
-                        && NONE.equals(argument.getInsets(ime()))));
-
-        inOrder.verify(callback).onStart(eq(callback.navBarAnim), argThat(
-                argument -> argument.getLowerBound().equals(NONE)
-                        && argument.getUpperBound().equals(before.getInsets(navigationBars()))));
-
-        inOrder.verify(callback).onPrepare(eq(callback.imeAnim));
-        inOrder.verify(mActivity.mListener).onApplyWindowInsets(
-                any(), eq(mActivity.mLastWindowInsets));
-
-        inOrder.verify(callback).onStart(eq(callback.imeAnim), argThat(
-                argument -> argument.getLowerBound().equals(NONE)
-                        && !argument.getUpperBound().equals(NONE)));
-
-        inOrder.verify(callback).onEnd(eq(callback.navBarAnim));
-        inOrder.verify(callback).onEnd(eq(callback.imeAnim));
-
-        assertAnimationSteps(callback.navAnimSteps, false /* showAnimation */);
-        assertAnimationSteps(callback.imeAnimSteps, false /* showAnimation */);
-
-        assertEquals(before.getInsets(navigationBars()),
-                callback.navAnimSteps.get(0).insets.getInsets(navigationBars()));
-        assertEquals(after.getInsets(navigationBars()),
-                callback.navAnimSteps.get(callback.navAnimSteps.size() - 1).insets
-                        .getInsets(navigationBars()));
-
-        assertEquals(before.getInsets(ime()),
-                callback.imeAnimSteps.get(0).insets.getInsets(ime()));
-        assertEquals(after.getInsets(ime()),
-                callback.imeAnimSteps.get(callback.imeAnimSteps.size() - 1).insets
-                        .getInsets(ime()));
-    }
-
-    @Test
     public void testAnimationCallbacks_consumedByDecor() {
         getInstrumentation().runOnMainSync(() -> {
             mActivity.getWindow().setDecorFitsSystemWindows(true);
@@ -326,256 +225,5 @@
                 insets -> NONE.equals(insets.getInsets(navigationBars()))), any());
     }
 
-    private void commonAnimationAssertions(TestActivity activity, WindowInsets before,
-            boolean show, int types) {
 
-        AnimCallback callback = activity.mCallback;
-
-        InOrder inOrder = inOrder(activity.mCallback, activity.mListener);
-
-        WindowInsets after = activity.mLastWindowInsets;
-        inOrder.verify(callback).onPrepare(eq(callback.lastAnimation));
-        inOrder.verify(activity.mListener).onApplyWindowInsets(any(), any());
-
-        inOrder.verify(callback).onStart(eq(callback.lastAnimation), argThat(
-                argument -> argument.getLowerBound().equals(NONE)
-                        && argument.getUpperBound().equals(show
-                                ? after.getInsets(types)
-                                : before.getInsets(types))));
-
-        inOrder.verify(callback, atLeast(2)).onProgress(any(), argThat(
-                argument -> argument.size() == 1 && argument.get(0) == callback.lastAnimation));
-        inOrder.verify(callback).onEnd(eq(callback.lastAnimation));
-
-        if ((types & systemBars()) != 0) {
-            assertTrue((callback.lastAnimation.getTypeMask() & systemBars()) != 0);
-        }
-        if ((types & ime()) != 0) {
-            assertTrue((callback.lastAnimation.getTypeMask() & ime()) != 0);
-        }
-        assertTrue(callback.lastAnimation.getDurationMillis() > 0);
-        assertNotNull(callback.lastAnimation.getInterpolator());
-        assertBeforeAfterState(callback.animationSteps, before, after);
-        assertAnimationSteps(callback.animationSteps, show /* increasing */);
-    }
-
-    private void assertBeforeAfterState(ArrayList<AnimationStep> steps, WindowInsets before,
-            WindowInsets after) {
-        assertEquals(before, steps.get(0).insets);
-        assertEquals(after, steps.get(steps.size() - 1).insets);
-    }
-
-    private void assertAnimationSteps(ArrayList<AnimationStep> steps, boolean showAnimation) {
-        assertTrue(steps.size() >= 2);
-        assertEquals(0f, steps.get(0).fraction, 0f);
-        assertEquals(0f, steps.get(0).interpolatedFraction, 0f);
-        assertEquals(1f, steps.get(steps.size() - 1).fraction, 0f);
-        assertEquals(1f, steps.get(steps.size() - 1).interpolatedFraction, 0f);
-        if (showAnimation) {
-            assertEquals(1f, steps.get(steps.size() - 1).alpha, 0f);
-        } else {
-            assertEquals(1f, steps.get(0).alpha, 0f);
-        }
-
-        assertListElements(steps, step -> step.fraction,
-                (current, next) -> next >= current);
-        assertListElements(steps, step -> step.interpolatedFraction,
-                (current, next) -> next >= current);
-        assertListElements(steps, step -> step.alpha, alpha -> alpha >= 0f);
-        assertListElements(steps, step -> step.insets, compareInsets(systemBars(), showAnimation));
-    }
-
-    private BiPredicate<WindowInsets, WindowInsets> compareInsets(int types,
-            boolean showAnimation) {
-        if (showAnimation) {
-            return (current, next) ->
-                    next.getInsets(types).left >= current.getInsets(types).left
-                            && next.getInsets(types).top >= current.getInsets(types).top
-                            && next.getInsets(types).right >= current.getInsets(types).right
-                            && next.getInsets(types).bottom >= current.getInsets(types).bottom;
-        } else {
-            return (current, next) ->
-                    next.getInsets(types).left <= current.getInsets(types).left
-                            && next.getInsets(types).top <= current.getInsets(types).top
-                            && next.getInsets(types).right <= current.getInsets(types).right
-                            && next.getInsets(types).bottom <= current.getInsets(types).bottom;
-        }
-    }
-
-    private <T, V> void assertListElements(ArrayList<T> list, Function<T, V> getter,
-            Predicate<V> predicate) {
-        for (int i = 0; i <= list.size() - 1; i++) {
-            V value = getter.apply(list.get(i));
-            assertTrue("Predicate.test failed i=" + i + " value=" + value, predicate.test(value));
-        }
-    }
-
-    private <T, V> void assertListElements(ArrayList<T> list, Function<T, V> getter,
-            BiPredicate<V, V> comparator) {
-        for (int i = 0; i <= list.size() - 2; i++) {
-            V current = getter.apply(list.get(i));
-            V next = getter.apply(list.get(i + 1));
-            assertTrue(comparator.test(current, next));
-        }
-    }
-
-    public static class AnimCallback extends WindowInsetsAnimation.Callback {
-
-        public static class AnimationStep {
-
-            AnimationStep(WindowInsets insets, float fraction, float interpolatedFraction,
-                    float alpha) {
-                this.insets = insets;
-                this.fraction = fraction;
-                this.interpolatedFraction = interpolatedFraction;
-                this.alpha = alpha;
-            }
-
-            WindowInsets insets;
-            float fraction;
-            float interpolatedFraction;
-            float alpha;
-        }
-
-        WindowInsetsAnimation lastAnimation;
-        volatile boolean animationDone;
-        final ArrayList<AnimationStep> animationSteps = new ArrayList<>();
-
-        public AnimCallback(int dispatchMode) {
-            super(dispatchMode);
-        }
-
-        @Override
-        public void onPrepare(WindowInsetsAnimation animation) {
-            animationSteps.clear();
-            lastAnimation = animation;
-        }
-
-        @Override
-        public Bounds onStart(WindowInsetsAnimation animation, Bounds bounds) {
-            return bounds;
-        }
-
-        @Override
-        public WindowInsets onProgress(WindowInsets insets,
-                List<WindowInsetsAnimation> runningAnimations) {
-            animationSteps.add(new AnimationStep(insets, lastAnimation.getFraction(),
-                    lastAnimation.getInterpolatedFraction(), lastAnimation.getAlpha()));
-            return WindowInsets.CONSUMED;
-        }
-
-        @Override
-        public void onEnd(WindowInsetsAnimation animation) {
-            animationDone = true;
-        }
-    }
-
-    public static class MultiAnimCallback extends WindowInsetsAnimation.Callback {
-
-        WindowInsetsAnimation statusBarAnim;
-        WindowInsetsAnimation navBarAnim;
-        WindowInsetsAnimation imeAnim;
-        volatile boolean animationDone;
-        final ArrayList<AnimationStep> statusAnimSteps = new ArrayList<>();
-        final ArrayList<AnimationStep> navAnimSteps = new ArrayList<>();
-        final ArrayList<AnimationStep> imeAnimSteps = new ArrayList<>();
-        Runnable startRunnable;
-        final ArraySet<WindowInsetsAnimation> runningAnims = new ArraySet<>();
-
-        public MultiAnimCallback() {
-            super(DISPATCH_MODE_STOP);
-        }
-
-        @Override
-        public void onPrepare(WindowInsetsAnimation animation) {
-            if ((animation.getTypeMask() & statusBars()) != 0) {
-                statusBarAnim = animation;
-            }
-            if ((animation.getTypeMask() & navigationBars()) != 0) {
-                navBarAnim = animation;
-            }
-            if ((animation.getTypeMask() & ime()) != 0) {
-                imeAnim = animation;
-            }
-        }
-
-        @Override
-        public Bounds onStart(WindowInsetsAnimation animation, Bounds bounds) {
-            if (startRunnable != null) {
-                startRunnable.run();
-            }
-            runningAnims.add(animation);
-            return bounds;
-        }
-
-        @Override
-        public WindowInsets onProgress(WindowInsets insets,
-                List<WindowInsetsAnimation> runningAnimations) {
-            if (statusBarAnim != null) {
-                statusAnimSteps.add(new AnimationStep(insets, statusBarAnim.getFraction(),
-                        statusBarAnim.getInterpolatedFraction(), statusBarAnim.getAlpha()));
-            }
-            if (navBarAnim != null) {
-                navAnimSteps.add(new AnimationStep(insets, navBarAnim.getFraction(),
-                        navBarAnim.getInterpolatedFraction(), navBarAnim.getAlpha()));
-            }
-            if (imeAnim != null) {
-                imeAnimSteps.add(new AnimationStep(insets, imeAnim.getFraction(),
-                        imeAnim.getInterpolatedFraction(), imeAnim.getAlpha()));
-            }
-
-            assertEquals(runningAnims.size(), runningAnimations.size());
-            for (int i = runningAnimations.size() - 1; i >= 0; i--) {
-                Assert.assertNotEquals(-1, runningAnims.indexOf(runningAnimations.get(i)));
-            }
-
-            return WindowInsets.CONSUMED;
-        }
-
-        @Override
-        public void onEnd(WindowInsetsAnimation animation) {
-            runningAnims.remove(animation);
-            if (runningAnims.isEmpty()) {
-                animationDone = true;
-            }
-        }
-    }
-
-    public static class TestActivity extends FocusableActivity {
-
-        AnimCallback mCallback = spy(new AnimCallback(Callback.DISPATCH_MODE_STOP));
-        WindowInsets mLastWindowInsets;
-
-        OnApplyWindowInsetsListener mListener;
-        LinearLayout mView;
-        View mChild;
-        EditText mEditor;
-
-        public class InsetsListener implements OnApplyWindowInsetsListener {
-
-            @Override
-            public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
-                mLastWindowInsets = insets;
-                return WindowInsets.CONSUMED;
-            }
-        }
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            mListener = spy(new InsetsListener());
-            mView = new LinearLayout(this);
-            mView.setWindowInsetsAnimationCallback(mCallback);
-            mView.setOnApplyWindowInsetsListener(mListener);
-            mChild = new TextView(this);
-            mEditor = new EditText(this);
-            mView.addView(mChild);
-
-            getWindow().setDecorFitsSystemWindows(false);
-            getWindow().getAttributes().layoutInDisplayCutoutMode =
-                    LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-            setContentView(mView);
-            mEditor.requestFocus();
-        }
-    }
 }
diff --git a/tests/tests/appop/AndroidTest.xml b/tests/tests/appop/AndroidTest.xml
index 386feb4..29f01e0 100644
--- a/tests/tests/appop/AndroidTest.xml
+++ b/tests/tests/appop/AndroidTest.xml
@@ -23,6 +23,7 @@
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAppOpsTestCases.apk" />
         <option name="test-file-name" value="CtsAppThatUsesAppOps.apk" />
+        <option name="test-file-name" value="AppInBackground.apk" />
         <option name="test-file-name" value="AppThatCanBeForcedIntoForegroundStates.apk" />
     </target_preparer>
 
diff --git a/tests/tests/appop/AppInBackground/Android.bp b/tests/tests/appop/AppInBackground/Android.bp
new file mode 100644
index 0000000..b46e877
--- /dev/null
+++ b/tests/tests/appop/AppInBackground/Android.bp
@@ -0,0 +1,23 @@
+// 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.
+
+android_test_helper_app {
+    name: "AppInBackground",
+
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ]
+}
diff --git a/tests/tests/appop/AppInBackground/AndroidManifest.xml b/tests/tests/appop/AppInBackground/AndroidManifest.xml
new file mode 100644
index 0000000..00d9ab8
--- /dev/null
+++ b/tests/tests/appop/AppInBackground/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.app.appops.cts.appinbackground">
+    <attribution android:tag="testAttribution" android:label="@string/dummyLabel" />
+
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+    <application />
+</manifest>
diff --git a/tests/tests/appop/AppInBackground/res/values/strings.xml b/tests/tests/appop/AppInBackground/res/values/strings.xml
new file mode 100644
index 0000000..c99e65f
--- /dev/null
+++ b/tests/tests/appop/AppInBackground/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<resources>
+    <string name="dummyLabel">A feature</string>
+</resources>
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt
index 103a4b2..bede62a 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt
@@ -39,6 +39,8 @@
 import org.junit.Test
 import java.lang.Thread.sleep
 
+private const val BACKGROUND_PACKAGE = "android.app.appops.cts.appinbackground"
+
 class AppOpEventCollectionTest {
     private val instrumentation = InstrumentationRegistry.getInstrumentation()
     private val context = instrumentation.targetContext
@@ -105,30 +107,86 @@
         val attributionOpEntry = opEntry.attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
 
         assertThat(attributionOpEntry.getLastAccessForegroundTime(OP_FLAG_SELF)).isIn(before..after)
+        assertThat(opEntry.getLastAccessForegroundTime(OP_FLAG_SELF)).isIn(before..after)
 
         // Access should should also show up in the combined state for all op-flags
         assertThat(attributionOpEntry.getLastAccessForegroundTime(OP_FLAGS_ALL)).isIn(before..after)
-        assertThat(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(before..after)
+        assertThat(opEntry.getLastAccessForegroundTime(OP_FLAGS_ALL)).isIn(before..after)
 
         // Foreground access should should also show up in the combined state for fg and bg
         assertThat(attributionOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
         assertThat(opEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
+        assertThat(attributionOpEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(before..after)
+        assertThat(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(before..after)
 
         // The access was in foreground, hence there is no background access
-        assertThat(attributionOpEntry.getLastBackgroundDuration(OP_FLAG_SELF)).isLessThan(before)
-        assertThat(opEntry.getLastBackgroundDuration(OP_FLAG_SELF)).isLessThan(before)
+        assertThat(attributionOpEntry.getLastAccessBackgroundTime(OP_FLAG_SELF)).isLessThan(before)
+        assertThat(opEntry.getLastAccessBackgroundTime(OP_FLAG_SELF)).isLessThan(before)
+        assertThat(attributionOpEntry.getLastAccessBackgroundTime(OP_FLAGS_ALL)).isLessThan(before)
+        assertThat(opEntry.getLastAccessBackgroundTime(OP_FLAGS_ALL)).isLessThan(before)
 
         // The access was for a attribution, hence there is no access for the default attribution
         if (null in opEntry.attributedOpEntries) {
             assertThat(opEntry.attributedOpEntries[null]!!
-                    .getLastAccessForegroundTime(OP_FLAG_SELF)).isLessThan(before)
+                .getLastAccessForegroundTime(OP_FLAG_SELF)).isLessThan(before)
         }
 
         // The access does not show up for other op-flags
-        assertThat(attributionOpEntry.getLastAccessForegroundTime(
-                OP_FLAGS_ALL and OP_FLAG_SELF.inv())).isLessThan(before)
-        assertThat(opEntry.getLastAccessForegroundTime(
-                OP_FLAGS_ALL and OP_FLAG_SELF.inv())).isLessThan(before)
+        assertThat(
+            attributionOpEntry.getLastAccessForegroundTime(OP_FLAGS_ALL and OP_FLAG_SELF.inv())
+        ).isLessThan(before)
+        assertThat(opEntry.getLastAccessForegroundTime(OP_FLAGS_ALL and OP_FLAG_SELF.inv()))
+            .isLessThan(before)
+    }
+
+    @Test
+    fun noteInBackgroundWithAttributionAndCheckOpEntries() {
+        val uid = context.packageManager.getPackageUid(BACKGROUND_PACKAGE, 0)
+
+        val before = System.currentTimeMillis()
+        assertThat(
+            runWithShellPermissionIdentity {
+                appOpsManager.noteOp(
+                    OPSTR_WIFI_SCAN, uid, BACKGROUND_PACKAGE, TEST_ATTRIBUTION_TAG, null
+                )
+            }
+        ).isEqualTo(AppOpsManager.MODE_ALLOWED)
+        val after = System.currentTimeMillis()
+
+        val opEntry = getOpEntry(uid, BACKGROUND_PACKAGE, OPSTR_WIFI_SCAN)!!
+        val attributionOpEntry = opEntry.attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
+
+        assertThat(attributionOpEntry.getLastAccessBackgroundTime(OP_FLAG_SELF)).isIn(before..after)
+        assertThat(opEntry.getLastAccessBackgroundTime(OP_FLAG_SELF)).isIn(before..after)
+
+        // Access should should also show up in the combined state for all op-flags
+        assertThat(attributionOpEntry.getLastAccessBackgroundTime(OP_FLAGS_ALL)).isIn(before..after)
+        assertThat(opEntry.getLastAccessBackgroundTime(OP_FLAGS_ALL)).isIn(before..after)
+
+        // Background access should should also show up in the combined state for fg and bg
+        assertThat(attributionOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
+        assertThat(opEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
+        assertThat(attributionOpEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(before..after)
+        assertThat(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(before..after)
+
+        // The access was in background, hence there is no foreground access
+        assertThat(attributionOpEntry.getLastAccessForegroundTime(OP_FLAG_SELF)).isLessThan(before)
+        assertThat(opEntry.getLastAccessForegroundTime(OP_FLAG_SELF)).isLessThan(before)
+        assertThat(attributionOpEntry.getLastAccessForegroundTime(OP_FLAGS_ALL)).isLessThan(before)
+        assertThat(opEntry.getLastAccessForegroundTime(OP_FLAGS_ALL)).isLessThan(before)
+
+        // The access was for a attribution, hence there is no access for the default attribution
+        if (null in opEntry.attributedOpEntries) {
+            assertThat(opEntry.attributedOpEntries[null]!!
+                .getLastAccessBackgroundTime(OP_FLAG_SELF)).isLessThan(before)
+        }
+
+        // The access does not show up for other op-flags
+        assertThat(
+            attributionOpEntry.getLastAccessBackgroundTime(OP_FLAGS_ALL and OP_FLAG_SELF.inv())
+        ).isLessThan(before)
+        assertThat(opEntry.getLastAccessBackgroundTime(OP_FLAGS_ALL and OP_FLAG_SELF.inv()))
+            .isLessThan(before)
     }
 
     @Test
diff --git a/tests/tests/display/OWNERS b/tests/tests/display/OWNERS
index 6b9f7be..041736b 100644
--- a/tests/tests/display/OWNERS
+++ b/tests/tests/display/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 46788
-michaelwr@google.com
\ No newline at end of file
+michaelwr@google.com
+santoscordon@google.com
diff --git a/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java b/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
index f3b716d..7df46ea 100644
--- a/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
+++ b/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
@@ -51,10 +51,7 @@
 
     @Before
     public void setUp() {
-        String version = Build.VERSION.CODENAME;
-        // Avoid running these tests before R, on which MediaParser was defined.
-        // These check is inlined from BuildCompat to avoid bringing in the entire dependency.
-        assumeTrue(version.length() == 1 && version.charAt(0) >= 'R' && version.charAt(0) <= 'Z');
+        assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
     }
 
     @Test
diff --git a/tests/tests/net/src/android/net/cts/NetworkRequestTest.java b/tests/tests/net/src/android/net/cts/NetworkRequestTest.java
index 5dfcffb..f32ee9e 100644
--- a/tests/tests/net/src/android/net/cts/NetworkRequestTest.java
+++ b/tests/tests/net/src/android/net/cts/NetworkRequestTest.java
@@ -190,11 +190,11 @@
         assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularMmsInternetSpecifier2));
         assertFalse(requestCellularInternet.canBeSatisfiedBy(capVpnInternetSpecifier1));
         assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularVpnMmsInternet));
-
-        testInvariantInCanBeSatisfiedBy();
     }
 
-    private void testInvariantInCanBeSatisfiedBy() {
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testInvariantInCanBeSatisfiedBy() {
         // Test invariant that result of NetworkRequest.canBeSatisfiedBy() should be the same with
         // NetworkCapabilities.satisfiedByNetworkCapabilities().
         final LocalNetworkSpecifier specifier1 = new LocalNetworkSpecifier(1234 /* id */);
diff --git a/tests/tests/opengl/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/opengl/src/android/opengl/cts/OpenGlEsVersionTest.java
index 37f90e9..ef2a0c1 100644
--- a/tests/tests/opengl/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -113,15 +113,6 @@
 
         String extensions = mActivity.getExtensionsString();
 
-        final String es30RequiredList[] = {
-            "OES_EGL_image_external_essl3"
-        };
-
-        for (int i = 0; i < es30RequiredList.length; ++i) {
-            assertTrue("OpenGL ES version 3.0+ is missing extension " + es30RequiredList[i],
-                    hasExtension(extensions, es30RequiredList[i]));
-        }
-
         if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) < 1)
             return;
 
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 39d8f1b..9bfae3c 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -200,6 +200,34 @@
         }
     }
 
+    @AppModeFull(reason = "Uses separate apps for testing")
+    fun testAutoRevoke_whitelistingApis() {
+        withDummyApp {
+            val pm = context.packageManager
+            runWithShellPermissionIdentity {
+                assertFalse(pm.isAutoRevokeWhitelisted(APK_PACKAGE_NAME))
+            }
+
+            runWithShellPermissionIdentity {
+                assertTrue(pm.setAutoRevokeWhitelisted(APK_PACKAGE_NAME, true))
+            }
+            eventually {
+                runWithShellPermissionIdentity {
+                    assertTrue(pm.isAutoRevokeWhitelisted(APK_PACKAGE_NAME))
+                }
+            }
+
+            runWithShellPermissionIdentity {
+                assertTrue(pm.setAutoRevokeWhitelisted(APK_PACKAGE_NAME, false))
+            }
+            eventually {
+                runWithShellPermissionIdentity {
+                    assertFalse(pm.isAutoRevokeWhitelisted(APK_PACKAGE_NAME))
+                }
+            }
+        }
+    }
+
     private fun wakeUpScreen() {
         runShellCommand("input keyevent KEYCODE_WAKEUP")
         runShellCommand("input keyevent 82")
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index abc63a5..dcc3aef 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -3778,11 +3778,6 @@
     <permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"
                 android:protectionLevel="signature|installer" />
 
-    <!-- Allows an application to manage the companion devices.
-         @hide -->
-    <permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
-                android:protectionLevel="signature" />
-
     <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
          <p>Not for use by third-party applications.
          @hide
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 66f1cb3..86e674e 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -2928,16 +2928,7 @@
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
-        // Tab should not cause focus to leave the multiline textfield.
-        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_TAB);
-        mInstrumentation.waitForIdleSync();
-        assertTrue(mTextView.isFocused());
-
-        // Tab on the singleline TextView should.
-        mActivityRule.runOnUiThread(() -> {
-            mTextView.setSingleLine(true);
-        });
-        mInstrumentation.waitForIdleSync();
+        // Tab should
         CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_TAB);
         mInstrumentation.waitForIdleSync();
         assertFalse(mTextView.isFocused());