Merge "Fix textView id for NonExportedActivity" into rvc-dev
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 67216ef..dcca509 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -33,6 +33,25 @@
 THRESH_MIN_PIXEL = 4  # Crop test allowed offset
 PREVIEW_SIZE = (1920, 1080)  # preview size
 
+# Before API level 30, only resolutions with the following listed aspect ratio
+# are checked. Device launched after API level 30 will need to pass the test
+# for all advertised resolutions. Device launched before API level 30 just
+# needs to pass the test for all resolutions within these aspect ratios.
+AR_CHECKED_PRE_API_30 = ["4:3", "16:9", "18:9"]
+AR_DIFF_ATOL = 0.01
+
+
+def is_checked_aspect_ratio(first_api_level, w, h):
+    if first_api_level >= 30:
+        return True
+
+    for ar_check in AR_CHECKED_PRE_API_30:
+        match_ar_list = [float(x) for x in ar_check.split(":")]
+        match_ar = match_ar_list[0] / match_ar_list[1]
+        if np.isclose(float(w)/h, match_ar, atol=AR_DIFF_ATOL):
+            return True
+
+    return False
 
 def calc_expected_circle_image_ratio(ref_fov, img_w, img_h):
     """Determine the circle image area ratio in percentage for a given image size.
@@ -536,8 +555,9 @@
                 fov_percent = calc_circle_image_ratio(
                         cc_w, cc_h, w_iter, h_iter)
                 chk_percent = calc_expected_circle_image_ratio(ref_fov, w_iter, h_iter)
-                if not np.isclose(fov_percent, chk_percent,
-                                  rtol=FOV_PERCENT_RTOL):
+                chk_enabled = is_checked_aspect_ratio(first_api, w_iter, h_iter)
+                if chk_enabled and not np.isclose(fov_percent, chk_percent,
+                                                  rtol=FOV_PERCENT_RTOL):
                     msg = "FoV %%: %.2f, Ref FoV %%: %.2f, " % (
                             fov_percent, chk_percent)
                     msg += "TOL=%.f%%, img: %dx%d, ref: %dx%d" % (
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
index cd739b5..36a10f4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
@@ -375,7 +375,7 @@
 
                     CameraCharacteristics physicalChar =
                             manager.getCameraCharacteristics(physicalId);
-                    hwLevel = characteristics.get(
+                    hwLevel = physicalChar.get(
                             CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                     if (hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY ||
                             hwLevel ==
@@ -384,6 +384,18 @@
                         continue;
                     }
 
+                    int[] physicalActualCapabilities = physicalChar.get(
+                            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+                    boolean physicalHaveBC = false;
+                    for (int capability : physicalActualCapabilities) {
+                        if (capability == BACKWARD_COMPAT) {
+                            physicalHaveBC = true;
+                            break;
+                        }
+                    }
+                    if (!physicalHaveBC) {
+                        continue;
+                    }
                     // To reduce duplicate tests, only additionally test hidden physical cameras
                     // with different focal length compared to the default focal length of the
                     // logical camera.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
old mode 100644
new mode 100755
index c4ad958..e2989ac
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
@@ -602,7 +602,12 @@
                 nextButtonText = R.string.next_button_text;
                 break;
         }
-        mNextButton.setText(nextButtonText);
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mNextButton.setText(nextButtonText);
+            }
+        });
     }
 
     /**
diff --git a/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java b/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
index 29d718f..11a1ae0 100644
--- a/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
+++ b/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
@@ -43,6 +43,18 @@
         return tf;
     }
 
+    // *** READ THIS IF YOUR DEVICE IS FAILING THIS TEST ***
+    // This test checks to see that Microsoft OS Descriptors are enabled on the adb USB interface,
+    // so that users don't have to install a specific driver for their device in order to use adb
+    // with it (and OEMs don't have to sign and host that driver).
+    //
+    // adbd exports Microsoft OS descriptors when setting up its endpoint descriptors, but the
+    // kernel requires that the OS descriptor functionality be enabled separately by writing "1" to
+    // the gadget's configfs file at /config/usb_gadget/g<N>/os_desc/use (where <N> is probably 1).
+    // To pass this test, you need to modify your USB HAL implementation to do this.
+    //
+    // See https://android.googlesource.com/platform/hardware/google/pixel/+/5c7c6d5edcbe04454eb9a40f947ac0a3045f64eb
+    // for the patch that enabled this on Pixel devices.
     public void testHasMsOsDescriptors() throws Exception {
         File check_ms_os_desc = copyResourceToTempFile("/check_ms_os_desc");
         check_ms_os_desc.setExecutable(true);
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index ae185c7..3a569db 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -17,7 +17,7 @@
     defaults: ["cts_defaults"],
 
     // Only compile source java files in this apk.
-    srcs: ["src/**/*.java"],
+    srcs: ["src/**/*.java", "src/**/*.kt"],
 
     libs: [
         "cts-tradefed",
@@ -27,7 +27,11 @@
         "hamcrest-library",
     ],
 
-    static_libs: ["CompatChangeGatingTestBase"],
+    static_libs: [
+        "CompatChangeGatingTestBase",
+        "CtsPkgInstallerConstants",
+        "cts-host-utils",
+    ],
 
     java_resource_dirs: ["res"],
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
index 24cc5ae..283d3cb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
@@ -28,7 +28,7 @@
 /**
  * Base class.
  */
-abstract class BaseAppSecurityTest extends BaseHostJUnit4Test {
+public abstract class BaseAppSecurityTest extends BaseHostJUnit4Test {
 
     /** Whether multi-user is supported. */
     protected boolean mSupportsMultiUser;
@@ -92,7 +92,10 @@
             this(false);
         }
         public InstallMultiple(boolean instant) {
-            super(getDevice(), getBuild(), getAbi());
+            this(instant, true);
+        }
+        public InstallMultiple(boolean instant, boolean grantPermissions) {
+            super(getDevice(), getBuild(), getAbi(), grantPermissions);
             addArg(instant ? "--instant" : "");
             addArg("--force-queryable");
         }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java
index 54c00dc..4e43022 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java
@@ -51,10 +51,17 @@
     private boolean mUseNaturalAbi;
 
     public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
+        this(device, buildInfo, abi, true);
+    }
+
+    public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi,
+            boolean grantPermissions) {
         mDevice = device;
         mBuild = buildInfo;
         mAbi = abi;
-        addArg("-g");
+        if (grantPermissions) {
+            addArg("-g");
+        }
     }
 
     T addArg(String arg) {
@@ -114,6 +121,11 @@
         return (T) this;
     }
 
+    T restrictPermissions() {
+        addArg("--restrict-permissions");
+        return (T) this;
+    }
+
     protected String deriveRemoteName(String originalName, int index) {
         return index + "_" + originalName;
     }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageSetInstallerTest.kt b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageSetInstallerTest.kt
new file mode 100644
index 0000000..f3c3420
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageSetInstallerTest.kt
@@ -0,0 +1,256 @@
+/*
+ * 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.appsecurity.cts
+
+import android.appsecurity.cts.PackageSetInstallerConstants.CHANGE_ID
+import android.appsecurity.cts.PackageSetInstallerConstants.PERMISSION_HARD_RESTRICTED
+import android.appsecurity.cts.PackageSetInstallerConstants.PERMISSION_IMMUTABLY_SOFT_RESTRICTED
+import android.appsecurity.cts.PackageSetInstallerConstants.PERMISSION_KEY
+import android.appsecurity.cts.PackageSetInstallerConstants.PERMISSION_NOT_RESTRICTED
+import android.appsecurity.cts.PackageSetInstallerConstants.SHOULD_SUCCEED_KEY
+import android.appsecurity.cts.PackageSetInstallerConstants.SHOULD_THROW_EXCEPTION_KEY
+import android.appsecurity.cts.PackageSetInstallerConstants.TARGET_APK
+import android.appsecurity.cts.PackageSetInstallerConstants.TARGET_PKG
+import android.appsecurity.cts.PackageSetInstallerConstants.WHITELIST_APK
+import android.appsecurity.cts.PackageSetInstallerConstants.WHITELIST_PKG
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters
+import android.cts.host.utils.DeviceJUnit4Parameterized
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * This test verifies protection for an exploit where any app could set the installer package
+ * name for another app if the installer was uninstalled or never set.
+ *
+ * It mimics both the set installer logic and checks for a permission bypass caused by this exploit,
+ * where an app could take installer for itself and whitelist itself to receive protected
+ * permissions.
+ */
+@RunWith(DeviceJUnit4Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(
+        DeviceJUnit4ClassRunnerWithParameters.RunnerFactory::class)
+class PackageSetInstallerTest : BaseAppSecurityTest() {
+
+    companion object {
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "{1}")
+        fun parameters() = arrayOf(
+                arrayOf(true, "throwException"),
+                arrayOf(false, "failSilently")
+        )
+    }
+
+    @JvmField
+    @Parameterized.Parameter(0)
+    var failSilently = false
+
+    @Parameterized.Parameter(1)
+    lateinit var testName: String
+
+    @Before
+    @After
+    fun uninstallTestPackages() {
+        device.uninstallPackage(TARGET_PKG)
+        device.uninstallPackage(WHITELIST_PKG)
+    }
+
+    @After
+    fun resetChanges() {
+        device.executeShellCommand("am compat reset $CHANGE_ID $TARGET_PKG")
+        device.executeShellCommand("am compat reset $CHANGE_ID $WHITELIST_PKG")
+    }
+
+    @Before
+    fun initializeChangeState() {
+        if (failSilently) {
+            device.executeShellCommand("am compat disable $CHANGE_ID $TARGET_PKG")
+            device.executeShellCommand("am compat disable $CHANGE_ID $WHITELIST_PKG")
+        } else {
+            resetChanges()
+        }
+    }
+
+    @Test
+    fun notRestricted() {
+        runTest(removeWhitelistShouldSucceed = false,
+                permission = PERMISSION_NOT_RESTRICTED,
+                finalState = GrantState.TRUE)
+    }
+
+    @Test
+    fun hardRestricted() {
+        runTest(removeWhitelistShouldSucceed = true,
+                permission = PERMISSION_HARD_RESTRICTED,
+                finalState = GrantState.FALSE)
+    }
+
+    @Test
+    fun immutablySoftRestrictedGranted() {
+        runTest(removeWhitelistShouldSucceed = null,
+                permission = PERMISSION_IMMUTABLY_SOFT_RESTRICTED,
+                finalState = GrantState.TRUE_EXEMPT)
+    }
+
+    @Test
+    fun immutablySoftRestrictedRevoked() {
+        runTest(removeWhitelistShouldSucceed = null,
+                permission = PERMISSION_IMMUTABLY_SOFT_RESTRICTED,
+                restrictPermissions = true,
+                finalState = GrantState.TRUE_RESTRICTED)
+    }
+
+    private fun runTest(
+        removeWhitelistShouldSucceed: Boolean?,
+        permission: String,
+        restrictPermissions: Boolean = false,
+        finalState: GrantState
+    ) {
+        // Verifies throwing a SecurityException or failing silently for backwards compatibility
+        val testArgs: Map<String, String?> = mapOf(
+                PERMISSION_KEY to permission
+        )
+
+        // First, install both packages and ensure no installer is set
+        InstallMultiple(false, false)
+                .addFile(TARGET_APK)
+                .allowTest()
+                .forUser(mPrimaryUserId)
+                .apply {
+                    if (restrictPermissions) {
+                        restrictPermissions()
+                    }
+                }
+                .run()
+
+        InstallMultiple(false, false)
+                .addFile(WHITELIST_APK)
+                .allowTest()
+                .forUser(mPrimaryUserId)
+                .run()
+
+        assertPermission(false, permission)
+        assertTargetInstaller(null)
+
+        // Install the installer whitelist app and take over the installer package. This methods
+        // adopts the INSTALL_PACKAGES permission and verifies that the new behavior of checking
+        // this permission is applied.
+        Utils.runDeviceTests(device, WHITELIST_PKG, ".PermissionWhitelistTest",
+                "setTargetInstallerPackage", mPrimaryUserId,
+                testArgs.plus(SHOULD_THROW_EXCEPTION_KEY to (!failSilently).toString()))
+        assertTargetInstaller(WHITELIST_PKG)
+
+        // Verify that without whitelist restriction, the target app can be granted the permission
+        grantPermission(permission)
+        assertPermission(true, permission)
+        revokePermission(permission)
+        assertPermission(false, permission)
+
+        val whitelistArgs = testArgs
+                .plus(SHOULD_SUCCEED_KEY to removeWhitelistShouldSucceed?.toString())
+                .filterValues { it != null }
+
+        // Now restrict the permission from the target app using the whitelist app
+        Utils.runDeviceTests(device, WHITELIST_PKG, ".PermissionWhitelistTest",
+                "removeWhitelistRestrictedPermission", mPrimaryUserId, whitelistArgs)
+
+        // Now remove the installer and verify the installer is wiped
+        device.uninstallPackage(WHITELIST_PKG)
+        assertTargetInstaller(null)
+
+        // Verify whitelist restriction retained by attempting and failing to grant permission
+        assertPermission(false, permission)
+        grantPermission(permission)
+        assertGrantState(finalState, permission)
+        revokePermission(permission)
+
+        // Attempt exploit to take over installer package and have target whitelist itself
+        Utils.runDeviceTests(device, TARGET_PKG, ".PermissionRequestTest",
+                "setSelfAsInstallerAndWhitelistPermission", mPrimaryUserId,
+                testArgs.plus(SHOULD_THROW_EXCEPTION_KEY to (!failSilently).toString()))
+
+        // Assert nothing changed about whitelist restriction
+        assertTargetInstaller(null)
+        grantPermission(permission)
+        assertGrantState(finalState, permission)
+    }
+
+    private fun assertTargetInstaller(installer: String?) {
+        assertThat(device.executeShellCommand("pm list packages -i | grep $TARGET_PKG").trim())
+                .isEqualTo("package:$TARGET_PKG  installer=$installer")
+    }
+
+    private fun assertPermission(granted: Boolean, permission: String) {
+        assertThat(device.executeShellCommand("dumpsys package $TARGET_PKG | grep $permission"))
+                .contains("$permission: granted=$granted")
+    }
+
+    private fun grantPermission(permission: String) {
+        device.executeShellCommand("pm grant $TARGET_PKG $permission")
+    }
+
+    private fun revokePermission(permission: String) {
+        device.executeShellCommand("pm revoke $TARGET_PKG $permission")
+    }
+
+    private fun assertGrantState(state: GrantState, permission: String) {
+        val output = device.executeShellCommand(
+                "dumpsys package $TARGET_PKG | grep \"$permission: granted\"").trim()
+
+        // Make sure only the expected output line is returned
+        assertWithMessage(output).that(output.lines().size).isEqualTo(1)
+
+        when (state) {
+            GrantState.TRUE -> {
+                assertThat(output).contains("granted=true")
+                assertThat(output).doesNotContain("RESTRICTION")
+                assertThat(output).doesNotContain("EXEMPT")
+            }
+            GrantState.TRUE_EXEMPT -> {
+                assertThat(output).contains("granted=true")
+                assertThat(output).contains("RESTRICTION_INSTALLER_EXEMPT")
+            }
+            GrantState.TRUE_RESTRICTED -> {
+                assertThat(output).contains("granted=true")
+                assertThat(output).contains("APPLY_RESTRICTION")
+                assertThat(output).doesNotContain("EXEMPT")
+            }
+            GrantState.FALSE -> {
+                assertThat(output).contains("granted=false")
+            }
+        }
+    }
+
+    enum class GrantState {
+        // Granted in full, unrestricted
+        TRUE,
+
+        // Granted in full by exemption
+        TRUE_EXEMPT,
+
+        // Granted in part
+        TRUE_RESTRICTED,
+
+        // Not granted at all
+        FALSE
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
index 0886269..987efde 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
@@ -78,6 +78,9 @@
     private ContentResolver mContentResolver;
     private int mUserId;
 
+    private static int currentAttempt = 0;
+    private static final int MAX_NUMBER_OF_ATTEMPT = 10;
+
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
@@ -545,9 +548,19 @@
         runShellCommand(InstrumentationRegistry.getInstrumentation(), cmd);
     }
 
-    static File stageFile(File file) throws IOException {
-        file.getParentFile().mkdirs();
-        file.createNewFile();
+    static File stageFile(File file) throws Exception {
+        // Sometimes file creation fails due to slow permission update, try more times 
+        while(currentAttempt < MAX_NUMBER_OF_ATTEMPT) {
+            try {
+                file.getParentFile().mkdirs();
+                file.createNewFile();
+                return file;
+            } catch(IOException e) {
+                currentAttempt++;
+                // wait 500ms
+                Thread.sleep(500);
+            }
+        } 
         return file;
     }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/Android.bp b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/Android.bp
new file mode 100644
index 0000000..990ef49
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/Android.bp
@@ -0,0 +1,40 @@
+// 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: "CtsPkgInstallerPermRequestApp",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "androidx.test.rules",
+        "truth-prebuilt",
+        "CtsPkgInstallerConstants",
+    ],
+    srcs: ["src/**/*.kt"],
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+    target_sdk_version: "30",
+    // sign this app with a different cert than CtsPkgInstallerPermWhitelistApp
+    certificate: ":cts-testkey2",
+}
+
+java_library {
+    name: "CtsPkgInstallerConstants",
+    srcs: ["utils/src/**/PackageSetInstallerConstants.kt"],
+    host_supported: true,
+}
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/AndroidManifest.xml
new file mode 100644
index 0000000..7d0ab56
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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="com.android.cts.packageinstallerpermissionrequestapp">
+
+    <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.packageinstallerpermissionrequestapp"
+                     android:label="Test for unset package installer permission exploit."/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/src/com/android/cts/packageinstallerpermissionrequestapp/PermissionRequestTest.kt b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/src/com/android/cts/packageinstallerpermissionrequestapp/PermissionRequestTest.kt
new file mode 100644
index 0000000..1ca6a7f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/src/com/android/cts/packageinstallerpermissionrequestapp/PermissionRequestTest.kt
@@ -0,0 +1,78 @@
+/*
+ * 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 com.android.cts.packageinstallerpermissionrequestapp
+
+import android.Manifest
+import android.appsecurity.cts.PackageSetInstallerConstants
+import android.appsecurity.cts.PackageSetInstallerConstants.SHOULD_THROW_EXCEPTION_KEY
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Bundle
+import androidx.test.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+
+class PermissionRequestTest {
+
+    @get:Rule
+    val expectedException = ExpectedException.none()
+
+    private val arguments: Bundle = InstrumentationRegistry.getArguments()
+    private val permission = arguments.getString(PackageSetInstallerConstants.PERMISSION_KEY)!!
+    private val context: Context = InstrumentationRegistry.getContext()
+    private val packageName = context.packageName
+    private val packageManager = context.packageManager
+
+    @Before
+    @After
+    fun verifyPermissionsDeniedAndInstallerUnchanged() {
+        assertThat(context.checkSelfPermission(permission))
+                .isEqualTo(PackageManager.PERMISSION_DENIED)
+        assertThat(context.checkSelfPermission(Manifest.permission.INSTALL_PACKAGES))
+                .isEqualTo(PackageManager.PERMISSION_DENIED)
+        assertThat(packageManager.getInstallerPackageName(packageName))
+                .isEqualTo(null)
+    }
+
+    @Test
+    fun setSelfAsInstallerAndWhitelistPermission() {
+        val shouldThrowException = arguments.getString(SHOULD_THROW_EXCEPTION_KEY)!!.toBoolean()
+        if (shouldThrowException) {
+            expectedException.expect(SecurityException::class.java)
+        }
+
+        try {
+            // This set call should fail
+            packageManager.setInstallerPackageName(packageName, packageName)
+        } finally {
+            // But also call the whitelist method to attempt to take the permission regardless.
+            // If this fails, which it should, it should also be a SecurityException.
+            try {
+                packageManager.addWhitelistedRestrictedPermission(packageName,
+                        permission, PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)
+                Assert.fail("addWhitelistedRestrictedPermission did not throw SecurityException")
+            } catch (ignored: SecurityException) {
+                // Ignore this to defer to shouldThrowException from above call
+            }
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/utils/src/android/appsecurity/cts/PackageSetInstallerConstants.kt b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/utils/src/android/appsecurity/cts/PackageSetInstallerConstants.kt
new file mode 100644
index 0000000..723cb94
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerPermissionRequestApp/utils/src/android/appsecurity/cts/PackageSetInstallerConstants.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.appsecurity.cts
+
+// Placed in CtsPkgInstallerPermRequestApp sources as its manifest declares what permissions to test
+object PackageSetInstallerConstants {
+
+    // The app that will be attempting to take over as installer and grant itself permissions
+    const val TARGET_APK = "CtsPkgInstallerPermRequestApp.apk"
+    const val TARGET_PKG = "com.android.cts.packageinstallerpermissionrequestapp"
+
+    // The app acting as the original installer who can restrict permissions
+    const val WHITELIST_APK = "CtsPkgInstallerPermWhitelistApp.apk"
+    const val WHITELIST_PKG = "com.android.cts.packageinstallerpermissionwhitelistapp"
+
+    const val PERMISSION_HARD_RESTRICTED = "android.permission.SEND_SMS"
+    const val PERMISSION_NOT_RESTRICTED = "android.permission.ACCESS_COARSE_LOCATION"
+    const val PERMISSION_IMMUTABLY_SOFT_RESTRICTED = "android.permission.READ_EXTERNAL_STORAGE"
+    const val PERMISSION_KEY = "permission"
+
+    // Whether setInstallerPackageName should throw
+    const val SHOULD_THROW_EXCEPTION_KEY = "shouldThrowException"
+
+    // Whether or not some boolean return method call should succeed
+    const val SHOULD_SUCCEED_KEY = "shouldSucceed"
+
+    // PackageManagerService.THROW_EXCEPTION_ON_REQUIRE_INSTALL_PACKAGES_TO_ADD_INSTALLER_PACKAGE
+    const val CHANGE_ID = 150857253
+}
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/Android.bp b/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/Android.bp
new file mode 100644
index 0000000..b731a05
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/Android.bp
@@ -0,0 +1,35 @@
+// 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: "CtsPkgInstallerPermWhitelistApp",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "androidx.test.rules",
+        "compatibility-device-util-axt",
+        "CtsPkgInstallerConstants",
+        "testng",
+    ],
+    srcs: ["src/**/*.kt"],
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+    target_sdk_version: "30",
+    // sign this app with a different cert than CtsPkgInstallerPermRequestApp
+    certificate: ":cts-testkey1",
+}
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/AndroidManifest.xml
new file mode 100644
index 0000000..d54b9c5
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?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="com.android.cts.packageinstallerpermissionwhitelistapp">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.packageinstallerpermissionwhitelistapp"
+                     android:label="Test for unset package installer permission exploit."/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/src/com/android/cts/packageinstallerpermissionwhitelistapp/PermissionWhitelistTest.kt b/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/src/com/android/cts/packageinstallerpermissionwhitelistapp/PermissionWhitelistTest.kt
new file mode 100644
index 0000000..464047e
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PackageInstallerWhitelistApp/src/com/android/cts/packageinstallerpermissionwhitelistapp/PermissionWhitelistTest.kt
@@ -0,0 +1,100 @@
+/*
+ * 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 com.android.cts.packageinstallerpermissionwhitelistapp
+
+import android.Manifest
+import android.appsecurity.cts.PackageSetInstallerConstants
+import android.appsecurity.cts.PackageSetInstallerConstants.PERMISSION_KEY
+import android.appsecurity.cts.PackageSetInstallerConstants.SHOULD_THROW_EXCEPTION_KEY
+import android.appsecurity.cts.PackageSetInstallerConstants.TARGET_PKG
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Bundle
+import androidx.test.InstrumentationRegistry
+import com.android.compatibility.common.util.ShellIdentityUtils
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.testng.Assert.assertThrows
+
+class PermissionWhitelistTest {
+
+    private val arguments: Bundle = InstrumentationRegistry.getArguments()
+    private val shouldThrowException = arguments.getString(SHOULD_THROW_EXCEPTION_KEY)
+            ?.toBoolean() ?: false
+    private val permission = arguments.getString(PERMISSION_KEY)!!
+    private val context: Context = InstrumentationRegistry.getContext()
+    private val packageName = context.packageName
+    private val packageManager = context.packageManager
+
+    @Before
+    fun verifyNoInstallPackagesPermissions() {
+        // This test adopts shell permissions to get INSTALL_PACKAGES. That ensures that the
+        // whitelist package having INSTALL_PACKAGES doesn't bypass any checks. In a realistic
+        // scenario, this whitelisting app would request install, not directly install the target
+        // package.
+        assertThat(context.checkSelfPermission(Manifest.permission.INSTALL_PACKAGES))
+                .isEqualTo(PackageManager.PERMISSION_DENIED)
+    }
+
+    @Test
+    fun setTargetInstallerPackage() {
+        assertTargetInstaller(null)
+
+        val block = {
+            packageManager.setInstallerPackageName(TARGET_PKG, packageName)
+        }
+
+        if (shouldThrowException) {
+            assertThrows(SecurityException::class.java) { block() }
+        } else {
+            block()
+        }
+
+        assertTargetInstaller(null)
+
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(packageManager,
+                ShellIdentityUtils.ShellPermissionMethodHelperNoReturn {
+                    it.setInstallerPackageName(TARGET_PKG, packageName)
+                }, Manifest.permission.INSTALL_PACKAGES)
+        assertTargetInstaller(packageName)
+    }
+
+    @Test
+    fun removeWhitelistRestrictedPermission() {
+        val block = {
+            packageManager.removeWhitelistedRestrictedPermission(TARGET_PKG, permission,
+                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)
+        }
+
+        val shouldSucceed = arguments.getString(
+                PackageSetInstallerConstants.SHOULD_SUCCEED_KEY)
+        if (shouldSucceed == null) {
+            assertThrows(SecurityException::class.java) { block() }
+        } else {
+            assertThat(block()).isEqualTo(shouldSucceed.toBoolean())
+        }
+
+        assertThat(packageManager.checkPermission(permission, TARGET_PKG))
+                .isEqualTo(PackageManager.PERMISSION_DENIED)
+    }
+
+    private fun assertTargetInstaller(installer: String?) {
+        assertThat(packageManager.getInstallerPackageName(TARGET_PKG))
+                .isEqualTo(installer)
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
index 6a7aa7e..c16d7f3 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -115,7 +115,13 @@
         assertFalse(probe.exists());
         assertTrue(probe.mkdirs());
 
-        assertDirReadWriteAccess(probe);
+        try {
+            assertDirReadWriteAccess(probe);
+        }
+        finally {
+            probe.delete();
+            assertFalse(probe.exists());
+        }
     }
 
     /**
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 9c46c5f..d9fc9eb 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -913,7 +913,7 @@
 
     @Test
     public void testDefaultSmsApplication() throws Exception {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephony) {
             return;
         }
 
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 6a9eed4..fb4c5e9 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -57,17 +57,6 @@
             DEVICE_OWNER_PKG + ".BaseDeviceOwnerTest$BasicAdminReceiver";
 
     @Test
-    public void testManagedProfilesSupportedWithLockScreenOnly() throws Exception {
-        if (!mHasFeature || hasDeviceFeature("android.software.leanback")) {
-            return;
-        }
-        // Managed profiles should be only supported if the device supports the secure lock
-        // screen feature.
-        // Exception is Android TV which does not support lock screen feature.
-        assertTrue(mHasSecureLockScreen);
-    }
-
-    @Test
     public void testManagedProfileSetup() throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index 98e1c59..e3cbad8 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -253,10 +253,13 @@
         try {
             runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".DeviceFeatureUtils",
                     "testHasFactoryResetProtectionPolicy", mUserId);
-        } catch (Exception e) {
+        } catch (AssertionError e) {
             // Unable to continue running tests because factory reset protection policy is not
             // supported on the device
             return;
+        } catch (Exception e) {
+            // Also skip test in case of other exceptions
+            return;
         }
 
         assertMetricsLogged(getDevice(), () -> {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index acb524b..f575fc7 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -474,7 +474,7 @@
 
     @Test
     public void testPersonalAppsSuspensionSms() throws Exception {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephony) {
             return;
         }
 
diff --git a/hostsidetests/media/Android.bp b/hostsidetests/media/Android.bp
index 3e85112..635c5c2 100644
--- a/hostsidetests/media/Android.bp
+++ b/hostsidetests/media/Android.bp
@@ -33,6 +33,10 @@
         "tradefed",
         "compatibility-host-util",
     ],
+
+    static_libs: [
+        "cts-host-utils",
+    ],
 }
 
 filegroup {
diff --git a/hostsidetests/media/bitstreams/Android.bp b/hostsidetests/media/bitstreams/Android.bp
index 9c17208..f13984e 100644
--- a/hostsidetests/media/bitstreams/Android.bp
+++ b/hostsidetests/media/bitstreams/Android.bp
@@ -22,6 +22,9 @@
         "cts-tradefed",
         "tradefed",
     ],
+    static_libs: [
+        "cts-host-utils",
+    ],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsFullTest.java
index 72bb15a..0c18703 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsTest.java
index 5bcfe7e..6ca00d8 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitBpBitstreamsTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsFullTest.java
index 7db0198f..3dd9b35 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsTest.java
index 6ba3822..7c06151 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitHpBitstreamsTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsFullTest.java
index 4811150..1634856 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsTest.java
index b7f2c67..90e9bdf 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/H264Yuv420_8bitMpBitstreamsTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv400BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv400BitstreamsFullTest.java
index e00283f..50e9924 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv400BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv400BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsFullTest.java
index eb0fda7..b7a752d 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsTest.java
index 1334c82..7d8b289 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv420BitstreamsTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv422BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv422BitstreamsFullTest.java
index 0efdad2..528eefb 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv422BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv422BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv444BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv444BitstreamsFullTest.java
index 0f564ea..94bad70 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv444BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/HevcYuv444BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsFullTest.java
index bbfc2eb..7146d94 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsTest.java
index 8587abd..679850a 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp8BitstreamsTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsFullTest.java
index d209011..656ea21 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsTest.java
index 9b048bb..b80ff7f 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv420BitstreamsTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv422BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv422BitstreamsFullTest.java
index a03f1c4..3dda21a 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv422BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv422BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv444BitstreamsFullTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv444BitstreamsFullTest.java
index 22786fc..bf6b095 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv444BitstreamsFullTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/Vp9Yuv444BitstreamsFullTest.java
@@ -15,6 +15,9 @@
  */
 package android.media.cts.bitstreams;
 
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
diff --git a/hostsidetests/rollback/app/AndroidManifest.xml b/hostsidetests/rollback/app/AndroidManifest.xml
index 9d4d5d2..71cf5c1 100644
--- a/hostsidetests/rollback/app/AndroidManifest.xml
+++ b/hostsidetests/rollback/app/AndroidManifest.xml
@@ -17,7 +17,11 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.cts.rollback.host.app" >
 
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+    <queries>
+        <package android:name="com.android.cts.ctsshim" />
+        <package android:name="com.android.cts.priv.ctsshim" />
+    </queries>
+
     <application>
         <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
                   android:exported="true" />
diff --git a/hostsidetests/rollback/app2/AndroidManifest.xml b/hostsidetests/rollback/app2/AndroidManifest.xml
index 3105857..be6d483 100644
--- a/hostsidetests/rollback/app2/AndroidManifest.xml
+++ b/hostsidetests/rollback/app2/AndroidManifest.xml
@@ -17,7 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.cts.rollback.host.app2" >
 
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
     <application>
         <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
                   android:exported="true" />
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
index 7c2bf54..4ca2e12 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
@@ -176,4 +176,9 @@
     public void testCanRenameAFileWithNoDBRow_hasRW() throws Exception {
         runDeviceTest("testCanRenameAFileWithNoDBRow_hasRW");
     }
+
+    @Test
+    public void testCaseInsensitivity() throws Exception {
+        runDeviceTest("testAndroidDataObbCannotBeDeleted");
+    }
 }
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index c380d1a..d0f2b16 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -165,6 +165,7 @@
         runDeviceTest("testCreateLowerCaseDeleteUpperCase");
         runDeviceTest("testCreateUpperCaseDeleteLowerCase");
         runDeviceTest("testCreateMixedCaseDeleteDifferentMixedCase");
+        runDeviceTest("testAndroidDataObbDoesNotForgetMount");
     }
 
     @Test
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
index 67a8fec..251f65a 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -617,6 +617,25 @@
         }
     }
 
+    @Test
+    public void testAndroidDataObbCannotBeDeleted() throws Exception {
+        File canDeleteDir = new File("/sdcard/canDelete");
+        canDeleteDir.mkdirs();
+
+        File dataDir = new File("/sdcard/Android/data");
+        File obbDir = new File("/sdcard/Android/obb");
+        File androidDir = new File("/sdcard/Android");
+
+        assertThat(dataDir.exists()).isTrue();
+        assertThat(obbDir.exists()).isTrue();
+        assertThat(androidDir.exists()).isTrue();
+
+        assertThat(dataDir.delete()).isFalse();
+        assertThat(obbDir.delete()).isFalse();
+        assertThat(androidDir.delete()).isFalse();
+        assertThat(canDeleteDir.delete()).isTrue();
+    }
+
     private static void assertCanCreateFile(File file) throws IOException {
         if (file.exists()) {
             file.delete();
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index 4022fb5..bd75bcf 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -121,6 +121,7 @@
 import android.provider.MediaStore;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.system.StructStat;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
@@ -1000,6 +1001,30 @@
         createDeleteCreate(mixedCase1, mixedCase2);
     }
 
+    @Test
+    public void testAndroidDataObbDoesNotForgetMount() throws Exception {
+        File dataDir = getContext().getExternalFilesDir(null);
+        File upperCaseDataDir = new File(dataDir.getPath().replace("Android/data", "ANDROID/DATA"));
+
+        File obbDir = getContext().getObbDir();
+        File upperCaseObbDir = new File(obbDir.getPath().replace("Android/obb", "ANDROID/OBB"));
+
+
+        StructStat beforeDataStruct = Os.stat(dataDir.getPath());
+        StructStat beforeObbStruct = Os.stat(obbDir.getPath());
+
+        assertThat(dataDir.exists()).isTrue();
+        assertThat(upperCaseDataDir.exists()).isTrue();
+        assertThat(obbDir.exists()).isTrue();
+        assertThat(upperCaseObbDir.exists()).isTrue();
+
+        StructStat afterDataStruct = Os.stat(upperCaseDataDir.getPath());
+        StructStat afterObbStruct = Os.stat(upperCaseObbDir.getPath());
+
+        assertThat(beforeDataStruct.st_dev).isEqualTo(afterDataStruct.st_dev);
+        assertThat(beforeObbStruct.st_dev).isEqualTo(afterObbStruct.st_dev);
+    }
+
     private void createDeleteCreate(File create, File delete) throws Exception {
         try {
             assertThat(create.createNewFile()).isTrue();
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 1d4981b..6d9454f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -144,7 +144,7 @@
      */
     public static void runPoc(String pocName, ITestDevice device, int timeout,
             String arguments, IShellOutputReceiver receiver) throws Exception {
-        device.executeShellCommand("chmod +x " + TMP_PATH + pocName);
+        assertPocExecutable(pocName, device);
         if (receiver == null) {
             receiver = new NullOutputReceiver();
         }
@@ -156,6 +156,22 @@
     }
 
     /**
+     * Assert the poc is executable
+     * @param pocName name of the poc binary
+     * @param device device to be ran on
+     */
+    private static void assertPocExecutable(String pocName, ITestDevice device) throws Exception {
+        String fullPocPath = TMP_PATH + pocName;
+        device.executeShellCommand("chmod 777 " + fullPocPath);
+        assertEquals("'" + pocName + "' must exist and be readable.", 0,
+                runCommandGetExitCode("test -r " + fullPocPath, device));
+        assertEquals("'" + pocName + "'poc must exist and be writable.", 0,
+                runCommandGetExitCode("test -w " + fullPocPath, device));
+        assertEquals("'" + pocName + "'poc must exist and be executable.", 0,
+                runCommandGetExitCode("test -x " + fullPocPath, device));
+    }
+
+    /**
      * Enables malloc debug on a given process.
      *
      * @param processName the name of the process to run with libc malloc debug
@@ -340,7 +356,7 @@
      */
     public static int runPocGetExitStatus(String pocName, String arguments, ITestDevice device,
             int timeout) throws Exception {
-        device.executeShellCommand("chmod +x " + TMP_PATH + pocName);
+        assertPocExecutable(pocName, device);
         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
         String cmd = TMP_PATH + pocName + " " + arguments + " > /dev/null 2>&1; echo $?";
         long time = System.currentTimeMillis();
@@ -391,7 +407,7 @@
         String targetPath = TMP_PATH + pacName;
         AdbUtils.pushResource("/" + pacName, targetPath, device);
         runPocAssertNoCrashes(
-                TMP_PATH + "pacrunner", device, targetPath,
+                "pacrunner", device, targetPath,
                 new CrashUtils.Config().setProcessPatterns("pacrunner"));
         runCommandLine("rm " + targetPath, device);
         return 0; // b/157172329 fix tests that manually check the result; remove return statement
diff --git a/hostsidetests/stagedinstall/app/AndroidManifest.xml b/hostsidetests/stagedinstall/app/AndroidManifest.xml
index bc8bb0b..ebe83e6 100644
--- a/hostsidetests/stagedinstall/app/AndroidManifest.xml
+++ b/hostsidetests/stagedinstall/app/AndroidManifest.xml
@@ -17,7 +17,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.tests.stagedinstall" >
 
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+    <queries>
+        <package android:name="com.android.cts.ctsshim" />
+    </queries>
+
     <application>
         <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
                   android:exported="true" />
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
index 1ce2daf..a7922db 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -969,6 +969,47 @@
         assertThat(getInstalledVersion(TestApp.B)).isEqualTo(-1);
     }
 
+    // Failure reason of staged install should be be persisted for single sessions
+    @Test
+    public void testFailureReasonPersists_SingleSession_Commit() throws Exception {
+        int sessionId = Install.single(TestApp.A1).setStaged().commit();
+        // Install TestApp.A2 so that after reboot TestApp.A1 fails to install as it is downgrade
+        Install.single(TestApp.A2).commit();
+        assertThat(getInstalledVersion(TestApp.A)).isEqualTo(2);
+        storeSessionId(sessionId);
+    }
+
+    @Test
+    public void testFailureReasonPersists_SingleSession_VerifyPostReboot() throws Exception {
+        int sessionId = retrieveLastSessionId();
+        assertSessionFailedWithMessage(sessionId, "Failed to install sessionId: " + sessionId);
+        assertThat(getInstalledVersion(TestApp.A)).isEqualTo(2);
+    }
+
+    // If apk installation fails in one staged session, then all staged session should fail.
+    @Test
+    public void testFailureReasonPersists_MultipleSession_Commit() throws Exception {
+        int firstSessionId = Install.single(TestApp.A1).setStaged().commit();
+        int secondSessionId = Install.single(TestApp.B1).setStaged().commit();
+        // Install TestApp.A2 so that after reboot TestApp.A1 fails to install as it is downgrade
+        Install.single(TestApp.A2).commit();
+        assertThat(getInstalledVersion(TestApp.A)).isEqualTo(2);
+        assertThat(getInstalledVersion(TestApp.B)).isEqualTo(-1);
+        storeSessionIds(Arrays.asList(firstSessionId, secondSessionId));
+    }
+
+    @Test
+    public void testFailureReasonPersists_MultipleSession_VerifyPostReboot() throws Exception {
+        List<Integer> sessionIds = retrieveLastSessionIds();
+        int failingSessionId = sessionIds.get(0);
+        for (int sessionId: sessionIds) {
+            assertSessionFailedWithMessage(sessionId, "Failed to install sessionId: "
+                    + failingSessionId);
+        }
+        assertThat(getInstalledVersion(TestApp.A)).isEqualTo(2);
+        assertThat(getInstalledVersion(TestApp.B)).isEqualTo(-1);
+    }
+
     @Test
     public void testSamegradeSystemApex_Commit() throws Exception {
         final PackageInfo shim = InstrumentationRegistry.getInstrumentation().getContext()
@@ -1206,6 +1247,13 @@
                 (session) -> assertThat(session).isStagedSessionFailed());
     }
 
+    private static void assertSessionFailedWithMessage(int sessionId, String msg) {
+        assertSessionState(sessionId, (session) -> {
+            assertThat(session).isStagedSessionFailed();
+            assertThat(session.getStagedSessionErrorMessage()).contains(msg);
+        });
+    }
+
     private static void assertSessionState(
             int sessionId, Consumer<PackageInstaller.SessionInfo> assertion) {
         PackageInstaller packageInstaller = getPackageInstaller();
diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
index 06bbed8..54d735c 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
@@ -520,6 +520,25 @@
         runPhase("testInstallMultipleStagedSession_PartialFail_ApkOnly_VerifyPostReboot");
     }
 
+    // Failure reason of staged install should be be persisted for single sessions
+    @Test
+    @LargeTest
+    public void testFailureReasonPersists_SingleSession() throws Exception {
+        runPhase("testFailureReasonPersists_SingleSession_Commit");
+        getDevice().reboot();
+        runPhase("testFailureReasonPersists_SingleSession_VerifyPostReboot");
+    }
+
+    // Failure reason of staged install should be be persisted for multi session staged install
+    @Test
+    @LargeTest
+    public void testFailureReasonPersists_MultiSession() throws Exception {
+        assumeTrue(isCheckpointSupported());
+        runPhase("testFailureReasonPersists_MultipleSession_Commit");
+        getDevice().reboot();
+        runPhase("testFailureReasonPersists_MultipleSession_VerifyPostReboot");
+    }
+
     @Test
     @LargeTest
     public void testSamegradeSystemApex() throws Exception {
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index d02dcfd..1fde1b6 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -326,13 +326,15 @@
 
         getDevice().executeShellCommand(
                 "device_config put app_compat hidden_api_access_statslog_sampling_rate 65536");
+
+        Thread.sleep(WAIT_TIME_SHORT);
+
         try {
             final int atomTag = Atom.HIDDEN_API_USED_FIELD_NUMBER;
 
             createAndUploadConfig(atomTag, false);
 
-            runActivity("HiddenApiUsedActivity", null, null);
-
+            runActivity("HiddenApiUsedActivity", null, null, 2_500);
 
             List<EventMetricData> data = getEventMetricDataList();
             assertThat(data).hasSize(1);
diff --git a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDefaultTest.java b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDefaultTest.java
index 6e99c4e..266c60b 100644
--- a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDefaultTest.java
+++ b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDefaultTest.java
@@ -31,6 +31,11 @@
         installPackage(TEST_APK, true);
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        uninstallPackage(TEST_PKG, true);
+    }
+
     public void testCompatFeatureEnabled() throws Exception {
         if (supportsTaggedPointers) {
             runDeviceCompatTest(TEST_PKG, ".TaggingTest", "testHeapTaggingEnabled",
diff --git a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDisabledTest.java b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDisabledTest.java
index 50d6df3..fcbd905 100644
--- a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDisabledTest.java
+++ b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingDisabledTest.java
@@ -31,6 +31,11 @@
         installPackage(TEST_APK, true);
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        uninstallPackage(TEST_PKG, true);
+    }
+
     public void testCompatFeatureEnabled() throws Exception {
         // Checking for supportsTaggedPointers is unnecessary here, as we don't
         // validate against reportDisabledChanges.
diff --git a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingEnabledTest.java b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingEnabledTest.java
index 6b31626..a578e50 100644
--- a/hostsidetests/tagging/src/com/android/cts/tagging/TaggingEnabledTest.java
+++ b/hostsidetests/tagging/src/com/android/cts/tagging/TaggingEnabledTest.java
@@ -31,6 +31,11 @@
         installPackage(TEST_APK, true);
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        uninstallPackage(TEST_PKG, true);
+    }
+
     public void testCompatFeatureEnabled() throws Exception {
         if (!supportsTaggedPointers) {
             return;
diff --git a/hostsidetests/utils/Android.bp b/hostsidetests/utils/Android.bp
new file mode 100644
index 0000000..0930f91
--- /dev/null
+++ b/hostsidetests/utils/Android.bp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+java_library_host {
+    name: "cts-host-utils",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    libs: [
+        "cts-tradefed",
+        "tradefed",
+    ],
+}
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java b/hostsidetests/utils/src/android/cts/host/utils/DeviceJUnit4ClassRunnerWithParameters.java
similarity index 97%
rename from hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java
rename to hostsidetests/utils/src/android/cts/host/utils/DeviceJUnit4ClassRunnerWithParameters.java
index 944e258..7f8e07e 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java
+++ b/hostsidetests/utils/src/android/cts/host/utils/DeviceJUnit4ClassRunnerWithParameters.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.cts.bitstreams;
+package android.cts.host.utils;
 
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java b/hostsidetests/utils/src/android/cts/host/utils/DeviceJUnit4Parameterized.java
similarity index 97%
rename from hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java
rename to hostsidetests/utils/src/android/cts/host/utils/DeviceJUnit4Parameterized.java
index ea7ce7f..114678d 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java
+++ b/hostsidetests/utils/src/android/cts/host/utils/DeviceJUnit4Parameterized.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.cts.bitstreams;
+package android.cts.host.utils;
 
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.ConfigurationException;
diff --git a/libs/install/testapp/ACrashingV2.xml b/libs/install/testapp/ACrashingV2.xml
index 338a5b9..0ec90cf 100644
--- a/libs/install/testapp/ACrashingV2.xml
+++ b/libs/install/testapp/ACrashingV2.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A v2">
+    <application android:label="Test App A v2" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
                   android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.CrashingMainActivity">
diff --git a/libs/install/testapp/Av1.xml b/libs/install/testapp/Av1.xml
index e9714fc..5b47699 100644
--- a/libs/install/testapp/Av1.xml
+++ b/libs/install/testapp/Av1.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A1">
+    <application android:label="Test App A1" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
                   android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Av2.xml b/libs/install/testapp/Av2.xml
index fd8afa0..9f2c21a 100644
--- a/libs/install/testapp/Av2.xml
+++ b/libs/install/testapp/Av2.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A2">
+    <application android:label="Test App A2" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Av3.xml b/libs/install/testapp/Av3.xml
index a7839e3..d86aebd 100644
--- a/libs/install/testapp/Av3.xml
+++ b/libs/install/testapp/Av3.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A3">
+    <application android:label="Test App A3" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Bv1.xml b/libs/install/testapp/Bv1.xml
index 403e7e2..f990713 100644
--- a/libs/install/testapp/Bv1.xml
+++ b/libs/install/testapp/Bv1.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App B1">
+    <application android:label="Test App B1" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Bv2.xml b/libs/install/testapp/Bv2.xml
index f030c3f..3bd7292 100644
--- a/libs/install/testapp/Bv2.xml
+++ b/libs/install/testapp/Bv2.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App B2">
+    <application android:label="Test App B2" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Cv1.xml b/libs/install/testapp/Cv1.xml
index edb69f9..32f6989 100644
--- a/libs/install/testapp/Cv1.xml
+++ b/libs/install/testapp/Cv1.xml
@@ -23,7 +23,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App C1">
+    <application android:label="Test App C1" android:forceQueryable="true">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 255001a..6091924 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -2860,6 +2860,7 @@
     }
 
     @Test
+    @AppModeFull(reason = "WRITE_SECURE_SETTING permission can't be grant to instant apps")
     public void testSwitchInputMethod_noNewFillRequest() throws Exception {
         // Set service
         enableService();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedLoginActivityTest.java
index 47664de..75c1042 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedLoginActivityTest.java
@@ -34,6 +34,7 @@
 import android.autofillservice.cts.augmented.CannedAugmentedFillResponse;
 import android.autofillservice.cts.augmented.CtsAugmentedAutofillService;
 import android.autofillservice.cts.augmented.CtsAugmentedAutofillService.AugmentedFillRequest;
+import android.platform.test.annotations.AppModeFull;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.FillEventHistory.Event;
 import android.view.autofill.AutofillId;
@@ -284,6 +285,7 @@
     }
 
     @Test
+    @AppModeFull(reason = "WRITE_SECURE_SETTING permission can't be grant to instant apps")
     public void testSwitchInputMethod() throws Exception {
         // Set services
         enableService();
@@ -333,6 +335,7 @@
     }
 
     @Test
+    @AppModeFull(reason = "WRITE_SECURE_SETTING permission can't be grant to instant apps")
     public void testSwitchInputMethod_mainServiceDisabled() throws Exception {
         // Set services
         Helper.disableAutofillService(sContext);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
index cc0d074..74a7d3a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
@@ -40,6 +40,7 @@
 import android.content.Intent;
 import android.os.Binder;
 import android.os.Bundle;
+import android.platform.test.annotations.AppModeFull;
 import android.service.autofill.FillContext;
 import android.support.test.uiautomator.Direction;
 
@@ -305,6 +306,7 @@
     }
 
     @Test
+    @AppModeFull(reason = "WRITE_SECURE_SETTING permission can't be grant to instant apps")
     public void testSwitchInputMethod() throws Exception {
         // Set service
         enableService();
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index fe642c3..5f60ea4 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -307,6 +307,8 @@
         <activity android:name="android.server.wm.CloseOnOutsideTestActivity" />
         <activity android:name="android.server.wm.DialogFrameTestActivity" />
         <activity android:name="android.server.wm.DisplayCutoutTests$TestActivity"
+                  android:configChanges="orientation|screenSize"
+                  android:screenOrientation="nosensor"
                   android:turnScreenOn="true"
                   android:showWhenLocked="true"/>
 
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index f1423f0..d3b5621 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -299,6 +299,7 @@
 
     /** Extra key constants for {@link android.server.wm.app.LandscapeOrientationActivity}. */
     public static class LandscapeOrientationActivity {
+        public static final String EXTRA_APP_CONFIG_INFO = "app_config_info";
         public static final String EXTRA_CONFIG_INFO_IN_ON_CREATE = "config_info_in_on_create";
         public static final String EXTRA_DISPLAY_REAL_SIZE = "display_real_size";
     }
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java
index 00984fa..dd1ad87 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java
@@ -16,11 +16,14 @@
 
 package android.server.wm.app;
 
+import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_APP_CONFIG_INFO;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_CONFIG_INFO_IN_ON_CREATE;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_DISPLAY_REAL_SIZE;
 
+import android.app.Application;
 import android.content.res.Configuration;
 import android.graphics.Point;
+import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.server.wm.CommandSession.ConfigInfo;
 import android.view.Display;
@@ -40,6 +43,13 @@
             display.getRealSize(size);
             extras.putParcelable(EXTRA_CONFIG_INFO_IN_ON_CREATE, new ConfigInfo(this, display));
             extras.putParcelable(EXTRA_DISPLAY_REAL_SIZE, size);
+
+            final Application app = getApplication();
+            extras.putParcelable(EXTRA_APP_CONFIG_INFO, new ConfigInfo(app,
+                    // The display object is associated with application resources that it has its
+                    // own display adjustments.
+                    app.getSystemService(DisplayManager.class)
+                            .getDisplay(Display.DEFAULT_DISPLAY)));
             client.putExtras(extras);
         });
     }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index c898ef6..e005059 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -37,6 +37,7 @@
 import static android.server.wm.app.Components.PORTRAIT_ORIENTATION_ACTIVITY;
 import static android.server.wm.app.Components.RESIZEABLE_ACTIVITY;
 import static android.server.wm.app.Components.TEST_ACTIVITY;
+import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_APP_CONFIG_INFO;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_CONFIG_INFO_IN_ON_CREATE;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_DISPLAY_REAL_SIZE;
 import static android.server.wm.translucentapp26.Components.SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY;
@@ -467,6 +468,7 @@
 
         final SizeInfo reportedSizes = getActivityDisplaySize(LANDSCAPE_ORIENTATION_ACTIVITY);
         final Bundle extras = TestJournalContainer.get(LANDSCAPE_ORIENTATION_ACTIVITY).extras;
+        final ConfigInfo appConfigInfo = extras.getParcelable(EXTRA_APP_CONFIG_INFO);
         final Point onCreateRealDisplaySize = extras.getParcelable(EXTRA_DISPLAY_REAL_SIZE);
         final ConfigInfo onCreateConfigInfo = extras.getParcelable(EXTRA_CONFIG_INFO_IN_ON_CREATE);
         final SizeInfo onCreateSize = onCreateConfigInfo.sizeInfo;
@@ -478,13 +480,19 @@
         final Point expectedRealDisplaySize = new Point();
         display.getRealSize(expectedRealDisplaySize);
 
+        final int expectedRotation = display.getRotation();
         assertEquals("The activity should get the final display rotation in onCreate",
-                display.getRotation(), onCreateConfigInfo.rotation);
+                expectedRotation, onCreateConfigInfo.rotation);
+        assertEquals("The application should get the final display rotation in onCreate",
+                expectedRotation, appConfigInfo.rotation);
         assertEquals("The activity should get the final display size in onCreate",
                 expectedRealDisplaySize, onCreateRealDisplaySize);
-        assertEquals("The app size of activity should have the same orientation",
-                expectedRealDisplaySize.x > expectedRealDisplaySize.y,
+
+        final boolean isLandscape = expectedRealDisplaySize.x > expectedRealDisplaySize.y;
+        assertEquals("The app size of activity should have the same orientation", isLandscape,
                 onCreateSize.displayWidth > onCreateSize.displayHeight);
+        assertEquals("The application should get the same orientation", isLandscape,
+                appConfigInfo.sizeInfo.displayWidth > appConfigInfo.sizeInfo.displayHeight);
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
index 142b8ac..e4dc868 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
@@ -218,6 +218,8 @@
 
     @Test
     public void testSplitScreenBelowPip() throws Exception {
+        assumeTrue(supportsSplitScreenMultiWindow());
+
         // TODO(b/149338177): Fix test to pass with organizer API.
         mUseTaskOrganizer = false;
         // Launch Pip-capable activity and enter Pip immediately
@@ -255,6 +257,8 @@
 
     @Test
     public void testPipAboveSplitScreen() throws Exception {
+        assumeTrue(supportsSplitScreenMultiWindow());
+
         // TODO(b/149338177): Fix test to pass with organizer API.
         mUseTaskOrganizer = false;
         // Launch first activity
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationUpdateIntervalTest.java b/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationUpdateIntervalTest.java
index 0733c0d..a908057 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationUpdateIntervalTest.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationUpdateIntervalTest.java
@@ -43,6 +43,7 @@
     private static final String TAG = "GnssLocationUpdateIntervalTest";
 
     private static final int LOCATION_TO_COLLECT_COUNT = 8;
+    private static final int PASSIVE_LOCATION_TO_COLLECT_COUNT = 100;
     private static final int TIMEOUT_IN_SEC = 120;
 
     // Minimum time interval between fixes in milliseconds.
@@ -97,10 +98,9 @@
         TestLocationListener activeLocationListener = new TestLocationListener(
                 LOCATION_TO_COLLECT_COUNT);
         TestLocationListener passiveLocationListener = new TestLocationListener(
-                LOCATION_TO_COLLECT_COUNT);
+                PASSIVE_LOCATION_TO_COLLECT_COUNT);
         mTestLocationManager.requestLocationUpdates(activeLocationListener, fixIntervalMillis);
-        mTestLocationManager.requestPassiveLocationUpdates(passiveLocationListener,
-                fixIntervalMillis);
+        mTestLocationManager.requestPassiveLocationUpdates(passiveLocationListener, 0);
         try {
             boolean success = activeLocationListener.await(
                     (fixIntervalMillis * LOCATION_TO_COLLECT_COUNT) + TIMEOUT_IN_SEC);
diff --git a/tests/rollback/AndroidManifest.xml b/tests/rollback/AndroidManifest.xml
index ab1ec0f..3203f25 100644
--- a/tests/rollback/AndroidManifest.xml
+++ b/tests/rollback/AndroidManifest.xml
@@ -18,7 +18,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.cts.rollback" >
 
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
     <application>
         <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
                   android:exported="true" />
diff --git a/tests/sensor/src/android/hardware/cts/SensorSupportTest.java b/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
index 6942094..2cab0c9 100644
--- a/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
@@ -51,15 +51,13 @@
     @Override
     public void setUp() {
         PackageManager pm = getContext().getPackageManager();
-        // Tests will only run if either HIFI_SENSORS or VR high performance mode is supported.
+        // Some tests will only run if either HIFI_SENSORS or VR high performance mode is supported.
         mAreHifiSensorsSupported = pm.hasSystemFeature(PackageManager.FEATURE_HIFI_SENSORS);
         mVrHighPerformanceModeSupported = pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
         mIsVrHeadset = (getContext().getResources().getConfiguration().uiMode
             & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_VR_HEADSET;
-        if (mAreHifiSensorsSupported || mVrHighPerformanceModeSupported) {
-            mSensorManager =
-                    (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
-        }
+        mSensorManager =
+                (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
 
         mHasAccel = hasSensorType(Sensor.TYPE_ACCELEROMETER);
         mHasGyro = hasSensorType(Sensor.TYPE_GYROSCOPE);
@@ -171,6 +169,6 @@
     }
 
     private boolean hasSensorType(int sensorType) {
-        return (mSensorManager.getDefaultSensor(sensorType) != null);
+        return (mSensorManager != null && mSensorManager.getDefaultSensor(sensorType) != null);
     }
 }
diff --git a/tests/signature/api-check/android-test-base-28-api/Android.bp b/tests/signature/api-check/android-test-base-28-api/Android.bp
index 2b24bc1..31263b4 100644
--- a/tests/signature/api-check/android-test-base-28-api/Android.bp
+++ b/tests/signature/api-check/android-test-base-28-api/Android.bp
@@ -18,7 +18,7 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-android-test-base-current-txt",
+        ":cts-android-test-base-current-api-gz",
     ],
     min_sdk_version: "27",
 
diff --git a/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml
index ef43237..e048dc3 100644
--- a/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-28-api/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.android_test_base_28" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.api28.test.SignatureTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.txt" />
+        <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/android-test-base-current-api/Android.bp b/tests/signature/api-check/android-test-base-current-api/Android.bp
index ead699b..8ef01a1 100644
--- a/tests/signature/api-check/android-test-base-current-api/Android.bp
+++ b/tests/signature/api-check/android-test-base-current-api/Android.bp
@@ -18,7 +18,7 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-android-test-base-current-txt",
+        ":cts-android-test-base-current-api-gz",
     ],
 
     use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
index bbf942e..30da659 100644
--- a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.android_test_base_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.current.test.SignatureTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.txt" />
+        <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/android-test-mock-current-api/Android.bp b/tests/signature/api-check/android-test-mock-current-api/Android.bp
index 9f3ccbf..44c7a8a 100644
--- a/tests/signature/api-check/android-test-mock-current-api/Android.bp
+++ b/tests/signature/api-check/android-test-mock-current-api/Android.bp
@@ -18,7 +18,7 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-android-test-mock-current-txt",
+        ":cts-android-test-mock-current-api-gz",
     ],
 
     use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
index 19dbe7b..f8ab351 100644
--- a/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.android_test_mock_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.current.mock.SignatureTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="android-test-mock-current.txt" />
+        <option name="instrumentation-arg" key="expected-api-files" value="android-test-mock-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/android-test-runner-current-api/Android.bp b/tests/signature/api-check/android-test-runner-current-api/Android.bp
index 84ba5e9..80d2803 100644
--- a/tests/signature/api-check/android-test-runner-current-api/Android.bp
+++ b/tests/signature/api-check/android-test-runner-current-api/Android.bp
@@ -18,9 +18,9 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-android-test-base-current-txt",
-        ":cts-android-test-mock-current-txt",
-        ":cts-android-test-runner-current-txt",
+        ":cts-android-test-base-current-api-gz",
+        ":cts-android-test-mock-current-api-gz",
+        ":cts-android-test-runner-current-api-gz",
     ],
 
     use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
index 1c6ed19..5c18209 100644
--- a/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.android_test_runner_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.current.runner.SignatureTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.txt,android-test-mock-current.txt,android-test-runner-current.txt" />
+        <option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api.gz,android-test-mock-current.api.gz,android-test-runner-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/Android.bp b/tests/signature/api-check/apache-http-legacy-27-api/Android.bp
index 13e99d0..d649145 100644
--- a/tests/signature/api-check/apache-http-legacy-27-api/Android.bp
+++ b/tests/signature/api-check/apache-http-legacy-27-api/Android.bp
@@ -18,8 +18,8 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-current-txt",
-        ":cts-apache-http-legacy-current-txt",
+        ":cts-current-api-gz",
+        ":cts-apache-http-legacy-current-api-gz",
     ],
     min_sdk_version: "27",
 
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
index f308253..ff5cff8 100644
--- a/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
@@ -27,8 +27,8 @@
         <option name="package" value="android.signature.cts.api.apache_http_legacy_27" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.api27.http.SignatureTest" />
-        <option name="instrumentation-arg" key="base-api-files" value="current.txt" />
-        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.txt" />
+        <option name="instrumentation-arg" key="base-api-files" value="current.api.gz" />
+        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/Android.bp b/tests/signature/api-check/apache-http-legacy-current-api/Android.bp
index bf778fc..ffda5cc 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/Android.bp
+++ b/tests/signature/api-check/apache-http-legacy-current-api/Android.bp
@@ -18,7 +18,7 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-apache-http-legacy-current-txt",
+        ":cts-apache-http-legacy-current-api-gz",
     ],
 
     use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
index 3fa2220..5b15e41 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.apache_http_legacy_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.current.http.SignatureTest" />
-        <option name="instrumentation-arg" key="unexpected-api-files" value="apache-http-legacy-current.txt" />
+        <option name="instrumentation-arg" key="unexpected-api-files" value="apache-http-legacy-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp
index 5d7a473..f811f85 100644
--- a/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.bp
@@ -18,8 +18,8 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-current-txt",
-        ":cts-apache-http-legacy-current-txt",
+        ":cts-current-api-gz",
+        ":cts-apache-http-legacy-current-api-gz",
     ],
 
     use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
index 0c75fa6..7216d25 100644
--- a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
@@ -27,8 +27,8 @@
         <option name="package" value="android.signature.cts.api.apache_http_legacy_uses_library" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.http_uses_library.SignatureTest" />
-        <option name="instrumentation-arg" key="base-api-files" value="current.txt" />
-        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.txt" />
+        <option name="instrumentation-arg" key="base-api-files" value="current.api.gz" />
+        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-current.api.gz" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/current-api/Android.bp b/tests/signature/api-check/current-api/Android.bp
index 1e867d9..61656c3 100644
--- a/tests/signature/api-check/current-api/Android.bp
+++ b/tests/signature/api-check/current-api/Android.bp
@@ -18,10 +18,10 @@
         "signature-api-check-defaults",
     ],
     java_resources: [
-        ":cts-current-txt",
-        ":cts-android-test-base-current-txt",
-        ":cts-android-test-mock-current-txt",
-        ":cts-android-test-runner-current-txt",
+        ":cts-current-api-gz",
+        ":cts-android-test-base-current-api-gz",
+        ":cts-android-test-mock-current-api-gz",
+        ":cts-android-test-runner-current-api-gz",
     ],
 
     use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/current-api/AndroidTest.xml b/tests/signature/api-check/current-api/AndroidTest.xml
index 421306f..f14a503 100644
--- a/tests/signature/api-check/current-api/AndroidTest.xml
+++ b/tests/signature/api-check/current-api/AndroidTest.xml
@@ -28,8 +28,8 @@
         <option name="package" value="android.signature.cts.api.current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.current.SignatureTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="current.txt" />
-        <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-base-current.txt,android-test-mock-current.txt,android-test-runner-current.txt" />
+        <option name="instrumentation-arg" key="expected-api-files" value="current.api.gz" />
+        <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-base-current.api.gz,android-test-mock-current.api.gz,android-test-runner-current.api.gz" />
         <option name="runtime-hint" value="30s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/shared-libs-api/Android.mk b/tests/signature/api-check/shared-libs-api/Android.mk
index d921e6b..92c66d1 100644
--- a/tests/signature/api-check/shared-libs-api/Android.mk
+++ b/tests/signature/api-check/shared-libs-api/Android.mk
@@ -22,13 +22,13 @@
   $(foreach api_level,public system,\
     $(foreach lib,$(filter-out android,$(filter-out %removed,$(filter-out incompatibilities,\
       $(basename $(notdir $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(ver)/$(api_level)/api/*.txt)))))),\
-        $(eval all_shared_libs_modules += $(lib)-$(ver)-$(api_level).txt))))
+        $(eval all_shared_libs_modules += $(lib)-$(ver)-$(api_level).api))))
 
 all_shared_libs_files := $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(all_shared_libs_modules))
 
 include $(CLEAR_VARS)
-LOCAL_MODULE := cts-shared-libs-all.txt
-LOCAL_MODULE_STEM := shared-libs-all.txt.zip
+LOCAL_MODULE := cts-shared-libs-all.api
+LOCAL_MODULE_STEM := shared-libs-all.api.zip
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
 include $(BUILD_SYSTEM)/base_rules.mk
diff --git a/tests/signature/api-check/shared-libs-api/AndroidTest.xml b/tests/signature/api-check/shared-libs-api/AndroidTest.xml
index d6cc7fc..a679079 100644
--- a/tests/signature/api-check/shared-libs-api/AndroidTest.xml
+++ b/tests/signature/api-check/shared-libs-api/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.shared_libs" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.SignatureMultiLibsTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="shared-libs-all.txt.zip" />
+        <option name="instrumentation-arg" key="expected-api-files" value="shared-libs-all.api.zip" />
         <option name="runtime-hint" value="30s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/system-annotation/Android.bp b/tests/signature/api-check/system-annotation/Android.bp
index d328107..6b63792 100644
--- a/tests/signature/api-check/system-annotation/Android.bp
+++ b/tests/signature/api-check/system-annotation/Android.bp
@@ -21,10 +21,10 @@
         "compatibility-device-util-axt",
     ],
     java_resources: [
-        ":cts-system-current-txt",
-        ":cts-system-removed-txt",
-        ":cts-car-system-current-txt",
-        ":cts-car-system-removed-txt",
+        ":cts-system-current-api-gz",
+        ":cts-system-removed-api-gz",
+        ":cts-car-system-current-api-gz",
+        ":cts-car-system-removed-api-gz",
     ],
     min_sdk_version: "27",
 
diff --git a/tests/signature/api-check/system-annotation/AndroidTest.xml b/tests/signature/api-check/system-annotation/AndroidTest.xml
index 816ff81..4a61a40 100644
--- a/tests/signature/api-check/system-annotation/AndroidTest.xml
+++ b/tests/signature/api-check/system-annotation/AndroidTest.xml
@@ -27,7 +27,7 @@
         <option name="package" value="android.signature.cts.api.system_annotation" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.AnnotationTest" />
-        <option name="instrumentation-arg" key="expected-api-files" value="system-current.txt,system-removed.txt,car-system-current.txt,car-system-removed.txt" />
+        <option name="instrumentation-arg" key="expected-api-files" value="system-current.api.gz,system-removed.api.gz,car-system-current.api.gz,car-system-removed.api.gz" />
         <option name="instrumentation-arg" key="annotation-for-exact-match" value="@android.annotation.SystemApi\(client=PRIVILEGED_APPS\)" />
         <option name="runtime-hint" value="30s" />
     </test>
diff --git a/tests/signature/api-check/system-api/Android.mk b/tests/signature/api-check/system-api/Android.mk
index 2c577ca..b633daa 100644
--- a/tests/signature/api-check/system-api/Android.mk
+++ b/tests/signature/api-check/system-api/Android.mk
@@ -18,15 +18,15 @@
 $(foreach ver,$(PLATFORM_SYSTEMSDK_VERSIONS),\
   $(if $(call math_is_number,$(ver)),\
     $(if $(wildcard prebuilts/sdk/$(ver)/system/api/android.txt),\
-      $(eval all_system_api_modules += system-$(ver).txt)\
+      $(eval all_system_api_modules += system-$(ver).api)\
     )\
   )\
 )
 all_system_api_files := $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(all_system_api_modules))
 
 include $(CLEAR_VARS)
-LOCAL_MODULE := cts-system-all.txt
-LOCAL_MODULE_STEM := system-all.txt.zip
+LOCAL_MODULE := cts-system-all.api
+LOCAL_MODULE_STEM := system-all.api.zip
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
 LOCAL_COMPATIBILITY_SUITE := arcts cts vts10 general-tests
@@ -48,11 +48,11 @@
 LOCAL_JAVA_RESOURCE_FILES := $(all_system_api_zip_file)
 
 LOCAL_SIGNATURE_API_FILES := \
-    current.txt \
-    android-test-mock-current.txt \
-    android-test-runner-current.txt \
-    system-current.txt \
-    system-removed.txt \
+    current.api.gz \
+    android-test-mock-current.api.gz \
+    android-test-runner-current.api.gz \
+    system-current.api.gz \
+    system-removed.api.gz \
 
 include $(LOCAL_PATH)/../build_signature_apk.mk
 
diff --git a/tests/signature/api-check/system-api/AndroidTest.xml b/tests/signature/api-check/system-api/AndroidTest.xml
index 646338e..904dce1 100644
--- a/tests/signature/api-check/system-api/AndroidTest.xml
+++ b/tests/signature/api-check/system-api/AndroidTest.xml
@@ -27,9 +27,9 @@
         <option name="package" value="android.signature.cts.api.system" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.system.SignatureTest" />
-        <option name="instrumentation-arg" key="base-api-files" value="current.txt" />
-        <option name="instrumentation-arg" key="expected-api-files" value="system-current.txt,system-removed.txt,system-all.txt.zip" />
-        <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.txt,android-test-runner-current.txt" />
+        <option name="instrumentation-arg" key="base-api-files" value="current.api.gz" />
+        <option name="instrumentation-arg" key="expected-api-files" value="system-current.api.gz,system-removed.api.gz,system-all.api.zip" />
+        <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.api.gz,android-test-runner-current.api.gz" />
         <option name="runtime-hint" value="30s" />
     </test>
 </configuration>
diff --git a/tests/signature/api/Android.bp b/tests/signature/api/Android.bp
index 8c3e12a..424c881 100644
--- a/tests/signature/api/Android.bp
+++ b/tests/signature/api/Android.bp
@@ -12,115 +12,111 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-default_visibility = [
-    "//cts/tests/signature/api-check:__subpackages__",
-    "//cts/tests/signature/intent-check",
-]
+genrule_defaults {
+    name: "signature-cts-api-api-gz",
+    cmd: "$(location metalava) --no-banner -convert2xmlnostrip $(in) $(genDir)/api.xml && gzip -c $(genDir)/api.xml > $(out)",
+    tools: ["metalava"],
+    visibility: [
+        "//cts/tests/signature/api-check:__subpackages__",
+        "//cts/tests/signature/intent-check",
+    ],
+}
 
 genrule {
-    name: "cts-current-txt",
-    visibility: default_visibility,
+    name: "cts-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":frameworks-base-api-current.txt",
     ],
     out: [
-        "current.txt",
+        "current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-system-current-txt",
-    visibility: default_visibility,
+    name: "cts-system-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":frameworks-base-api-system-current.txt",
     ],
     out: [
-        "system-current.txt",
+        "system-current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-system-removed-txt",
-    visibility: default_visibility,
+    name: "cts-system-removed-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":frameworks-base-api-system-removed.txt",
     ],
     out: [
-        "system-removed.txt",
+        "system-removed.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-android-test-base-current-txt",
-    visibility: default_visibility,
+    name: "cts-android-test-base-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":android-test-base-current.txt",
     ],
     out: [
-        "android-test-base-current.txt",
+        "android-test-base-current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-android-test-mock-current-txt",
-    visibility: default_visibility,
+    name: "cts-android-test-mock-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":android-test-mock-current.txt",
     ],
     out: [
-        "android-test-mock-current.txt",
+        "android-test-mock-current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-android-test-runner-current-txt",
-    visibility: default_visibility,
+    name: "cts-android-test-runner-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":android-test-runner-current.txt",
     ],
     out: [
-        "android-test-runner-current.txt",
+        "android-test-runner-current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-apache-http-legacy-current-txt",
-    visibility: default_visibility,
+    name: "cts-apache-http-legacy-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":apache-http-legacy-current.txt",
     ],
     out: [
-        "apache-http-legacy-current.txt",
+        "apache-http-legacy-current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-car-system-current-txt",
-    visibility: default_visibility,
+    name: "cts-car-system-current-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":car-api-system-current.txt",
     ],
     out: [
-        "car-system-current.txt",
+        "car-system-current.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
 
 genrule {
-    name: "cts-car-system-removed-txt",
-    visibility: default_visibility,
+    name: "cts-car-system-removed-api-gz",
+    defaults: ["signature-cts-api-api-gz"],
     srcs: [
         ":car-api-system-removed.txt",
     ],
     out: [
-        "car-system-removed.txt",
+        "car-system-removed.api.gz",
     ],
-    cmd: "cp $(in) $(out)",
 }
diff --git a/tests/signature/api/Android.mk b/tests/signature/api/Android.mk
index e832b8f..d736c71 100644
--- a/tests/signature/api/Android.mk
+++ b/tests/signature/api/Android.mk
@@ -16,24 +16,25 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# $(1) name of the txt file to be created
+# $(1) name of the xml file to be created
 # $(2) path to the api text file
-define copy_api_txt_file
+define build_xml_api_file
 include $(CLEAR_VARS)
 LOCAL_MODULE := cts-$(subst .,-,$(1))
 LOCAL_MODULE_STEM := $(1)
 LOCAL_MODULE_CLASS := ETC
-LOCAL_COMPATIBILITY_SUITE := arcts cts vts10 general-tests
+LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
 include $(BUILD_SYSTEM)/base_rules.mk
 $$(LOCAL_BUILT_MODULE): $(2) | $(APICHECK)
-	@echo "Copying API file $$< -> $$@"
-	$$(copy-file-to-target)
+	@echo "Convert API file $$< -> $$@"
+	@mkdir -p $$(dir $$@)
+	$(hide) $(APICHECK_COMMAND) -convert2xmlnostrip $$< $$@
 endef
 
 $(foreach ver,$(PLATFORM_SYSTEMSDK_VERSIONS),\
   $(if $(call math_is_number,$(ver)),\
     $(if $(wildcard prebuilts/sdk/$(ver)/system/api/android.txt),\
-      $(eval $(call copy_api_txt_file,system-$(ver).txt,prebuilts/sdk/$(ver)/system/api/android.txt))\
+      $(eval $(call build_xml_api_file,system-$(ver).api,prebuilts/sdk/$(ver)/system/api/android.txt))\
     )\
   )\
 )
@@ -42,4 +43,7 @@
   $(foreach api_level,public system,\
     $(foreach lib,$(filter-out android,$(filter-out %removed,$(filter-out incompatibilities,\
       $(basename $(notdir $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(ver)/$(api_level)/api/*.txt)))))),\
-        $(eval $(call copy_api_txt_file,$(lib)-$(ver)-$(api_level).txt,prebuilts/sdk/$(ver)/$(api_level)/api/$(lib).txt)))))
+        $(eval $(call build_xml_api_file,$(lib)-$(ver)-$(api_level).api,prebuilts/sdk/$(ver)/$(api_level)/api/$(lib).txt)) \
+    )\
+  )\
+)
diff --git a/tests/signature/intent-check/Android.bp b/tests/signature/intent-check/Android.bp
index f6ec58c..82fb79e 100644
--- a/tests/signature/intent-check/Android.bp
+++ b/tests/signature/intent-check/Android.bp
@@ -18,9 +18,9 @@
 
     srcs: ["src/**/*.java"],
     java_resources: [
-        ":cts-current-txt",
-        ":cts-system-current-txt",
-        ":cts-system-removed-txt",
+        ":cts-current-api-gz",
+        ":cts-system-current-api-gz",
+        ":cts-system-removed-api-gz",
     ],
 
     // Tag this module as a cts test artifact
diff --git a/tests/signature/intent-check/DynamicConfig.xml b/tests/signature/intent-check/DynamicConfig.xml
index 6c7aace..b0cc4dc 100644
--- a/tests/signature/intent-check/DynamicConfig.xml
+++ b/tests/signature/intent-check/DynamicConfig.xml
@@ -23,6 +23,7 @@
     Bug: 78574873 android.intent.action.INSTALL_EPHEMERAL_PACKAGE
     Bug: 78574873 android.intent.action.RESOLVE_EPHEMERAL_PACKAGE
     Bug: 78574873 android.intent.action.EPHEMERAL_RESOLVER_SETTINGS
+    Bug: 150153196 android.intent.action.LOAD_DATA (system in API 30)
 -->
 <dynamicConfig>
     <entry key ="intent_whitelist">
@@ -34,5 +35,6 @@
       <value>android.intent.action.INSTALL_EPHEMERAL_PACKAGE</value>
       <value>android.intent.action.RESOLVE_EPHEMERAL_PACKAGE</value>
       <value>android.intent.action.EPHEMERAL_RESOLVER_SETTINGS</value>
+      <value>android.intent.action.LOAD_DATA</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java b/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java
index 0195dc4..efd574e 100644
--- a/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java
+++ b/tests/signature/intent-check/src/android/signature/cts/intent/IntentTest.java
@@ -48,11 +48,11 @@
 @RunWith(AndroidJUnit4.class)
 public class IntentTest {
 
-    private static final String CURRENT_API_RESOURCE = "current.txt";
+    private static final String CURRENT_API_RESOURCE = "current.api.gz";
 
-    private static final String SYSTEM_CURRENT_API_RESOURCE = "system-current.txt";
+    private static final String SYSTEM_CURRENT_API_RESOURCE = "system-current.api.gz";
 
-    private static final String SYSTEM_REMOVED_API_RESOURCE = "system-removed.txt";
+    private static final String SYSTEM_REMOVED_API_RESOURCE = "system-removed.api.gz";
 
     private static final String TAG = IntentTest.class.getSimpleName();
 
diff --git a/tests/signature/lib/android/Android.bp b/tests/signature/lib/android/Android.bp
index 7b0e679..546190a 100644
--- a/tests/signature/lib/android/Android.bp
+++ b/tests/signature/lib/android/Android.bp
@@ -24,7 +24,6 @@
     ],
     static_libs: [
         "signature-common-javalib",
-        "metalava",
     ],
     sdk_version: "current",
 }
diff --git a/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java b/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java
index 78027d4..70e3665 100644
--- a/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java
+++ b/tests/signature/lib/android/src/android/signature/cts/ApiDocumentParser.java
@@ -34,9 +34,14 @@
 
     private ApiParser getApiParser(VirtualPath path) {
         if (path.toString().endsWith(".txt")) {
-            return new TextApiParser();
+            // At one point we used the "text" signature format in this test, but we stopped doing
+            // it because we don't want metalava to be used as a library, especially
+            // on the device side.
+            throw new RuntimeException("Signature format not supported");
         } else if (path.toString().endsWith(".api")) {
-            return new XmlApiParser(tag);
+            return new XmlApiParser(tag, /*gzipped=*/ false);
+        } else if (path.toString().endsWith(".api.gz")) {
+            return new XmlApiParser(tag, /*gzipped=*/ true);
         } else {
             throw new IllegalStateException("Unrecognized file type: " + path);
         }
diff --git a/tests/signature/lib/android/src/android/signature/cts/KtHelper.kt b/tests/signature/lib/android/src/android/signature/cts/KtHelper.kt
deleted file mode 100644
index 4d2fade..0000000
--- a/tests/signature/lib/android/src/android/signature/cts/KtHelper.kt
+++ /dev/null
@@ -1,36 +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.
- */
-
-@file:JvmName("KtHelper")
-package android.signature.cts
-
-import com.android.tools.metalava.model.TypeItem
-
-/**
- * Allows Java to call the TypeItem.toTypeString() without having to explicitly specify each named
- * parameter to its default. This allows additional parameters to be added to the method without
- * breaking the Java code.
- */
-fun toDefaultTypeString(item: TypeItem): String {
-    // Normalize the strings to contain , without a following space. This is needed because
-    // different versions of the txt specification used different separators in generic types, some
-    // used "," and some used ", " and metalava does not normalize them. e.g. some files will format
-    // a Map from String to Integer as "java.util.Map<java.lang.String,java.lang.Integer>" and some
-    // will format it as "java.util.Map<java.lang.String, java.lang.Integer>".
-    //
-    // Must match separator used in android.signature.cts.ReflectionHelper.typeToString.
-    return item.toTypeString().replace(", ", ",")
-}
diff --git a/tests/signature/lib/android/src/android/signature/cts/TextApiParser.java b/tests/signature/lib/android/src/android/signature/cts/TextApiParser.java
deleted file mode 100644
index 26ac862..0000000
--- a/tests/signature/lib/android/src/android/signature/cts/TextApiParser.java
+++ /dev/null
@@ -1,191 +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.signature.cts;
-
-import android.signature.cts.JDiffClassDescription.JDiffConstructor;
-import android.signature.cts.JDiffClassDescription.JDiffField;
-import android.signature.cts.JDiffClassDescription.JDiffMethod;
-import com.android.tools.metalava.doclava1.ApiFile;
-import com.android.tools.metalava.doclava1.ApiParseException;
-import com.android.tools.metalava.doclava1.TextCodebase;
-import com.android.tools.metalava.model.ClassItem;
-import com.android.tools.metalava.model.ConstructorItem;
-import com.android.tools.metalava.model.FieldItem;
-import com.android.tools.metalava.model.Item;
-import com.android.tools.metalava.model.MethodItem;
-import com.android.tools.metalava.model.ModifierList;
-import com.android.tools.metalava.model.PackageItem;
-import com.android.tools.metalava.model.ParameterItem;
-import com.android.tools.metalava.model.TypeItem;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.reflect.Modifier;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import kotlin.streams.jdk8.StreamsKt;
-
-/**
- * Parser for the text representation of an API specification.
- */
-public class TextApiParser extends ApiParser {
-
-    @Override
-    public Stream<JDiffClassDescription> parseAsStream(VirtualPath path) {
-        try {
-            String content = new BufferedReader(new InputStreamReader(path.newInputStream()))
-                    .lines()
-                    .parallel()
-                    .collect(Collectors.joining("\n"));
-            TextCodebase codebase = ApiFile.parseApi(path.toString(), content, false);
-            List<PackageItem> packages = codebase.getPackages().getPackages();
-            return packages.stream()
-                    // Map each package to the Sequence of ClassItems that it contains
-                    .map(PackageItem::allClasses)
-                    // Flatten the Sequences of ClassItems into one stream.
-                    .flatMap(StreamsKt::asStream)
-                    // Filter out TextClassItems that are used from but not defined in the source.
-                    .filter(ClassItem::isDefined)
-                    .map(TextApiParser::convertClass);
-        } catch (IOException | ApiParseException e) {
-            throw new RuntimeException("Could not parse " + path, e);
-        }
-    }
-
-    private static JDiffClassDescription convertClass(ClassItem item) {
-        String pkg = item.containingPackage().qualifiedName();
-
-        JDiffClassDescription currentClass = new JDiffClassDescription(pkg, item.fullName());
-
-        int modifiers = getModifiers(item);
-
-        currentClass.setModifier(modifiers);
-        currentClass.setType(item.isInterface() ? JDiffClassDescription.JDiffType.INTERFACE :
-                JDiffClassDescription.JDiffType.CLASS);
-
-        // Map the super class.
-        ClassItem superClass = item.superClass();
-        if (superClass != null) {
-            String extendsClass = superClass.qualifiedName();
-            if (item.isInterface()) {
-                // TextCodebase treats an interface as if it extends java.lang.Object.
-                if (!superClass.isJavaLangObject()) {
-                    currentClass.addImplInterface(extendsClass);
-                }
-            } else {
-                currentClass.setExtendsClass(extendsClass);
-            }
-        }
-
-        // Map the interfaces.
-        item.interfaceTypes().stream()
-                .map(TypeItem::asClass)
-                .filter(Objects::nonNull)
-                .map(ClassItem::qualifiedName)
-                .forEach(currentClass::addImplInterface);
-
-        item.fields().stream().map(TextApiParser::convertField).forEach(currentClass::addField);
-
-        item.constructors().stream()
-                .map(TextApiParser::convertConstructor)
-                .forEach(currentClass::addConstructor);
-
-        item.methods().stream()
-                .map(TextApiParser::convertMethod)
-                .forEach(currentClass::addMethod);
-
-        return currentClass;
-    }
-
-    private static int getModifiers(Item item) {
-        ModifierList modifierList = item.getModifiers();
-        int modifiers = 0;
-        if (modifierList.isAbstract()) {
-            modifiers |= Modifier.ABSTRACT;
-        }
-        if (modifierList.isFinal()) {
-            modifiers |= Modifier.FINAL;
-        }
-        if (modifierList.isNative()) {
-            modifiers |= Modifier.NATIVE;
-        }
-        if (modifierList.isStatic()) {
-            modifiers |= Modifier.STATIC;
-        }
-        if (modifierList.isSynchronized()) {
-            modifiers |= Modifier.SYNCHRONIZED;
-        }
-        if (modifierList.isTransient()) {
-            modifiers |= Modifier.TRANSIENT;
-        }
-        if (modifierList.isVolatile()) {
-            modifiers |= Modifier.VOLATILE;
-        }
-        if (modifierList.isPrivate()) {
-            modifiers |= Modifier.PRIVATE;
-        } else if (modifierList.isProtected()) {
-            modifiers |= Modifier.PROTECTED;
-        } else if (modifierList.isPublic()) {
-            modifiers |= Modifier.PUBLIC;
-        }
-        return modifiers;
-    }
-
-    private static JDiffField convertField(FieldItem item) {
-        int modifiers = getModifiers(item);
-        Object value = item.initialValue(true);
-
-        if (item.isEnumConstant()) {
-            // Set the enum bit on the enum constant to match the modifiers returned by reflection.
-            modifiers |= 0x00004000;
-        }
-
-        return new JDiffField(item.name(),
-                KtHelper.toDefaultTypeString(item.type()), modifiers,
-                value == null ? null : value.toString());
-    }
-
-    private static JDiffConstructor convertConstructor(ConstructorItem item) {
-        JDiffConstructor constructor = new JDiffConstructor(item.name(), getModifiers(item));
-
-        convertParameters(item, constructor);
-
-        return constructor;
-    }
-
-    private static void convertParameters(MethodItem item, JDiffMethod method) {
-        item.parameters().stream()
-                .map(TextApiParser::convertParameter)
-                .forEach(method::addParam);
-    }
-
-    private static JDiffMethod convertMethod(MethodItem item) {
-        TypeItem returnType = item.returnType();
-        String returnTypeAsString = returnType == null ? null
-                : KtHelper.toDefaultTypeString(returnType);
-        JDiffMethod method = new JDiffMethod(item.name(), getModifiers(item), returnTypeAsString);
-
-        convertParameters(item, method);
-
-        return method;
-    }
-
-    private static String convertParameter(ParameterItem item) {
-        return KtHelper.toDefaultTypeString(item.type());
-    }
-}
diff --git a/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java b/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java
index 8e5d0bb..e77d7e0 100644
--- a/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java
+++ b/tests/signature/lib/android/src/android/signature/cts/XmlApiParser.java
@@ -20,6 +20,7 @@
 import android.signature.cts.JDiffClassDescription.JDiffMethod;
 import android.util.Log;
 import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.Modifier;
 import java.util.Collections;
 import java.util.HashSet;
@@ -28,6 +29,8 @@
 import java.util.function.Consumer;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
+import java.util.zip.GZIPInputStream;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlPullParserFactory;
@@ -106,11 +109,13 @@
     }
 
     private final String tag;
+    private final boolean gzipped;
 
     private final XmlPullParserFactory factory;
 
-    XmlApiParser(String tag) {
+    XmlApiParser(String tag, boolean gzipped) {
         this.tag = tag;
+        this.gzipped = gzipped;
         try {
             factory = XmlPullParserFactory.newInstance();
         } catch (XmlPullParserException e) {
@@ -121,18 +126,25 @@
     /**
      * Load field information from xml to memory.
      *
-     * @param className
+     * @param currentClass
      *         of the class being examined which will be shown in error messages
      * @param parser
      *         The XmlPullParser which carries the xml information.
      * @return the new field
      */
-    private static JDiffField loadFieldInfo(String className, XmlPullParser parser) {
+    private static JDiffField loadFieldInfo(
+            JDiffClassDescription currentClass, XmlPullParser parser) {
         String fieldName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
         String fieldType = canonicalizeType(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
-        int modifier = jdiffModifierToReflectionFormat(className, parser);
+        int modifier = jdiffModifierToReflectionFormat(currentClass.getClassName(), parser);
         String value = parser.getAttributeValue(null, ATTRIBUTE_VALUE);
 
+        if (currentClass.isEnumType() && fieldType.equals(currentClass.getAbsoluteClassName())
+                && (value != null && value.startsWith("PsiEnumConstant:"))) {
+            // We don't need to check the value.
+            value = null;
+        }
+
         // Canonicalize the expected value to ensure that it is consistent with the values obtained
         // using reflection by ApiComplianceChecker.getFieldValueAsString(...).
         if (value != null) {
@@ -148,10 +160,24 @@
                         break;
 
                     case "char":
-                        // A character is encoded in XML as its numeric value. Convert it to a
+                        // A character may be encoded in XML as its numeric value. Convert it to a
                         // string containing the single character.
-                        char c = (char) Integer.parseInt(value);
-                        value = String.valueOf(c);
+                        try {
+                            char c = (char) Integer.parseInt(value);
+                            value = String.valueOf(c);
+                        } catch (NumberFormatException e) {
+                            // If not, it must be a string "'?'". Extract the second character,
+                            // but we need to unescape it.
+                            int len = value.length();
+                            if (value.charAt(0) == '\'' && value.charAt(len - 1) == '\'') {
+                                String sub = value.substring(1, len - 1);
+                                value = unescapeFieldStringValue(sub);
+                            } else {
+                                throw new NumberFormatException(String.format(
+                                        "Cannot parse the value of field '%s': invalid number '%s'",
+                                        fieldName, value));
+                            }
+                        }
                         break;
 
                     case "double":
@@ -248,10 +274,25 @@
         String className = parser.getAttributeValue(null, ATTRIBUTE_NAME);
         JDiffClassDescription currentClass = new JDiffClassDescription(pkg, className);
 
-        currentClass.setModifier(jdiffModifierToReflectionFormat(className, parser));
         currentClass.setType(isInterface ? JDiffClassDescription.JDiffType.INTERFACE :
                 JDiffClassDescription.JDiffType.CLASS);
-        currentClass.setExtendsClass(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
+
+        String superClass = stripGenericsArgs(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
+        int modifiers = jdiffModifierToReflectionFormat(className, parser);
+        if (isInterface) {
+            if (superClass != null) {
+                currentClass.addImplInterface(superClass);
+            }
+        } else {
+            if ("java.lang.annotation.Annotation".equals(superClass)) {
+                // ApiComplianceChecker expects "java.lang.annotation.Annotation" to be in
+                // the "impl interfaces".
+                currentClass.addImplInterface(superClass);
+            } else {
+                currentClass.setExtendsClass(superClass);
+            }
+        }
+        currentClass.setModifier(modifiers);
         return currentClass;
     }
 
@@ -324,7 +365,11 @@
         XmlPullParser parser;
         try {
             parser = factory.newPullParser();
-            parser.setInput(path.newInputStream(), null);
+            InputStream input = path.newInputStream();
+            if (gzipped) {
+                input = new GZIPInputStream(input);
+            }
+            parser.setInput(input, null);
             return StreamSupport
                     .stream(new ClassDescriptionSpliterator(parser), false);
         } catch (XmlPullParserException | IOException e) {
@@ -332,6 +377,10 @@
         }
     }
 
+    private static String stripGenericsArgs(String typeName) {
+        return typeName == null ? null : typeName.replaceFirst("<.*", "");
+    }
+
     private class ClassDescriptionSpliterator implements Spliterator<JDiffClassDescription> {
 
         private final XmlPullParser parser;
@@ -444,8 +493,8 @@
                         break;
 
                     case TAG_IMPLEMENTS:
-                        currentClass
-                                .addImplInterface(parser.getAttributeValue(null, ATTRIBUTE_NAME));
+                        currentClass.addImplInterface(stripGenericsArgs(
+                                parser.getAttributeValue(null, ATTRIBUTE_NAME)));
                         break;
 
                     case TAG_CONSTRUCTOR:
@@ -470,7 +519,7 @@
                         break;
 
                     case TAG_FIELD:
-                        JDiffField field = loadFieldInfo(currentClass.getClassName(), parser);
+                        JDiffField field = loadFieldInfo(currentClass, parser);
                         currentClass.addField(field);
                         break;
 
diff --git a/tests/tests/content/pm/SecureFrp/AndroidManifest.xml b/tests/tests/content/pm/SecureFrp/AndroidManifest.xml
index 9e45d4a..f1b5184 100644
--- a/tests/tests/content/pm/SecureFrp/AndroidManifest.xml
+++ b/tests/tests/content/pm/SecureFrp/AndroidManifest.xml
@@ -18,7 +18,6 @@
           package="com.android.tests.securefrpinstall" >
 
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 
     <application>
         <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
index 7f60d5f..9ffba5f 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
@@ -30,6 +30,7 @@
 import android.media.MediaFormat;
 import android.media.cts.R;
 import android.net.Uri;
+import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.AndroidTestCase;
@@ -38,6 +39,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.MediaUtils;
 
 import java.io.IOException;
@@ -76,6 +78,7 @@
     // Time out processing, as we have no way to query whether the decoder will produce output.
     private static final int TIMEOUT_MS = 60000;  // 1 minute
 
+    private boolean mIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
     /**
      * Tests whether decoding a short group-of-pictures succeeds. The test queues a few video frames
      * then signals end-of-stream. The test fails if the decoder doesn't output the queued frames.
@@ -84,6 +87,7 @@
     @SmallTest
     @RequiresDevice
     public void testDecodeShortVideo() throws InterruptedException {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         runThread(() -> runDecodeShortVideo(
                 INPUT_RESOURCE_ID,
                 LAST_BUFFER_TIMESTAMP_US,
@@ -100,6 +104,7 @@
      * then signals end-of-stream. The test fails if the decoder doesn't output the queued frames.
      */
     public void testDecodeShortEncryptedVideo() throws InterruptedException {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         runThread(() -> runDecodeShortEncryptedVideo(
                 true /* obtainBlockForEachBuffer */));
         runThread(() -> runDecodeShortEncryptedVideo(
@@ -114,6 +119,7 @@
     @SmallTest
     @RequiresDevice
     public void testDecodeShortAudio() throws InterruptedException {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         runThread(() -> runDecodeShortAudio(
                 INPUT_RESOURCE_ID,
                 LAST_BUFFER_TIMESTAMP_US,
@@ -132,6 +138,7 @@
     @SmallTest
     @RequiresDevice
     public void testEncodeShortAudio() throws InterruptedException {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         runThread(() -> runEncodeShortAudio());
     }
 
@@ -143,6 +150,7 @@
     @SmallTest
     @RequiresDevice
     public void testEncodeShortVideo() throws InterruptedException {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         runThread(() -> runEncodeShortVideo());
     }
 
@@ -153,6 +161,7 @@
     @SmallTest
     @RequiresDevice
     public void testFormatChange() throws InterruptedException {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         List<FormatChangeEvent> events = new ArrayList<>();
         runThread(() -> runDecodeShortVideo(
                 getMediaExtractorForMimeType(INPUT_RESOURCE_ID, "video/"),
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index a20e39f..d41716e 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -41,6 +41,7 @@
 import android.media.MediaFormat;
 import android.media.cts.R;
 import android.opengl.GLES20;
+import android.os.Build;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -55,6 +56,7 @@
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.MediaUtils;
 
 import java.io.BufferedInputStream;
@@ -118,6 +120,7 @@
     // Time out decoding, as we have no way to query whether the decoder will produce output.
     private static final int DECODING_TIMEOUT_MS = 10000;
 
+    private static boolean mIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
     /**
      * Tests:
      * <br> Exceptions for MediaCodec factory methods
@@ -315,25 +318,27 @@
             fail("configure should not return MediaCodec.CodecException on wrong state");
         } catch (IllegalStateException e) { // expected
         }
-        try {
-            codec.getQueueRequest(0);
-            fail("getQueueRequest should throw IllegalStateException when not configured with " +
-                    "CONFIGURE_FLAG_USE_BLOCK_MODEL");
-        } catch (MediaCodec.CodecException e) {
-            logMediaCodecException(e);
-            fail("getQueueRequest should not return " +
-                    "MediaCodec.CodecException on wrong configuration");
-        } catch (IllegalStateException e) { // expected
-        }
-        try {
-            codec.getOutputFrame(0);
-            fail("getOutputFrame should throw IllegalStateException when not configured with " +
-                    "CONFIGURE_FLAG_USE_BLOCK_MODEL");
-        } catch (MediaCodec.CodecException e) {
-            logMediaCodecException(e);
-            fail("getOutputFrame should not return MediaCodec.CodecException on wrong " +
-                    "configuration");
-        } catch (IllegalStateException e) { // expected
+        if (mIsAtLeastR) {
+            try {
+                codec.getQueueRequest(0);
+                fail("getQueueRequest should throw IllegalStateException when not configured with " +
+                        "CONFIGURE_FLAG_USE_BLOCK_MODEL");
+            } catch (MediaCodec.CodecException e) {
+                logMediaCodecException(e);
+                fail("getQueueRequest should not return " +
+                        "MediaCodec.CodecException on wrong configuration");
+            } catch (IllegalStateException e) { // expected
+            }
+            try {
+                codec.getOutputFrame(0);
+                fail("getOutputFrame should throw IllegalStateException when not configured with " +
+                        "CONFIGURE_FLAG_USE_BLOCK_MODEL");
+            } catch (MediaCodec.CodecException e) {
+                logMediaCodecException(e);
+                fail("getOutputFrame should not return MediaCodec.CodecException on wrong " +
+                        "configuration");
+            } catch (IllegalStateException e) { // expected
+            }
         }
 
         // two flushes should be fine.
@@ -368,100 +373,102 @@
         } catch (IllegalStateException e) { // expected
         }
 
-        // recreate
-        codec = createCodecByType(format.getString(MediaFormat.KEY_MIME), isEncoder);
+        if (mIsAtLeastR) {
+            // recreate
+            codec = createCodecByType(format.getString(MediaFormat.KEY_MIME), isEncoder);
 
-        // configure improperly
-        try {
+            // configure improperly
+            try {
+                codec.configure(format, null /* surface */, null /* crypto */,
+                        MediaCodec.CONFIGURE_FLAG_USE_BLOCK_MODEL |
+                        (isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0) /* flags */);
+                fail("configure with detached buffer mode should be done after setCallback");
+            } catch (MediaCodec.CodecException e) {
+                logMediaCodecException(e);
+                fail("configure should not return IllegalStateException when improperly configured");
+            } catch (IllegalStateException e) { // expected
+            }
+
+            final LinkedBlockingQueue<Integer> inputQueue = new LinkedBlockingQueue<>();
+            codec.setCallback(new MediaCodec.Callback() {
+                @Override
+                public void onInputBufferAvailable(MediaCodec codec, int index) {
+                    inputQueue.offer(index);
+                }
+                @Override
+                public void onOutputBufferAvailable(
+                        MediaCodec codec, int index, MediaCodec.BufferInfo info) { }
+                @Override
+                public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { }
+                @Override
+                public void onError(MediaCodec codec, CodecException e) { }
+            });
+
+            // configure with CONFIGURE_FLAG_USE_BLOCK_MODEL (enter Configured State)
             codec.configure(format, null /* surface */, null /* crypto */,
                     MediaCodec.CONFIGURE_FLAG_USE_BLOCK_MODEL |
                     (isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0) /* flags */);
-            fail("configure with detached buffer mode should be done after setCallback");
-        } catch (MediaCodec.CodecException e) {
-            logMediaCodecException(e);
-            fail("configure should not return IllegalStateException when improperly configured");
-        } catch (IllegalStateException e) { // expected
-        }
 
-        final LinkedBlockingQueue<Integer> inputQueue = new LinkedBlockingQueue<>();
-        codec.setCallback(new MediaCodec.Callback() {
-            @Override
-            public void onInputBufferAvailable(MediaCodec codec, int index) {
-                inputQueue.offer(index);
+            // start codec (enter Executing state)
+            codec.start();
+
+            // grab input index (this should happen immediately)
+            Integer index = null;
+            try {
+                index = inputQueue.poll(2, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
             }
-            @Override
-            public void onOutputBufferAvailable(
-                    MediaCodec codec, int index, MediaCodec.BufferInfo info) { }
-            @Override
-            public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { }
-            @Override
-            public void onError(MediaCodec codec, CodecException e) { }
-        });
+            assertNotNull(index);
 
-        // configure with CONFIGURE_FLAG_USE_BLOCK_MODEL (enter Configured State)
-        codec.configure(format, null /* surface */, null /* crypto */,
-                MediaCodec.CONFIGURE_FLAG_USE_BLOCK_MODEL |
-                (isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0) /* flags */);
+            // test a few commands
+            try {
+                codec.getInputBuffers();
+                fail("getInputBuffers called in detached buffer mode should throw exception");
+            } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
+            }
+            try {
+                codec.getOutputBuffers();
+                fail("getOutputBuffers called in detached buffer mode should throw exception");
+            } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
+            }
+            try {
+                codec.getInputBuffer(index);
+                fail("getInputBuffer called in detached buffer mode should throw exception");
+            } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
+            }
+            try {
+                codec.dequeueInputBuffer(0);
+                fail("dequeueInputBuffer called in detached buffer mode should throw exception");
+            } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
+            }
+            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+            try {
+                codec.dequeueOutputBuffer(info, 0);
+                fail("dequeueOutputBuffer called in detached buffer mode should throw exception");
+            } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
+            }
 
-        // start codec (enter Executing state)
-        codec.start();
-
-        // grab input index (this should happen immediately)
-        Integer index = null;
-        try {
-            index = inputQueue.poll(2, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-        }
-        assertNotNull(index);
-
-        // test a few commands
-        try {
-            codec.getInputBuffers();
-            fail("getInputBuffers called in detached buffer mode should throw exception");
-        } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
-        }
-        try {
-            codec.getOutputBuffers();
-            fail("getOutputBuffers called in detached buffer mode should throw exception");
-        } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
-        }
-        try {
-            codec.getInputBuffer(index);
-            fail("getInputBuffer called in detached buffer mode should throw exception");
-        } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
-        }
-        try {
-            codec.dequeueInputBuffer(0);
-            fail("dequeueInputBuffer called in detached buffer mode should throw exception");
-        } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
-        }
-        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-        try {
-            codec.dequeueOutputBuffer(info, 0);
-            fail("dequeueOutputBuffer called in detached buffer mode should throw exception");
-        } catch (MediaCodec.IncompatibleWithBlockModelException e) { // expected
-        }
-
-        // test getQueueRequest
-        MediaCodec.QueueRequest request = codec.getQueueRequest(index);
-        try {
-            request.queue();
-            fail("QueueRequest should throw IllegalStateException when no buffer is set");
-        } catch (IllegalStateException e) { // expected
-        }
-        // setting a block
-        String[] names = new String[]{ codec.getName() };
-        request.setLinearBlock(MediaCodec.LinearBlock.obtain(1, names), 0, 0);
-        // setting additional block should fail
-        try (HardwareBuffer buffer = HardwareBuffer.create(
-                16 /* width */,
-                16 /* height */,
-                HardwareBuffer.YCBCR_420_888,
-                1 /* layers */,
-                HardwareBuffer.USAGE_CPU_READ_OFTEN | HardwareBuffer.USAGE_CPU_WRITE_OFTEN)) {
-            request.setHardwareBuffer(buffer);
-            fail("QueueRequest should throw IllegalStateException multiple blocks are set.");
-        } catch (IllegalStateException e) { // expected
+            // test getQueueRequest
+            MediaCodec.QueueRequest request = codec.getQueueRequest(index);
+            try {
+                request.queue();
+                fail("QueueRequest should throw IllegalStateException when no buffer is set");
+            } catch (IllegalStateException e) { // expected
+            }
+            // setting a block
+            String[] names = new String[]{ codec.getName() };
+            request.setLinearBlock(MediaCodec.LinearBlock.obtain(1, names), 0, 0);
+            // setting additional block should fail
+            try (HardwareBuffer buffer = HardwareBuffer.create(
+                    16 /* width */,
+                    16 /* height */,
+                    HardwareBuffer.YCBCR_420_888,
+                    1 /* layers */,
+                    HardwareBuffer.USAGE_CPU_READ_OFTEN | HardwareBuffer.USAGE_CPU_WRITE_OFTEN)) {
+                request.setHardwareBuffer(buffer);
+                fail("QueueRequest should throw IllegalStateException multiple blocks are set.");
+            } catch (IllegalStateException e) { // expected
+            }
         }
 
         // release codec
@@ -2662,8 +2669,10 @@
      * through the scenario.
      */
     public void testFlushAfterFirstBuffer() throws Exception {
-        for (int i = 0; i < 100; ++i) {
-            doFlushAfterFirstBuffer();
+        if (MediaUtils.check(mIsAtLeastR, "test needs Android 11")) {
+            for (int i = 0; i < 100; ++i) {
+                doFlushAfterFirstBuffer();
+            }
         }
     }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 66f65a1..1407f79 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -31,6 +31,7 @@
 import android.media.MediaFormat;
 import static android.media.MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION;
 import android.media.cts.R;
+import android.os.Build;
 import android.os.PersistableBundle;
 import android.platform.test.annotations.AppModeFull;
 import android.test.AndroidTestCase;
@@ -39,6 +40,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.MediaUtils;
 
 import java.io.BufferedReader;
@@ -61,6 +63,7 @@
     private static final String TAG = "MediaExtractorTest";
     private static final UUID UUID_WIDEVINE = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
     private static final UUID UUID_PLAYREADY = new UUID(0x9A04F07998404286L, 0xAB92E65BE0885F95L);
+    private static boolean mIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
 
     protected Resources mResources;
     protected MediaExtractor mExtractor;
@@ -376,6 +379,7 @@
     }
 
     public void testGetDrmInitData() throws Exception {
+        if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
         setDataSource(R.raw.psshtest);
         DrmInitData drmInitData = mExtractor.getDrmInitData();
         assertEquals(drmInitData.getSchemeInitDataCount(), 2);
diff --git a/tests/tests/mediaparser/Android.bp b/tests/tests/mediaparser/Android.bp
index 3a65698..6a13d24 100644
--- a/tests/tests/mediaparser/Android.bp
+++ b/tests/tests/mediaparser/Android.bp
@@ -23,6 +23,7 @@
     ],
     srcs: ["src/**/*.java"],
     sdk_version: "test_current",
+    min_sdk_version: "29",
     libs: [
         "android.test.base.stubs",
         "android.test.runner.stubs",
diff --git a/tests/tests/net/api23Test/AndroidManifest.xml b/tests/tests/net/api23Test/AndroidManifest.xml
index 8af87f6..4889660 100644
--- a/tests/tests/net/api23Test/AndroidManifest.xml
+++ b/tests/tests/net/api23Test/AndroidManifest.xml
@@ -18,8 +18,11 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.net.cts.api23test">
 
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application android:usesCleartextTraffic="true">
diff --git a/tests/tests/net/src/android/net/cts/CaptivePortalApiTest.kt b/tests/tests/net/src/android/net/cts/CaptivePortalApiTest.kt
index 40d0ca6..68d5281 100644
--- a/tests/tests/net/src/android/net/cts/CaptivePortalApiTest.kt
+++ b/tests/tests/net/src/android/net/cts/CaptivePortalApiTest.kt
@@ -61,7 +61,6 @@
 import java.net.Inet4Address
 import java.util.concurrent.ArrayBlockingQueue
 import java.util.concurrent.TimeUnit
-import kotlin.reflect.KClass
 import kotlin.test.assertEquals
 import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
@@ -90,7 +89,7 @@
     private val eth by lazy { context.assertHasService(EthernetManager::class.java) }
     private val cm by lazy { context.assertHasService(ConnectivityManager::class.java) }
 
-    private val handlerThread = HandlerThread(CaptivePortalApiTest::class.simpleName)
+    private val handlerThread = HandlerThread(CaptivePortalApiTest::class.java.simpleName)
     private val serverIpAddr = InetAddresses.parseNumericAddress("192.0.2.222") as Inet4Address
     private val clientIpAddr = InetAddresses.parseNumericAddress("192.0.2.111") as Inet4Address
     private val httpServer = HttpServer()
@@ -155,11 +154,11 @@
     fun testApiCallbacks() {
         // Handle the DHCP handshake that includes the capport API URL
         val discover = reader.assertDhcpPacketReceived(
-                DhcpDiscoverPacket::class, TEST_TIMEOUT_MS, DHCP_MESSAGE_TYPE_DISCOVER)
+                DhcpDiscoverPacket::class.java, TEST_TIMEOUT_MS, DHCP_MESSAGE_TYPE_DISCOVER)
         reader.sendResponse(makeOfferPacket(discover.clientMac, discover.transactionId))
 
         val request = reader.assertDhcpPacketReceived(
-                DhcpRequestPacket::class, TEST_TIMEOUT_MS, DHCP_MESSAGE_TYPE_REQUEST)
+                DhcpRequestPacket::class.java, TEST_TIMEOUT_MS, DHCP_MESSAGE_TYPE_REQUEST)
         assertEquals(discover.transactionId, request.transactionId)
         assertEquals(clientIpAddr, request.mRequestedIp)
         reader.sendResponse(makeAckPacket(request.clientMac, request.transactionId))
@@ -244,7 +243,7 @@
 }
 
 private fun <T : DhcpPacket> TapPacketReader.assertDhcpPacketReceived(
-    packetType: KClass<T>,
+    packetType: Class<T>,
     timeoutMs: Long,
     type: Byte
 ): T {
@@ -254,7 +253,7 @@
     val packet = DhcpPacket.decodeFullPacket(packetBytes, packetBytes.size, DhcpPacket.ENCAP_L2)
     assertTrue(packetType.isInstance(packet),
             "Expected ${packetType.simpleName} but got ${packet.javaClass.simpleName}")
-    return packetType.java.cast(packet)
+    return packetType.cast(packet)
 }
 
 private fun <T> Context.assertHasService(manager: Class<T>): T {
diff --git a/tests/tests/net/src/android/net/cts/Ikev2VpnTest.java b/tests/tests/net/src/android/net/cts/Ikev2VpnTest.java
index 5cc0cb4..dff2581 100644
--- a/tests/tests/net/src/android/net/cts/Ikev2VpnTest.java
+++ b/tests/tests/net/src/android/net/cts/Ikev2VpnTest.java
@@ -46,13 +46,15 @@
 import android.net.TestNetworkManager;
 import android.net.VpnManager;
 import android.net.cts.util.CtsNetUtils;
+import android.os.Build;
 import android.platform.test.annotations.AppModeFull;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
 import com.android.org.bouncycastle.x509.X509V1CertificateGenerator;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DevSdkIgnoreRunner;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -70,7 +72,8 @@
 
 import javax.security.auth.x500.X500Principal;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
+@IgnoreUpTo(Build.VERSION_CODES.Q)
 @AppModeFull(reason = "Appops state changes disallowed for instant apps (OP_ACTIVATE_PLATFORM_VPN)")
 public class Ikev2VpnTest {
     private static final String TAG = Ikev2VpnTest.class.getSimpleName();
diff --git a/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
index 32cdf92..b1f3602 100644
--- a/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
+++ b/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -30,8 +30,8 @@
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.BroadcastReceiver;
-import android.content.Context;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
@@ -44,6 +44,8 @@
 import android.net.NetworkInfo.State;
 import android.net.NetworkRequest;
 import android.net.TestNetworkManager;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Build;
@@ -169,6 +171,7 @@
 
         boolean connected = false;
         try {
+            clearWifiBlacklist();
             SystemUtil.runShellCommand("svc wifi enable");
             SystemUtil.runWithShellPermissionIdentity(() -> mWifiManager.reconnect(),
                     NETWORK_SETTINGS);
@@ -188,11 +191,23 @@
         return wifiNetwork;
     }
 
+    /**
+     * Re-enable wifi networks that were blacklisted, typically because no internet connection was
+     * detected the last time they were connected. This is necessary to make sure wifi can reconnect
+     * to them.
+     */
+    private void clearWifiBlacklist() {
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) {
+                mWifiManager.enableNetwork(config.networkId, false /* attemptConnect */);
+            }
+        });
+    }
+
     /** Disable WiFi and wait for it to become disconnected from the network. */
     public void disconnectFromWifi(Network wifiNetworkToCheck) {
         final TestNetworkCallback callback = new TestNetworkCallback();
         mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback);
-        Network lostWifiNetwork = null;
 
         ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
                 mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED);
@@ -200,9 +215,15 @@
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mContext.registerReceiver(receiver, filter);
 
+        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        final boolean wasWifiConnected = wifiInfo != null && wifiInfo.getNetworkId() != -1;
         // Assert that we can establish a TCP connection on wifi.
         Socket wifiBoundSocket = null;
         if (wifiNetworkToCheck != null) {
+            assertTrue("Cannot check network " + wifiNetworkToCheck + ": wifi is not connected",
+                    wasWifiConnected);
+            final NetworkCapabilities nc = mCm.getNetworkCapabilities(wifiNetworkToCheck);
+            assertNotNull("Network " + wifiNetworkToCheck + " is not connected", nc);
             try {
                 wifiBoundSocket = getBoundSocket(wifiNetworkToCheck, TEST_HOST, HTTP_PORT);
                 testHttpRequest(wifiBoundSocket);
@@ -211,13 +232,14 @@
             }
         }
 
-        boolean disconnected = false;
         try {
             SystemUtil.runShellCommand("svc wifi disable");
-            // Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
-            lostWifiNetwork = callback.waitForLost();
-            assertNotNull(lostWifiNetwork);
-            disconnected = receiver.waitForState();
+            if (wasWifiConnected) {
+                // Ensure we get both an onLost callback and a CONNECTIVITY_ACTION.
+                assertNotNull("Did not receive onLost callback after disabling wifi",
+                        callback.waitForLost());
+                assertTrue("Wifi failed to reach DISCONNECTED state.", receiver.waitForState());
+            }
         } catch (InterruptedException ex) {
             fail("disconnectFromWifi was interrupted");
         } finally {
@@ -225,8 +247,6 @@
             mContext.unregisterReceiver(receiver);
         }
 
-        assertTrue("Wifi failed to reach DISCONNECTED state.", disconnected);
-
         // Check that the socket is closed when wifi disconnects.
         if (wifiBoundSocket != null) {
             try {
diff --git a/tests/tests/os/src/android/os/cts/FileObserverTest.java b/tests/tests/os/src/android/os/cts/FileObserverTest.java
index b853f89..9e61066 100644
--- a/tests/tests/os/src/android/os/cts/FileObserverTest.java
+++ b/tests/tests/os/src/android/os/cts/FileObserverTest.java
@@ -255,7 +255,7 @@
 
     @AppModeFull(reason = "Instant apps cannot access external storage")
     public void testFileObserverExternalStorageDirectory() throws Exception {
-        helpTestFileObserver(Environment.getExternalStorageDirectory(), false);
+        helpTestFileObserver(Environment.getExternalStorageDirectory(), true);
     }
 
     @AppModeFull(reason = "Instant apps cannot access external storage")
@@ -264,7 +264,7 @@
                 Pair.create(getContext().getCacheDir(), false),
                 Pair.create(getContext().getFilesDir(), false),
                 Pair.create(getContext().getExternalFilesDir(null), true),
-                Pair.create(Environment.getExternalStorageDirectory(), false)
+                Pair.create(Environment.getExternalStorageDirectory(), true)
         );
     }
 
diff --git a/tests/tests/packageinstaller/atomicinstall/AndroidManifest.xml b/tests/tests/packageinstaller/atomicinstall/AndroidManifest.xml
index 54d4260..1f8f283 100644
--- a/tests/tests/packageinstaller/atomicinstall/AndroidManifest.xml
+++ b/tests/tests/packageinstaller/atomicinstall/AndroidManifest.xml
@@ -17,7 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.tests.atomicinstall" >
 
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
     <application>
         <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
                   android:exported="true" />
diff --git a/tests/tests/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java b/tests/tests/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java
index d4e1530..004f8bc 100644
--- a/tests/tests/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java
+++ b/tests/tests/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java
@@ -43,7 +43,6 @@
             int stringId = permissionControllerContext.getResources().getIdentifier(
                     APP_PERMISSION_BUTTON_ALLOW_ALWAYS, "string",
                     "com.android.permissioncontroller");
-//                    mPermissionController); STOPSHIP b/147434671
 
             Assert.assertEquals(mContext.getPackageManager().getBackgroundPermissionOptionLabel(),
                     permissionControllerContext.getString(stringId));
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
index fde4b91..aa5b1be 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
@@ -63,6 +63,7 @@
     private Context mContext;
     private ContentResolver mResolver;
 
+    private Uri mExternalAudio;
     private Uri mExternalImages;
     private Uri mExternalFiles;
 
@@ -80,6 +81,7 @@
         mResolver = mContext.getContentResolver();
 
         Log.d(TAG, "Using volume " + mVolumeName);
+        mExternalAudio = MediaStore.Audio.Media.getContentUri(mVolumeName);
         mExternalImages = MediaStore.Images.Media.getContentUri(mVolumeName);
         mExternalFiles = MediaStore.Files.getContentUri(mVolumeName);
     }
@@ -329,9 +331,9 @@
     @Test
     public void testInPlaceUpdate_mediaFileWithInvalidRelativePath() throws Exception {
         final File file = new File(ProviderTestUtils.stageDownloadDir(mVolumeName),
-                "test" + System.nanoTime() + ".jpg");
-        ProviderTestUtils.stageFile(R.raw.scenery, file);
-        Log.d(TAG, "Staged image file at " + file.getAbsolutePath());
+                "test" + System.nanoTime() + ".mp3");
+        ProviderTestUtils.stageFile(R.raw.testmp3, file);
+        Log.d(TAG, "Staged audio file at " + file.getAbsolutePath());
 
         // Since file is created by shell, package name in MediaStore database row for this file
         // will not be test app's package name. To treat the insert as upsert, package name in
@@ -342,19 +344,14 @@
 
         final ContentValues insertValues = new ContentValues();
         insertValues.put(MediaColumns.DATA, file.getAbsolutePath());
-        insertValues.put(MediaStore.Images.ImageColumns.DESCRIPTION, "Not a cat photo");
-        final Uri uri = mResolver.insert(mExternalImages, insertValues);
-        assertEquals(0, queryLong(uri, MediaStore.Images.ImageColumns.IS_PRIVATE));
-        assertStringColumn(uri, MediaStore.Images.ImageColumns.DESCRIPTION, "Not a cat photo");
+        insertValues.put(MediaStore.Audio.AudioColumns.BOOKMARK, 42L);
+        final Uri uri = mResolver.insert(mExternalAudio, insertValues);
+        assertEquals(42L, queryLong(uri, MediaStore.Audio.AudioColumns.BOOKMARK));
 
         final ContentValues updateValues = new ContentValues();
-        updateValues.put(FileColumns.MEDIA_TYPE, FileColumns.MEDIA_TYPE_IMAGE);
-        updateValues.put(FileColumns.MIME_TYPE, "image/jpeg");
-        updateValues.put(MediaStore.Images.ImageColumns.IS_PRIVATE, 1);
-        int updateRows = mResolver.update(uri, updateValues, null, null);
-        assertEquals(1, updateRows);
-        // Only interested in update not throwing exception. No need in checking whenever values
-        // were actually updates, as it is not in the scope of this test.
+        updateValues.put(MediaStore.Audio.AudioColumns.BOOKMARK, 43L);
+        assertEquals(1, mResolver.update(uri, updateValues, null, null));
+        assertEquals(43L, queryLong(uri, MediaStore.Audio.AudioColumns.BOOKMARK));
     }
 
     @Test
diff --git a/tests/tests/telephony/current/LocationAccessingApp/src/android/telephony/cts/locationaccessingapp/CtsLocationAccessService.java b/tests/tests/telephony/current/LocationAccessingApp/src/android/telephony/cts/locationaccessingapp/CtsLocationAccessService.java
index 861de55..0b9d9c3 100644
--- a/tests/tests/telephony/current/LocationAccessingApp/src/android/telephony/cts/locationaccessingapp/CtsLocationAccessService.java
+++ b/tests/tests/telephony/current/LocationAccessingApp/src/android/telephony/cts/locationaccessingapp/CtsLocationAccessService.java
@@ -48,6 +48,7 @@
             "get_service_state_from_listener";
     public static final String COMMAND_LISTEN_CELL_LOCATION = "listen_cell_location";
     public static final String COMMAND_LISTEN_CELL_INFO = "listen_cell_info";
+    public static final String COMMAND_REQUEST_CELL_INFO_UPDATE = "request_cell_info_update";
 
     private static final long LISTENER_TIMEOUT = 1000;
 
@@ -84,6 +85,8 @@
                 case COMMAND_LISTEN_CELL_LOCATION:
                     result = listenForCellLocation();
                     break;
+                case COMMAND_REQUEST_CELL_INFO_UPDATE:
+                    result = requestCellInfoUpdate();
             }
             return Collections.singletonList(result);
         }
@@ -171,4 +174,31 @@
             handlerThread.quit();
         }
     }
+
+    private List<CellInfo> requestCellInfoUpdate() {
+        LinkedBlockingQueue<List<CellInfo>> queue = new LinkedBlockingQueue<>();
+        HandlerThread handlerThread = new HandlerThread("Telephony location CTS");
+        handlerThread.start();
+        Executor executor = new Handler(handlerThread.getLooper())::post;
+        TelephonyManager.CellInfoCallback cb = new TelephonyManager.CellInfoCallback() {
+            @Override
+            public void onCellInfo(List<CellInfo> cellInfo) {
+                queue.offer(cellInfo);
+            }
+        };
+
+        mTelephonyManager.requestCellInfoUpdate(executor, cb);
+
+        try {
+            List<CellInfo> ci = queue.poll(LISTENER_TIMEOUT, TimeUnit.MILLISECONDS);
+            if (ci == null) {
+                throw new RuntimeException("Timed out waiting for cell info");
+            }
+            return ci;
+        } catch (InterruptedException e) {
+            throw new RuntimeException("interrupted");
+        } finally {
+            handlerThread.quit();
+        }
+    }
 }
diff --git a/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java b/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java
index 1d234d7..6bfb156 100644
--- a/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java
+++ b/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.telephony.TelephonyManager;
@@ -48,6 +49,12 @@
         assertNotNull(mTelephonyManager);
     }
 
+    public static void grantUserReadPhoneStatePermission() {
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        uiAutomation.grantRuntimePermission(getContext().getPackageName(),
+                android.Manifest.permission.READ_PHONE_STATE);
+    }
+
     /**
      * Verify that TelephonyManager APIs requiring READ_PHONE_STATE Permission must work.
      * <p>
@@ -64,6 +71,8 @@
             return;
         }
 
+        grantUserReadPhoneStatePermission();
+
         try {
             mTelephonyManager.getNetworkType();
         } catch (SecurityException e) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java
index e038fef..8b9eaaf 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java
@@ -298,6 +298,9 @@
         doReturn(-1).when(cursor).getColumnIndex(eq(
                 Telephony.CellBroadcasts.ETWS_WARNING_TYPE));
 
+        doReturn(0).when(cursor).getColumnIndex(eq(
+                Telephony.CellBroadcasts.ETWS_IS_PRIMARY));
+
         doReturn(-1).when(cursor).getColumnIndex(eq(
                 Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS));
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyLocationTests.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyLocationTests.java
index 1c8e0c5..7b522f7 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyLocationTests.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyLocationTests.java
@@ -13,6 +13,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.telephony.CellInfo;
 import android.telephony.CellLocation;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
@@ -193,8 +194,25 @@
                 }
             }, Manifest.permission.ACCESS_COARSE_LOCATION);
         }, Manifest.permission.ACCESS_FINE_LOCATION);
-
     }
+
+    @Test
+    public void testSdk28CellInfoUpdate() {
+        if (!mShouldTest) return;
+
+        // Verify that a target-sdk 28 app still requires fine location access
+        // to call requestCellInfoUpdate
+        withRevokedPermission(LOCATION_ACCESS_APP_SDK28_PACKAGE, () -> {
+            try {
+                List<CellInfo> cis = (List<CellInfo>) performLocationAccessCommandSdk28(
+                        CtsLocationAccessService.COMMAND_REQUEST_CELL_INFO_UPDATE);
+                assertTrue(cis == null || cis.isEmpty());
+            } catch (SecurityException e) {
+                // expected
+            }
+        }, Manifest.permission.ACCESS_FINE_LOCATION);
+    }
+
     private ICtsLocationAccessControl getLocationAccessAppControl() {
         Intent bindIntent = new Intent(CtsLocationAccessService.CONTROL_ACTION);
         bindIntent.setComponent(new ComponentName(
diff --git a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 1055531..f7160dd 100644
--- a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -286,8 +286,9 @@
         assertTrue(tetheredIfaces.length == 0);
 
         final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
-        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
-                c -> c.run() /* executor */, startTetheringCallback);
+        final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
+                .setShouldShowEntitlementUi(false).build();
+        mTM.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
         startTetheringCallback.verifyTetheringStarted();
 
         mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs);
@@ -529,8 +530,9 @@
         assertFalse(isIfaceMatch(wifiRegexs, callback.getTetheredInterfaces()));
 
         final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
-        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
-                c -> c.run() /* executor */, startTetheringCallback);
+        final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
+                .setShouldShowEntitlementUi(false).build();
+        mTM.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
         startTetheringCallback.verifyTetheringStarted();
 
         callback.expectTetheredInterfacesChanged(wifiRegexs);
diff --git a/tests/tests/util/AndroidManifest.xml b/tests/tests/util/AndroidManifest.xml
index 3d402d5..77ab380 100644
--- a/tests/tests/util/AndroidManifest.xml
+++ b/tests/tests/util/AndroidManifest.xml
@@ -18,12 +18,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.util.cts">
 
-    <queries>
-        <package android:name="com.android.cts.install.lib.testapp.A" />
-        <package android:name="com.android.cts.install.lib.testapp.B" />
-        <package android:name="com.android.cts.install.lib.testapp.C" />
-    </queries>
-
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.READ_LOGS" />
     <application>
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
index 7670a52..59aa5c0 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
@@ -21,6 +21,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static junit.framework.TestCase.assertFalse;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
 import android.app.UiAutomation;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -40,15 +47,23 @@
 import android.os.WorkSource;
 import android.platform.test.annotations.AppModeFull;
 import android.support.test.uiautomator.UiDevice;
-import android.test.AndroidTestCase;
 import android.text.TextUtils;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.ShellIdentityUtils;
 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.Test;
+import org.junit.runner.RunWith;
+
 import java.util.List;
 import java.util.concurrent.Executors;
 
@@ -61,9 +76,15 @@
  * TODO(b/150716005): Use assumeTrue for wifi support check.
  */
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-public class WifiNetworkSpecifierTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WifiNetworkSpecifierTest {
     private static final String TAG = "WifiNetworkSpecifierTest";
 
+    private static boolean sWasVerboseLoggingEnabled;
+    private static boolean sWasScanThrottleEnabled;
+
+    private Context mContext;
     private WifiManager mWifiManager;
     private ConnectivityManager mConnectivityManager;
     private UiDevice mUiDevice;
@@ -71,8 +92,6 @@
     private final Object mUiLock = new Object();
     private WifiConfiguration mTestNetwork;
     private TestNetworkCallback mNetworkCallback;
-    private boolean mWasVerboseLoggingEnabled;
-    private boolean mWasScanThrottleEnabled;
 
     private static final int DURATION = 10_000;
     private static final int DURATION_UI_INTERACTION = 25_000;
@@ -80,77 +99,100 @@
     private static final int DURATION_SCREEN_TOGGLE = 2000;
     private static final int SCAN_RETRY_CNT_TO_FIND_MATCHING_BSSID = 3;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
-        mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
-        mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
-        assertNotNull(mWifiManager);
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip the test if WiFi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(context));
+
+        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        assertNotNull(wifiManager);
 
         // turn on verbose logging for tests
-        mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.isVerboseLoggingEnabled());
+        sWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> wifiManager.isVerboseLoggingEnabled());
         ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.setVerboseLoggingEnabled(true));
+                () -> wifiManager.setVerboseLoggingEnabled(true));
         // Disable scan throttling for tests.
-        mWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.isScanThrottleEnabled());
+        sWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> wifiManager.isScanThrottleEnabled());
         ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.setScanThrottleEnabled(false));
+                () -> wifiManager.setScanThrottleEnabled(false));
 
         // enable Wifi
-        if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
-        PollingCheck.check("Wifi not enabled", DURATION, () -> mWifiManager.isWifiEnabled());
-
-        // turn screen on
-        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        turnScreenOn();
+        if (!wifiManager.isWifiEnabled()) setWifiEnabled(true);
+        PollingCheck.check("Wifi not enabled", DURATION, () -> wifiManager.isWifiEnabled());
 
         // check we have >= 1 saved network
         List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.getPrivilegedConfiguredNetworks());
+                () -> wifiManager.getPrivilegedConfiguredNetworks());
         assertFalse("Need at least one saved network", savedNetworks.isEmpty());
 
-        // Pick any one of the saved networks on the device (assumes that it is in range)
-        mTestNetwork = savedNetworks.get(0);
         // Disconnect & disable auto-join on the saved network to prevent auto-connect from
         // interfering with the test.
         ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.disableNetwork(mTestNetwork.networkId));
-        // wait for Wifi to be disconnected
+                () -> {
+                    for (WifiConfiguration savedNetwork : savedNetworks) {
+                        wifiManager.disableNetwork(savedNetwork.networkId);
+                    }
+                });
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!WifiFeature.isWifiSupported(context)) return;
+
+        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        assertNotNull(wifiManager);
+
+        if (!wifiManager.isWifiEnabled()) setWifiEnabled(true);
+
+        // Re-enable networks.
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> {
+                    for (WifiConfiguration savedNetwork : wifiManager.getConfiguredNetworks()) {
+                        wifiManager.enableNetwork(savedNetwork.networkId, false);
+                    }
+                });
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> wifiManager.setScanThrottleEnabled(sWasScanThrottleEnabled));
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> wifiManager.setVerboseLoggingEnabled(sWasVerboseLoggingEnabled));
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+        // turn screen on
+        turnScreenOn();
+
+        List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.getPrivilegedConfiguredNetworks());
+        // Pick any one of the saved networks on the device (assumes that it is in range)
+        mTestNetwork = savedNetworks.get(0);
+
+        // Wait for Wifi to be disconnected.
         PollingCheck.check(
                 "Wifi not disconnected",
                 20000,
                 () -> mWifiManager.getConnectionInfo().getNetworkId() == -1);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            super.tearDown();
-            return;
-        }
-        if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
-        turnScreenOff();
+    @After
+    public void tearDown() throws Exception {
         // If there is failure, ensure we unregister the previous request.
         if (mNetworkCallback != null) {
             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
         }
-        ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.enableNetwork(mTestNetwork.networkId, true));
-        ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.setScanThrottleEnabled(mWasScanThrottleEnabled));
-        ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
-        super.tearDown();
+        turnScreenOff();
     }
 
-    private void setWifiEnabled(boolean enable) throws Exception {
+    private static void setWifiEnabled(boolean enable) throws Exception {
         // now trigger the change using shell commands.
         SystemUtil.runShellCommand("svc wifi " + (enable ? "enable" : "disable"));
     }
@@ -398,11 +440,8 @@
     /**
      * Tests the entire connection flow using a specific SSID in the specifier.
      */
+    @Test
     public void testConnectionWithSpecificSsid() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
                 .setSsid(removeDoubleQuotes(mTestNetwork.SSID))
                 .build();
@@ -412,11 +451,8 @@
     /**
      * Tests the entire connection flow using a SSID pattern in the specifier.
      */
+    @Test
     public void testConnectionWithSsidPattern() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         // Creates a ssid pattern by dropping the last char in the saved network & pass that
         // as a prefix match pattern in the request.
         String ssidUnquoted = removeDoubleQuotes(mTestNetwork.SSID);
@@ -486,11 +522,8 @@
     /**
      * Tests the entire connection flow using a specific BSSID in the specifier.
      */
+    @Test
     public void testConnectionWithSpecificBssid() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         ScanResult scanResult = findScanResultMatchingSavedNetwork();
         WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
                 .setBssid(MacAddress.fromString(scanResult.BSSID))
@@ -501,11 +534,8 @@
     /**
      * Tests the entire connection flow using a BSSID pattern in the specifier.
      */
+    @Test
     public void testConnectionWithBssidPattern() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         ScanResult scanResult = findScanResultMatchingSavedNetwork();
         // Note: The match may return more than 1 network in this case since we use a prefix match,
         // But, we will still ensure that the UI interactions in the test still selects the
@@ -520,11 +550,8 @@
     /**
      * Tests the entire connection flow using a BSSID pattern in the specifier.
      */
+    @Test
     public void testUserRejectionWithSpecificSsid() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
                 .setSsid(removeDoubleQuotes(mTestNetwork.SSID))
                 .build();
@@ -535,11 +562,8 @@
      * Tests the builder for WPA2 enterprise networks.
      * Note: Can't do end to end tests for such networks in CTS environment.
      */
+    @Test
     public void testBuilderForWpa2Enterprise() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
                 .setSsid(removeDoubleQuotes(mTestNetwork.SSID))
                 .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
@@ -555,11 +579,8 @@
      * Tests the builder for WPA3 enterprise networks.
      * Note: Can't do end to end tests for such networks in CTS environment.
      */
+    @Test
     public void testBuilderForWpa3Enterprise() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
         WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
                 .setSsid(removeDoubleQuotes(mTestNetwork.SSID))
                 .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())