Merge "Always set secure FRP setting on user 0" into rvc-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 14bbc39..8b45f84 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -209,7 +209,7 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_device_admin" />
-            <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive:android.software.lockscreen_disabled" />
+            <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive:android.hardware.type.television:android.software.lockscreen_disabled" />
             <meta-data android:name="test_required_features"
                     android:value="android.software.device_admin" />
         </activity>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index b1e0388..b898bc9 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -2356,7 +2356,7 @@
     <!-- Strings for CA cert installation via intent test -->
     <string name="cacert_install_via_intent">CA Cert install via intent</string>
     <string name="cacert_install_via_intent_title">This test attempts to install a CA certificate via an intent.</string>
-    <string name="cacert_install_via_intent_info">Attempt installing a CA certificate via an intent, which should fail. If you see a dialog redirecting the user to Settings for installing the certificate, the test passed. If a any other dialog comes up, the test failed.</string>
+    <string name="cacert_install_via_intent_info">Attempt installing a CA certificate via an intent, which should not be possible. Tapping Go should show a dialog telling the user that CA certificates can put their privacy at risk and must be installed via Settings. If a any other dialog comes up, the test failed.</string>
 
     <!-- Strings for Widget -->
     <string name="widget_framework_test">Widget Framework Test</string>
@@ -3983,7 +3983,7 @@
         Please press \'Create uninitialized user\' to create a user that is not set up. Then press the
         \'Set restriction\' button to set the user restriction.
         Then press \'Go\' to open \'Multiple users\' setting. \n
-        Click the Settings icon adjacent to the managed user.\n\n
+        Click the managed user to open settings.\n\n
 
         Mark this test as passed if:\n\n
         - \"Delete User\" is disabled.\n
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
index 62892d6..1a829f2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
@@ -127,6 +127,7 @@
                 mNetworkSuggestionBuilder.setWpa3Passphrase(mPsk);
             }
         }
+        mNetworkSuggestionBuilder.setIsMetered(false);
         return mNetworkSuggestionBuilder.build();
     }
 
diff --git a/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java b/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
index 11a1ae0..bea7506 100644
--- a/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
+++ b/hostsidetests/adb/src/android/adb/cts/AdbHostTest.java
@@ -59,8 +59,13 @@
         File check_ms_os_desc = copyResourceToTempFile("/check_ms_os_desc");
         check_ms_os_desc.setExecutable(true);
 
+        String serial = getDevice().getSerialNumber();
+        if (serial.startsWith("emulator-")) {
+            return;
+        }
+
         ProcessBuilder pb = new ProcessBuilder(check_ms_os_desc.getAbsolutePath());
-        pb.environment().put("ANDROID_SERIAL", getDevice().getSerialNumber());
+        pb.environment().put("ANDROID_SERIAL", serial);
         pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
         pb.redirectErrorStream(true);
         Process p = pb.start();
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
index 3900d4a..f939b17 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
@@ -111,8 +111,10 @@
         device.uninstallPackage("com.android.appsecurity.b71360999");
         device.uninstallPackage("com.android.appsecurity.b71361168");
         device.uninstallPackage("com.android.appsecurity.b79488511");
-        device.uninstallPackage(CORRUPT_APK_PACKAGE_NAME);
+        // WARNING: PlatformCompat overrides for package parsing changes must be reset before the
+        // package is uninstalled because overrides cannot be reset if the package is not present.
         device.executeShellCommand("am compat reset-all " + CORRUPT_APK_PACKAGE_NAME);
+        device.uninstallPackage(CORRUPT_APK_PACKAGE_NAME);
     }
 
     @Before
@@ -132,7 +134,7 @@
     private String install(String apk) throws DeviceNotAvailableException, FileNotFoundException  {
         return getDevice().installPackage(
                 new CompatibilityBuildHelper(mBuildInfo).getTestFile(apk),
-                false /*reinstall*/);
+                true /* reinstall */);
     }
 
     /**
@@ -167,12 +169,13 @@
         assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b79488511.apk");
     }
 
-    /** APKs that target pre-Q and have a compressed resources.arsc can be installed. */
+    /** APKs that target pre-R and have a compressed resources.arsc can be installed. */
     public void testFailInstallCompressedARSC_Q() throws Exception {
         assertNull(install(COMPRESSED_ARSC_Q));
     }
 
     public void testFailInstallCompressedARSC_Q_PlatformConfig_enabled() throws Exception {
+        assertNull(install(COMPRESSED_ARSC_Q));
         getDevice().executeShellCommand(String.format("am compat enable %s %s",
                 FAIL_COMPRESSED_ARSC_PLATFORM_CONFIG_ID, CORRUPT_APK_PACKAGE_NAME));
         assertNotNull(install(COMPRESSED_ARSC_Q));
@@ -183,18 +186,13 @@
         assertNotNull(install(COMPRESSED_ARSC_R));
     }
 
-    public void testFailInstallCompressedARSC_R_PlatformConfig_disabled() throws Exception {
-        getDevice().executeShellCommand(String.format("am compat disable %s %s",
-                FAIL_COMPRESSED_ARSC_PLATFORM_CONFIG_ID, CORRUPT_APK_PACKAGE_NAME));
-        assertNull(install(COMPRESSED_ARSC_R));
-    }
-
-    /** APKs that target pre-Q and have a unaligned resources.arsc can be installed. */
+    /** APKs that target pre-R and have a unaligned resources.arsc can be installed. */
     public void testFailInstallUnalignedARSC_Q() throws Exception {
         assertNull(install(UNALIGNED_ARSC_Q));
     }
 
     public void testFailInstallUnalignedARSC_Q_PlatformConfig_enabled() throws Exception {
+        assertNull(install(UNALIGNED_ARSC_Q));
         getDevice().executeShellCommand(String.format("am compat enable %s %s",
                 FAIL_COMPRESSED_ARSC_PLATFORM_CONFIG_ID, CORRUPT_APK_PACKAGE_NAME));
         assertNotNull(install(UNALIGNED_ARSC_Q));
@@ -204,10 +202,4 @@
     public void testFailInstallUnalignedARSC_R() throws Exception {
         assertNotNull(install(UNALIGNED_ARSC_R));
     }
-
-    public void testFailInstallUnalignedARSC_R_PlatformConfig_disabled() throws Exception {
-        getDevice().executeShellCommand(String.format("am compat disable %s %s",
-                FAIL_COMPRESSED_ARSC_PLATFORM_CONFIG_ID, CORRUPT_APK_PACKAGE_NAME));
-        assertNull(install(UNALIGNED_ARSC_R));
-    }
 }
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.bp b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.bp
index 915d9a9..0994422 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.bp
@@ -32,4 +32,28 @@
         "vts10",
         "general-tests",
     ]
+}
+
+android_test_import {
+    name: "CtsCorruptApkTests_Unaligned_Q",
+    apk: "unaligned_Q.apk",
+    presigned: true,
+    preprocessed: true,
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ]
+}
+
+android_test_import {
+    name: "CtsCorruptApkTests_Unaligned_R",
+    apk: "unaligned_R.apk",
+    presigned: true,
+    preprocessed: true,
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ]
 }
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.mk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.mk
deleted file mode 100644
index ae419b6..0000000
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2020 Google Inc.
-#
-# 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.
-#
-
-LOCAL_PATH := $(my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CtsCorruptApkTests_Unaligned_Q
-LOCAL_SRC_FILES := unaligned_Q.apk
-LOCAL_MODULE_CLASS := APPS
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_SUFFIX := .apk
-LOCAL_CERTIFICATE := PRESIGNED
-LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/unaligned_Q.apk
-LOCAL_COMPATIBILITY_SUITE := cts vts10 general-tests
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CtsCorruptApkTests_Unaligned_R
-LOCAL_SRC_FILES := unaligned_R.apk
-LOCAL_MODULE_CLASS := APPS
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_SUFFIX := .apk
-LOCAL_CERTIFICATE := PRESIGNED
-LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/unaligned_R.apk
-LOCAL_COMPATIBILITY_SUITE := cts vts10 general-tests
-include $(BUILD_PREBUILT)
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/AndroidManifest.xml
index b574029..93a223d 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/AndroidManifest.xml
@@ -17,5 +17,6 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.content.cts.corruptapk" >
-    <application android:hasCode="false" />
+    <application android:hasCode="false"
+                 android:debuggable="true"/>
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_Q.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_Q.apk
index 58c30cd..afaac5d 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_Q.apk
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_Q.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_R.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_R.apk
index 1bdd2bb..ecb009f 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_R.apk
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/compressed_R.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_Q.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_Q.apk
index b6023bc..a17200b 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_Q.apk
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_Q.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_R.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_R.apk
index e64bcfd..7296b84 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_R.apk
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/compressed_arsc/unaligned_R.apk
Binary files differ
diff --git a/hostsidetests/devicepolicy/AndroidTest.xml b/hostsidetests/devicepolicy/AndroidTest.xml
index 575dc04..b579e97 100644
--- a/hostsidetests/devicepolicy/AndroidTest.xml
+++ b/hostsidetests/devicepolicy/AndroidTest.xml
@@ -23,6 +23,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <!-- Device admin/owner requires being run in system user -->
     <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
 
     <!-- Push the list of public APIs to device -->
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
diff --git a/hostsidetests/graphics/gpuprofiling/AndroidTest.xml b/hostsidetests/graphics/gpuprofiling/AndroidTest.xml
index 6dd7410..bfaa33e 100644
--- a/hostsidetests/graphics/gpuprofiling/AndroidTest.xml
+++ b/hostsidetests/graphics/gpuprofiling/AndroidTest.xml
@@ -20,9 +20,13 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsGraphicsProfilingDataApp.apk" />
+    </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
-        <option name="push" value="ctsgraphicsgpuprofilinginit->/data/local/tmp/ctsgraphicsgpuprofilinginit" />
+        <option name="push" value="ctsgraphicsgpucountersinit->/data/local/tmp/ctsgraphicsgpucountersinit" />
         <option name="append-bitness" value="true" />
     </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
diff --git a/hostsidetests/graphics/gpuprofiling/app/Android.bp b/hostsidetests/graphics/gpuprofiling/app/Android.bp
index 6c05ece..9bb6ce7 100644
--- a/hostsidetests/graphics/gpuprofiling/app/Android.bp
+++ b/hostsidetests/graphics/gpuprofiling/app/Android.bp
@@ -13,11 +13,11 @@
 // limitations under the License.
 
 cc_test {
-    name: "ctsgraphicsgpuprofilinginit",
+    name: "ctsgraphicsgpucountersinit",
     srcs: [
-        "android_graphics_cts_GpuProfilingData.cpp",
+        "android_graphics_cts_GpuCounters.cpp",
     ],
-    test_suites: ["cts"],
+    test_suites: ["cts", "general-tests"],
     compile_multilib: "both",
     multilib: {
         lib32: {
@@ -34,9 +34,44 @@
     shared_libs: [
         "libdl",
         "libandroid",
-        "libvulkan",
         "liblog",
     ],
     stl: "c++_static",
     sdk_version: "current",
 }
+
+cc_test_library {
+    name: "libctsgraphicsgpuprofiling_jni",
+    gtest: false,
+    srcs: [
+        "jni/CtsGraphicsProfilingDataJniOnLoad.cpp",
+        "jni/android_graphics_cts_GpuRenderStages.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    header_libs: ["jni_headers"],
+    shared_libs: [
+        "libandroid",
+        "libvulkan",
+        "liblog",
+    ],
+    stl: "c++_shared",
+    sdk_version: "current",
+}
+
+android_test_helper_app {
+    name: "CtsGraphicsProfilingDataApp",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+    // tag this module as a cts test artifact
+    test_suites: ["cts", "general-tests"],
+    compile_multilib: "both",
+    jni_libs: [
+        "libctsgraphicsgpuprofiling_jni",
+    ],
+    use_embedded_native_libs: false,
+    stl: "c++_shared",
+}
\ No newline at end of file
diff --git a/hostsidetests/graphics/gpuprofiling/app/AndroidManifest.xml b/hostsidetests/graphics/gpuprofiling/app/AndroidManifest.xml
new file mode 100644
index 0000000..da58bef
--- /dev/null
+++ b/hostsidetests/graphics/gpuprofiling/app/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="android.graphics.gpuprofiling.app">
+    <application android:extractNativeLibs="true" android:debuggable="true">
+        <activity android:name=".GpuRenderStagesDeviceActivity" android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/hostsidetests/graphics/gpuprofiling/app/android_graphics_cts_GpuCounters.cpp b/hostsidetests/graphics/gpuprofiling/app/android_graphics_cts_GpuCounters.cpp
new file mode 100644
index 0000000..c710d4f
--- /dev/null
+++ b/hostsidetests/graphics/gpuprofiling/app/android_graphics_cts_GpuCounters.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 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.
+ *
+ */
+
+#define LOG_TAG "GpuProfilingData"
+
+#include <chrono>
+#include <csignal>
+#include <string>
+#include <thread>
+#include <unistd.h>
+#include <vector>
+
+#include <android/log.h>
+#include <dlfcn.h>
+
+#define ALOGI(msg, ...)                                                        \
+  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
+#define ALOGE(msg, ...)                                                        \
+  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, (msg), __VA_ARGS__)
+#define ALOGD(msg, ...)                                                        \
+  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, (msg), __VA_ARGS__)
+#define REQUIRE_SUCCESS(fn, name)                                              \
+  do {                                                                         \
+    if (VK_SUCCESS != fn) {                                                    \
+      ALOGE("Vulkan Error in %s", name);                                       \
+      return -1;                                                               \
+    }                                                                          \
+  } while (0)
+
+namespace {
+
+typedef void (*FN_PTR)(void);
+
+/**
+ * Load the vendor provided counter producer library.
+ * startCounterProducer is a thin rewrite of the same producer loading logic in
+ * github.com/google/agi
+ */
+
+int startCounterProducer() {
+  ALOGI("%s", "Loading producer library");
+  char *error;
+  std::string libDir = sizeof(void *) == 8 ? "lib64" : "lib";
+  std::string producerPath = "/vendor/" + libDir + "/libgpudataproducer.so";
+
+  ALOGI("Trying %s", producerPath.c_str());
+  void *handle = dlopen(producerPath.c_str(), RTLD_GLOBAL);
+  if ((error = dlerror()) != nullptr || handle == nullptr) {
+    ALOGE("Error loading lib: %s", error);
+    return -1;
+  }
+
+  FN_PTR startFunc = (FN_PTR)dlsym(handle, "start");
+  if ((error = dlerror()) != nullptr) {
+    ALOGE("Error looking for start symbol: %s", error);
+    dlclose(handle);
+    return -1;
+  }
+
+  if (startFunc == nullptr) {
+    ALOGE("Did not find the producer library %s", producerPath.c_str());
+    ALOGE("LD_LIBRARY_PATH=%s", getenv("LD_LIBRARY_PATH"));
+    return -1;
+  }
+
+  ALOGI("Calling start at %p", startFunc);
+  (*startFunc)();
+  ALOGI("Producer %s has exited.", producerPath.c_str());
+  dlclose(handle);
+  return 0;
+}
+
+volatile std::sig_atomic_t done = 0;
+
+} // anonymous namespace
+
+int main() {
+  std::signal(SIGTERM, [](int /*signal*/) {
+    ALOGI("%s", "SIGTERM received");
+    done = 1;
+  });
+  std::thread dummy([&]() {
+    int result = startCounterProducer();
+    ALOGI("%s %d", "startCounterProducer returned", result);
+  });
+  ALOGI("%s", "Waiting for host");
+  while (!done) {
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+  }
+  return 0;
+}
diff --git a/hostsidetests/graphics/gpuprofiling/app/jni/CtsGraphicsProfilingDataJniOnLoad.cpp b/hostsidetests/graphics/gpuprofiling/app/jni/CtsGraphicsProfilingDataJniOnLoad.cpp
new file mode 100644
index 0000000..5948ff8
--- /dev/null
+++ b/hostsidetests/graphics/gpuprofiling/app/jni/CtsGraphicsProfilingDataJniOnLoad.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+
+extern int register_android_gputools_cts_GpuProfilingData(JNIEnv *);
+
+jint JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
+  JNIEnv *env = nullptr;
+  if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK)
+    return JNI_ERR;
+  if (register_android_gputools_cts_GpuProfilingData(env))
+    return JNI_ERR;
+  return JNI_VERSION_1_4;
+}
\ No newline at end of file
diff --git a/hostsidetests/graphics/gpuprofiling/app/android_graphics_cts_GpuProfilingData.cpp b/hostsidetests/graphics/gpuprofiling/app/jni/android_graphics_cts_GpuRenderStages.cpp
similarity index 70%
rename from hostsidetests/graphics/gpuprofiling/app/android_graphics_cts_GpuProfilingData.cpp
rename to hostsidetests/graphics/gpuprofiling/app/jni/android_graphics_cts_GpuRenderStages.cpp
index 19439c0..e0d49c0 100644
--- a/hostsidetests/graphics/gpuprofiling/app/android_graphics_cts_GpuProfilingData.cpp
+++ b/hostsidetests/graphics/gpuprofiling/app/jni/android_graphics_cts_GpuRenderStages.cpp
@@ -17,15 +17,12 @@
 
 #define LOG_TAG "GpuProfilingData"
 
-#include <chrono>
-#include <csignal>
-#include <string>
-#include <thread>
-#include <unistd.h>
 #include <vector>
 
 #include <android/log.h>
 #include <dlfcn.h>
+#include <jni.h>
+#include <string>
 #include <vulkan/vulkan.h>
 
 #define ALOGI(msg, ...)                                                        \
@@ -46,48 +43,7 @@
 
 typedef void (*FN_PTR)(void);
 
-/**
- * Load the vendor provided counter producer library.
- * startCounterProducer is a thin rewrite of the same producer loading logic in
- * github.com/google/agi
- */
-
-int startCounterProducer() {
-  ALOGI("%s", "Loading producer library");
-  char *error;
-  std::string libDir = sizeof(void *) == 8 ? "lib64" : "lib";
-  std::string producerPath = "/vendor/" + libDir + "/libgpudataproducer.so";
-
-  ALOGI("Trying %s", producerPath.c_str());
-  void *handle = dlopen(producerPath.c_str(), RTLD_GLOBAL);
-  if ((error = dlerror()) != nullptr || handle == nullptr) {
-    ALOGE("Error loading lib: %s", error);
-    return -1;
-  }
-
-  FN_PTR startFunc = (FN_PTR)dlsym(handle, "start");
-  if ((error = dlerror()) != nullptr) {
-    ALOGE("Error looking for start symbol: %s", error);
-    dlclose(handle);
-    return -1;
-  }
-
-  if (startFunc == nullptr) {
-    ALOGE("Did not find the producer library %s", producerPath.c_str());
-    ALOGE("LD_LIBRARY_PATH=%s", getenv("LD_LIBRARY_PATH"));
-    return -1;
-  }
-
-  ALOGI("Calling start at %p", startFunc);
-  (*startFunc)();
-  ALOGI("Producer %s has exited.", producerPath.c_str());
-  dlclose(handle);
-  return 0;
-}
-
-int initVulkan(VkDevice &device) {
-  std::string result = "";
-
+int initVulkan() {
   const VkApplicationInfo appInfo = {
       VK_STRUCTURE_TYPE_APPLICATION_INFO,
       nullptr,            // pNext
@@ -171,34 +127,27 @@
       nullptr,
   };
 
+  VkDevice device;
+
   REQUIRE_SUCCESS(
       vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device),
       "vkCreateDevice");
-
   return 0;
 }
 
-volatile std::sig_atomic_t done = 0;
+jint android_graphics_cts_GpuProfilingData_nativeInitVulkan(JNIEnv * /*env*/,
+                                                            jclass /*clazz*/) {
+  return (jint)initVulkan();
+}
 
+static JNINativeMethod gMethods[] = {
+    {"nativeInitVulkan", "()I",
+     (void *)android_graphics_cts_GpuProfilingData_nativeInitVulkan}};
 } // anonymous namespace
 
-int main() {
-  ALOGI("%s", "Creating Vulkan device");
-  VkDevice device;
-  std::signal(SIGTERM, [](int /*signal*/) {
-    ALOGI("%s", "SIGTERM received");
-    done = 1;
-  });
-  int result = initVulkan(device);
-  ALOGI("%s %d", "initVulkan returned", result);
-  std::thread dummy([&]() {
-    result = startCounterProducer();
-    ALOGI("%s %d", "startCounterProducer returned", result);
-  });
-  ALOGI("%s", "Waiting for host");
-  while (!done) {
-    std::this_thread::sleep_for(std::chrono::milliseconds(100));
-  }
-  vkDestroyDevice(device, nullptr);
-  return 0;
-}
+int register_android_gputools_cts_GpuProfilingData(JNIEnv *env) {
+  jclass clazz = env->FindClass(
+      "android/graphics/gpuprofiling/app/GpuRenderStagesDeviceActivity");
+  return env->RegisterNatives(clazz, gMethods,
+                              sizeof(gMethods) / sizeof(JNINativeMethod));
+}
\ No newline at end of file
diff --git a/hostsidetests/graphics/gpuprofiling/app/src/android/gpuprofiling/GpuRenderStagesDeviceActivity.java b/hostsidetests/graphics/gpuprofiling/app/src/android/gpuprofiling/GpuRenderStagesDeviceActivity.java
new file mode 100644
index 0000000..e6bd660
--- /dev/null
+++ b/hostsidetests/graphics/gpuprofiling/app/src/android/gpuprofiling/GpuRenderStagesDeviceActivity.java
@@ -0,0 +1,42 @@
+/*
+ * 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.graphics.gpuprofiling.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.lang.Override;
+
+public class GpuRenderStagesDeviceActivity extends Activity {
+
+    static {
+        System.loadLibrary("ctsgraphicsgpuprofiling_jni");
+    }
+
+    private static final String TAG = GpuRenderStagesDeviceActivity.class.getSimpleName();
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        int result = nativeInitVulkan();
+        Log.i(TAG, "nativeInitVulkan returned: " + result);
+        Log.i(TAG, "GpuProfilingData activity complete");
+    }
+
+    private static native int nativeInitVulkan();
+}
diff --git a/hostsidetests/graphics/gpuprofiling/src/android/graphics/gpuprofiling/cts/CtsGpuProfilingDataTest.java b/hostsidetests/graphics/gpuprofiling/src/android/graphics/gpuprofiling/cts/CtsGpuProfilingDataTest.java
index ff33375..f5654cd 100644
--- a/hostsidetests/graphics/gpuprofiling/src/android/graphics/gpuprofiling/cts/CtsGpuProfilingDataTest.java
+++ b/hostsidetests/graphics/gpuprofiling/src/android/graphics/gpuprofiling/cts/CtsGpuProfilingDataTest.java
@@ -17,6 +17,7 @@
 package android.graphics.gpuprofiling.cts;
 
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.util.CommandResult;
@@ -46,11 +47,16 @@
     // Positive tests
     // - Ensure the perfetto producers for render stages, counters, and ftrace gpu frequency are available
 
-    private static final String BIN_NAME = "ctsgraphicsgpuprofilinginit";
+    private static final String BIN_NAME = "ctsgraphicsgpucountersinit";
     private static final String DEVICE_BIN_PATH = "/data/local/tmp/" + BIN_NAME;
+    private static final String APP = "android.graphics.gpuprofiling.app";
+    private static final String APK = "CtsGraphicsProfilingDataApp.apk";
+    private static final String ACTIVITY = "GpuRenderStagesDeviceActivity";
     private static final String COUNTERS_SOURCE_NAME = "gpu.counters";
     private static final String STAGES_SOURCE_NAME = "gpu.renderstages";
-    private static final String PROFILING_PROPERTY = "ro.hardware.gpu.profiler.support";
+    private static final String PROFILING_PROPERTY = "graphics.gpu.profiler.support";
+    private static final String LAYER_PACKAGE_PROPERTY = "graphics.gpu.profiler.vulkan_layer_apk";
+    private static final String LAYER_NAME = "VkRenderStagesProducer";
     private static int MAX_RETRIES = 5;
 
     private class ShellThread extends Thread {
@@ -65,28 +71,40 @@
         @Override
         public void run() {
             try {
-                CommandResult activityStatus = getDevice().executeShellV2Command(mCmd);
+                getDevice().executeShellV2Command(mCmd);
             } catch (Exception e) {
-                // TODO Do something here?
+                CLog.e("Failed to start counters producer" + e.getMessage());
             }
         }
     }
 
     /**
-     * Kill the native process after each test
+     * Kill the native process and remove the layer related settings after each test
      */
     @After
     public void cleanup() throws Exception {
-        // TODO figure out how to unregister the producers
         getDevice().executeShellV2Command("killall " + BIN_NAME);
+        getDevice().executeShellV2Command("am force-stop " + APP);
+        getDevice().executeShellV2Command("settings delete global gpu_debug_layers");
+        getDevice().executeShellV2Command("settings delete global enable_gpu_debug_layers");
+        getDevice().executeShellV2Command("settings delete global gpu_debug_app");
+        getDevice().executeShellV2Command("settings delete global gpu_debug_layer_app");
     }
 
     /**
-     * Clean up before starting any tests.
+     * Clean up before starting any tests. Apply the necessary layer settings if we need them
      */
     @Before
     public void init() throws Exception {
         cleanup();
+        String layerApp = getDevice().getProperty(LAYER_PACKAGE_PROPERTY);
+        if (layerApp != null && !layerApp.isEmpty()) {
+            getDevice().executeShellV2Command("settings put global enable_gpu_debug_layers 1");
+            getDevice().executeShellV2Command("settings put global gpu_debug_app " + APP);
+            getDevice().executeShellV2Command("settings put global gpu_debug_layer_app " + layerApp);
+            getDevice().executeShellV2Command("settings put global gpu_debug_layers " + LAYER_NAME);
+        }
+        installPackage(APK);
     }
 
     /**
@@ -100,6 +118,7 @@
             // Spin up a new thread to avoid blocking the main thread while the native process waits to be killed.
             ShellThread shellThread = new ShellThread(DEVICE_BIN_PATH);
             shellThread.start();
+            CommandResult activityStatus = getDevice().executeShellV2Command("am start -n " + APP + "/." + ACTIVITY);
             boolean countersSourceFound = false;
             boolean stagesSourceFound = false;
             for(int i = 0; i < MAX_RETRIES; i++) {
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java
index 33e3e94..dbfa9fb 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java
@@ -33,7 +33,8 @@
 
     private void setupNewPublicVolume() throws Exception {
         if (!mIsPublicVolumeSetup) {
-            runDeviceTest("setupNewPublicVolume");
+            assertTrue(runDeviceTests("android.scopedstorage.cts",
+                    "android.scopedstorage.cts.PublicVolumeTestHelper", "setupNewPublicVolume"));
             mIsPublicVolumeSetup = true;
         }
     }
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java
index 8ed0101..c9bd65f 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java
@@ -33,7 +33,8 @@
 
     private void setupNewPublicVolume() throws Exception {
         if (!mIsPublicVolumeSetup) {
-            runDeviceTest("setupNewPublicVolume");
+            assertTrue(runDeviceTests("android.scopedstorage.cts",
+                    "android.scopedstorage.cts.PublicVolumeTestHelper", "setupNewPublicVolume"));
             mIsPublicVolumeSetup = true;
         }
     }
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 108b3e8..88be97c 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -166,6 +166,7 @@
         runDeviceTest("testCreateUpperCaseDeleteLowerCase");
         runDeviceTest("testCreateMixedCaseDeleteDifferentMixedCase");
         runDeviceTest("testAndroidDataObbDoesNotForgetMount");
+        runDeviceTest("testCacheConsistencyForCaseInsensitivity");
     }
 
     @Test
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/PublicVolumeLegacyTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/PublicVolumeLegacyTest.java
index 57ddf29..7e59505 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/PublicVolumeLegacyTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/PublicVolumeLegacyTest.java
@@ -23,7 +23,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
-import org.junit.Test;
 import org.junit.runner.RunWith;
 
 /**
@@ -39,13 +38,4 @@
         TestUtils.setExternalStorageVolume(volumeName);
         super.setup();
     }
-
-    /**
-     * This is not an actual test, but rather just a one time setup method that creates the new
-     * public volume on which the test would run.
-     */
-    @Test
-    public void setupNewPublicVolume() throws Exception {
-        TestUtils.createNewPublicVolume();
-    }
 }
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTest.java
index b0bf57e..e1fed5d 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTest.java
@@ -23,7 +23,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
-import org.junit.Test;
 import org.junit.runner.RunWith;
 
 /**
@@ -39,13 +38,4 @@
         TestUtils.setExternalStorageVolume(volumeName);
         super.setup();
     }
-
-    /**
-     * This is not an actual test, but rather just a one time setup method that creates the new
-     * public volume on which the test would run.
-     */
-    @Test
-    public void setupNewPublicVolume() throws Exception {
-        TestUtils.createNewPublicVolume();
-    }
 }
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTestHelper.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTestHelper.java
new file mode 100644
index 0000000..ce5d2a2
--- /dev/null
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/PublicVolumeTestHelper.java
@@ -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.
+ */
+
+package android.scopedstorage.cts;
+
+import android.scopedstorage.cts.lib.TestUtils;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Creates public volume for running tests from {@link PublicVolumeTest} and
+ * {@link PublicVolumeLegacyTest}
+ */
+@RunWith(AndroidJUnit4.class)
+public class PublicVolumeTestHelper {
+    /**
+     * This is not an actual test, but rather just a one time setup method that creates the new
+     * public volume on which the test would run.
+     */
+    @Test
+    public void setupNewPublicVolume() throws Exception {
+        TestUtils.createNewPublicVolume();
+    }
+}
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index d3b109b..1842d1c 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -867,14 +867,14 @@
         try {
             assertThat(file.createNewFile()).isTrue();
 
-            // Since we can only place one F_WRLCK, the second open for readPfd will go
-            // throuh FUSE
+            // We upgrade 'w' only to 'rw'
             ParcelFileDescriptor writePfd = openWithMediaProvider(file, "w");
             ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw");
 
             assertRWR(readPfd, writePfd);
+            assertRWR(writePfd, readPfd); // Can read on 'w' only pfd
             assertLowerFsFd(writePfd);
-            assertUpperFsFd(readPfd); // Without cache
+            assertLowerFsFd(readPfd);
         } finally {
             file.delete();
         }
@@ -1030,6 +1030,27 @@
         assertThat(beforeObbStruct.st_dev).isEqualTo(afterObbStruct.st_dev);
     }
 
+    @Test
+    public void testCacheConsistencyForCaseInsensitivity() throws Exception {
+        File upperCaseFile = new File(getDownloadDir(), "CACHE_CONSISTENCY_FOR_CASE_INSENSITIVITY");
+        File lowerCaseFile = new File(getDownloadDir(), "cache_consistency_for_case_insensitivity");
+
+        try {
+            ParcelFileDescriptor upperCasePfd =
+                    ParcelFileDescriptor.open(upperCaseFile,
+                            ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE);
+            ParcelFileDescriptor lowerCasePfd =
+                    ParcelFileDescriptor.open(lowerCaseFile,
+                            ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE);
+
+            assertRWR(upperCasePfd, lowerCasePfd);
+            assertRWR(lowerCasePfd, upperCasePfd);
+        } finally {
+            upperCaseFile.delete();
+            lowerCaseFile.delete();
+        }
+    }
+
     private void createDeleteCreate(File create, File delete) throws Exception {
         try {
             assertThat(create.createNewFile()).isTrue();
@@ -1042,7 +1063,7 @@
             Thread.sleep(5);
         } finally {
             create.delete();
-            create.delete();
+            delete.delete();
         }
     }
 
@@ -1979,6 +2000,8 @@
 
         final File downloadDir = getDownloadDir();
         final File otherAppPdf = new File(downloadDir, "other-" + NONMEDIA_FILE_NAME);
+        final File shellPdfAtRoot = new File(getExternalStorageDir(),
+                "shell-" + NONMEDIA_FILE_NAME);
         final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
         final File myAppPdf = new File(downloadDir, "my-" + NONMEDIA_FILE_NAME);
         final File doesntExistPdf = new File(downloadDir, "nada-" + NONMEDIA_FILE_NAME);
@@ -1993,14 +2016,21 @@
             assertThat(myAppPdf.createNewFile()).isTrue();
             assertFileAccess_readWrite(myAppPdf);
 
-            // We can read the other app's image file because we hold R_E_S, but we can only
-            // check exists for the pdf file.
+            // We can read the other app's image file because we hold R_E_S, but we can
+            // check only exists for the pdf files.
             assertFileAccess_readOnly(otherAppImage);
             assertFileAccess_existsOnly(otherAppPdf);
             assertAccess(doesntExistPdf, false, false, false);
+
+            // We can check only exists for another app's files on root.
+            // Use shell to create root file because TEST_APP_A is in
+            // scoped storage.
+            executeShellCommand("touch " + shellPdfAtRoot.getAbsolutePath());
+            assertFileAccess_existsOnly(shellPdfAtRoot);
         } finally {
             deleteFileAsNoThrow(TEST_APP_A, otherAppPdf.getAbsolutePath());
             deleteFileAsNoThrow(TEST_APP_A, otherAppImage.getAbsolutePath());
+            executeShellCommand("rm " + shellPdfAtRoot.getAbsolutePath());
             myAppPdf.delete();
             uninstallApp(TEST_APP_A);
         }
@@ -2024,17 +2054,17 @@
             // We cannot read or write the file, but app A can.
             assertThat(canReadAndWriteAs(TEST_APP_A,
                     otherAppExternalDataFile.getAbsolutePath())).isTrue();
-            assertCannotAccessOtherAppFile(otherAppExternalDataFile);
+            assertCannotReadOrWrite(otherAppExternalDataFile);
 
             // We cannot read or write the dir, but app A can.
             assertThat(canReadAndWriteAs(TEST_APP_A,
                     otherAppExternalDataDir.getAbsolutePath())).isTrue();
-            assertCannotAccessOtherAppFile(otherAppExternalDataDir);
+            assertCannotReadOrWrite(otherAppExternalDataDir);
 
             // We cannot read or write the sub dir, but app A can.
             assertThat(canReadAndWriteAs(TEST_APP_A,
                     otherAppExternalDataSubDir.getAbsolutePath())).isTrue();
-            assertCannotAccessOtherAppFile(otherAppExternalDataSubDir);
+            assertCannotReadOrWrite(otherAppExternalDataSubDir);
 
             // We can read and write our own app dir, but app A cannot.
             assertThat(canReadAndWriteAs(TEST_APP_A,
@@ -2045,6 +2075,7 @@
             assertDirectoryAccess(getExternalStorageDir(), true);
             assertDirectoryAccess(new File(getExternalStorageDir(), "Android"), true);
             assertDirectoryAccess(new File(getExternalStorageDir(), "doesnt/exist"), false);
+            assertCannotReadOrWrite(new File("/storage/emulated"));
         } finally {
             uninstallApp(TEST_APP_A); // Uninstalling deletes external app dirs
         }
@@ -2747,7 +2778,7 @@
         assertAccess(file, exists, canRead, canWrite, true /* checkExists */);
     }
 
-    private static void assertCannotAccessOtherAppFile(File file)
+    private static void assertCannotReadOrWrite(File file)
             throws Exception {
         // App data directories have different 'x' bits on upgrading vs new devices. Let's not
         // check 'exists', by passing checkExists=false. But assert this app cannot read or write
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 6b7dd04..de90629 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -1258,10 +1258,11 @@
         assertDomainZeroOrOne("u:r:wpa:s0", "/system/bin/wpa_supplicant");
     }
 
-    /* permissioncontroller may or may not be running */
+    /* permissioncontroller, if running, always runs in permissioncontroller_app */
     @CddTest(requirement="9.7")
     public void testPermissionControllerDomain() throws DeviceNotAvailableException {
-        assertDomainZeroOrOne("u:r:permissioncontroller_app:s0", "com.google.android.permissioncontroller");
+        assertExecutableHasDomain("com.google.android.permissioncontroller", "u:r:permissioncontroller_app:s0");
+        assertExecutableHasDomain("com.android.permissioncontroller", "u:r:permissioncontroller_app:s0");
     }
 
     /* vzwomatrigger may or may not be running */
diff --git a/hostsidetests/statsd/apps/statsdapp/Android.bp b/hostsidetests/statsd/apps/statsdapp/Android.bp
index eabea94..a76c07e 100644
--- a/hostsidetests/statsd/apps/statsdapp/Android.bp
+++ b/hostsidetests/statsd/apps/statsdapp/Android.bp
@@ -45,6 +45,7 @@
         "androidx.legacy_legacy-support-v4",
         "androidx.test.rules",
         "cts-net-utils",
+        "BlobStoreTestUtils"
     ],
     jni_libs: ["liblmkhelper"],
     compile_multilib: "both",
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
index 72bea3d..9311656 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
@@ -27,6 +27,7 @@
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.app.blob.BlobStoreManager;
 import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.bluetooth.BluetoothAdapter;
@@ -61,6 +62,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.SystemClock;
@@ -75,6 +77,11 @@
 import androidx.annotation.NonNull;
 import androidx.test.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.utils.blob.DummyBlobData;
+
+import com.google.common.io.BaseEncoding;
+
 import org.junit.Test;
 
 import java.net.HttpURLConnection;
@@ -82,6 +89,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
@@ -677,7 +685,7 @@
         long startTime = System.currentTimeMillis();
         CountDownLatch latch = StatsdJobService.resetCountDownLatch();
         js.schedule(job);
-        waitForReceiver(context, 2_500, latch, null);
+        waitForReceiver(context, 5_000, latch, null);
     }
 
     @Test
@@ -938,6 +946,42 @@
         context.stopService(intent);
     }
 
+
+    // Constants for testBlobStore
+    private static final long BLOB_COMMIT_CALLBACK_TIMEOUT_SEC = 5;
+    private static final long BLOB_EXPIRY_DURATION_MS = 24 * 60 * 60 * 1000;
+    private static final long BLOB_FILE_SIZE_BYTES = 23 * 1024L;
+    private static final long BLOB_LEASE_EXPIRY_DURATION_MS = 60 * 60 * 1000;
+    private static final byte[] FAKE_PKG_CERT_SHA256 = BaseEncoding.base16().decode(
+            "187E3D3172F2177D6FEC2EA53785BF1E25DFF7B2E5F6E59807E365A7A837E6C3");
+
+    @Test
+    public void testBlobStore() throws Exception {
+        Context context = InstrumentationRegistry.getContext();
+        int uid = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).uid;
+
+        BlobStoreManager bsm = context.getSystemService(BlobStoreManager.class);
+        final long leaseExpiryMs = System.currentTimeMillis() + BLOB_LEASE_EXPIRY_DURATION_MS;
+
+        final DummyBlobData blobData = new DummyBlobData.Builder(context).setExpiryDurationMs(
+                BLOB_EXPIRY_DURATION_MS).setFileSize(BLOB_FILE_SIZE_BYTES).build();
+
+        blobData.prepare();
+        try {
+            // Commit the Blob, should result in BLOB_COMMITTED atom event
+            commitBlob(context, bsm, blobData);
+
+            // Lease the Blob, should result in BLOB_LEASED atom event
+            bsm.acquireLease(blobData.getBlobHandle(), "", leaseExpiryMs);
+
+            // Open the Blob, should result in BLOB_OPENED atom event
+            bsm.openBlob(blobData.getBlobHandle());
+
+        } finally {
+            blobData.delete();
+        }
+    }
+
     // ------- Helper methods
 
     /** Puts the current thread to sleep. */
@@ -994,4 +1038,19 @@
     private static void setScreenBrightness(int brightness) {
         runShellCommand("settings put system screen_brightness " + brightness);
     }
+
+
+    private void commitBlob(Context context, BlobStoreManager bsm, DummyBlobData blobData)
+            throws Exception {;
+        final long sessionId = bsm.createSession(blobData.getBlobHandle());
+        try (BlobStoreManager.Session session = bsm.openSession(sessionId)) {
+            blobData.writeToSession(session);
+            session.allowPackageAccess("fake.package.name", FAKE_PKG_CERT_SHA256);
+
+            final CompletableFuture<Integer> callback = new CompletableFuture<>();
+            session.commit(context.getMainExecutor(), callback::complete);
+            assertWithMessage("Session failed to commit within timeout").that(
+                    callback.get(BLOB_COMMIT_CALLBACK_TIMEOUT_SEC, TimeUnit.SECONDS)).isEqualTo(0);
+        }
+    }
 }
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java
index 329bdfa..d81040f 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java
@@ -28,6 +28,8 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.concurrent.GuardedBy;
+
 /**
  * Handles callback from the framework {@link android.app.job.JobScheduler}.
  * Runs a job for 0.5 seconds. Provides a countdown latch to wait on, by the test that schedules it.
@@ -38,6 +40,10 @@
 
   JobInfo mRunningJobInfo;
   JobParameters mRunningParams;
+
+  private static final Object sLock = new Object();
+
+  @GuardedBy("sLock")
   private static CountDownLatch sLatch;
 
   final Handler mHandler = new Handler();
@@ -47,24 +53,27 @@
         Thread.sleep(500);
       } catch (InterruptedException e) {
       }
+
       jobFinished(mRunningParams, false);
-      if (sLatch != null) {
-        sLatch.countDown();
+
+      synchronized (sLock) {
+        if (sLatch != null) {
+          sLatch.countDown();
+        }
       }
     }
   };
 
   public static synchronized CountDownLatch resetCountDownLatch() {
-    sLatch = new CountDownLatch(1);
+    synchronized (sLock) {
+      if (sLatch == null || sLatch.getCount() == 0) {
+        sLatch = new CountDownLatch(1);
+      }
+    }
     return sLatch;
   }
 
   @Override
-  public void onCreate() {
-    super.onCreate();
-  }
-
-  @Override
   public boolean onStartJob(JobParameters params) {
     mRunningParams = params;
     mHandler.post(mWorker);
@@ -75,4 +84,4 @@
   public boolean onStopJob(JobParameters params) {
     return false;
   }
-}
\ No newline at end of file
+}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java
index 12f110b..6968307 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java
@@ -58,7 +58,6 @@
         }
         synchronized (sLock) {
             Log.i(TAG, "onPerformSync");
-            sLock.notifyAll();
             if (sLatch != null) {
                 sLatch.countDown();
             } else {
@@ -79,8 +78,12 @@
         ContentResolver.requestSync(account, StatsdProvider.AUTHORITY, extras);
     }
 
-    public static synchronized CountDownLatch resetCountDownLatch() {
-        sLatch = new CountDownLatch(1);
+    public static CountDownLatch resetCountDownLatch() {
+        synchronized (sLock) {
+            if (sLatch == null || sLatch.getCount() == 0) {
+                sLatch = new CountDownLatch(1);
+            }
+        }
         return sLatch;
     }
 }
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
index ef216cc..51e24ea 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
@@ -205,22 +205,24 @@
 
     private String probe(String path) throws Exception {
         return getDevice().executeShellCommand("if [ -e " + path + " ] ; then"
-                + " cat " + path + " ; else echo 0 ; fi");
+                + " cat " + path + " ; else echo -1 ; fi");
     }
 
     /**
      * Determines whether perfetto enabled the kernel ftrace tracer.
      */
     protected boolean isSystemTracingEnabled() throws Exception {
-        final String debugFsPath = "/sys/kernel/debug/tracing/tracing_on";
         final String traceFsPath = "/sys/kernel/tracing/tracing_on";
-        String tracing_on = probe(debugFsPath);
+        String tracing_on = probe(traceFsPath);
         if (tracing_on.startsWith("0")) return false;
         if (tracing_on.startsWith("1")) return true;
-        // fallback to traceFs
-        LogUtil.CLog.d("Unexpected state for %s = %s. Falling back to traceFs", debugFsPath,
+
+        // fallback to debugfs
+        LogUtil.CLog.d("Unexpected state for %s = %s. Falling back to debugfs", traceFsPath,
                 tracing_on);
-        tracing_on = probe(traceFsPath);
+
+        final String debugFsPath = "/sys/kernel/debug/tracing/tracing_on";
+        tracing_on = probe(debugFsPath);
         if (tracing_on.startsWith("0")) return false;
         if (tracing_on.startsWith("1")) return true;
         throw new Exception(String.format("Unexpected state for %s = %s", traceFsPath, tracing_on));
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index a54f44e..6668d8f 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -16,6 +16,7 @@
 package android.cts.statsd.atom;
 
 import static com.android.os.AtomsProto.IntegrityCheckResultReported.Response.ALLOWED;
+
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
@@ -24,6 +25,7 @@
 import android.os.WakeLockLevelEnum;
 import android.server.ErrorSource;
 import android.telephony.NetworkTypeEnum;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.util.PropertyUtil;
 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
@@ -41,6 +43,9 @@
 import com.android.os.AtomsProto.BinderCalls;
 import com.android.os.AtomsProto.BleScanResultReceived;
 import com.android.os.AtomsProto.BleScanStateChanged;
+import com.android.os.AtomsProto.BlobCommitted;
+import com.android.os.AtomsProto.BlobLeased;
+import com.android.os.AtomsProto.BlobOpened;
 import com.android.os.AtomsProto.CameraStateChanged;
 import com.android.os.AtomsProto.DangerousPermissionState;
 import com.android.os.AtomsProto.DangerousPermissionStateSampled;
@@ -77,8 +82,10 @@
 import com.android.os.StatsLog.EventMetricData;
 import com.android.server.notification.SmallHash;
 import com.android.tradefed.log.LogUtil;
+
 import com.google.common.collect.Range;
 import com.google.protobuf.Descriptors;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -180,11 +187,12 @@
         createAndUploadConfig(atomTag, false);
         Thread.sleep(WAIT_TIME_SHORT);
 
-        runActivity("StatsdCtsForegroundActivity", "action", "action.sleep_top");
+        runActivity("StatsdCtsForegroundActivity", "action", "action.sleep_top", 3_500);
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = getEventMetricDataList();
 
+        assertThat(data).hasSize(1);
         AppStartOccurred atom = data.get(0).getAtom().getAppStartOccurred();
         assertThat(atom.getPkgName()).isEqualTo(TEST_PACKAGE_NAME);
         assertThat(atom.getActivityName())
@@ -676,7 +684,7 @@
                 assertThat(state.getLocationReports()).isGreaterThan((long) 0);
                 assertThat(state.getLocationFailureReports()).isAtLeast((long) 0);
                 assertThat(state.getTimeToFirstFixReports()).isGreaterThan((long) 0);
-                assertThat(state.getTimeToFirstFixMilliS()).isGreaterThan((long) 0);
+                assertThat(state.getTimeToFirstFixMillis()).isGreaterThan((long) 0);
                 assertThat(state.getPositionAccuracyReports()).isGreaterThan((long) 0);
                 assertThat(state.getPositionAccuracyMeters()).isGreaterThan((long) 0);
                 assertThat(state.getTopFourAverageCn0Reports()).isGreaterThan((long) 0);
@@ -891,8 +899,9 @@
         List<EventMetricData> data = getEventMetricDataList();
 
         // Assert that the events happened in the expected order.
-        assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT,
-                atom -> atom.getSyncStateChanged().getState().getNumber());
+        assertStatesOccurred(stateSet, data,
+            /* wait = */ 0 /* don't verify time differences between state changes */,
+            atom -> atom.getSyncStateChanged().getState().getNumber());
     }
 
     public void testVibratorState() throws Exception {
@@ -1308,8 +1317,8 @@
         // Start test app and trigger a pull while it is running.
         try (AutoCloseable a = withActivity("StatsdCtsForegroundActivity", "action",
                 "action.show_notification")) {
-            setAppBreadcrumbPredicate();
             Thread.sleep(WAIT_TIME_LONG);
+            setAppBreadcrumbPredicate();
         }
 
         // Assert about ProcessMemorySnapshot for the test app, statsd and system server.
@@ -1999,12 +2008,9 @@
         doTestMobileBytesTransferThat(Atom.MOBILE_BYTES_TRANSFER_BY_FG_BG_FIELD_NUMBER, (atom) -> {
             final AtomsProto.MobileBytesTransferByFgBg data =
                     ((Atom) atom).getMobileBytesTransferByFgBg();
-            if (data.getUid() == appUid) {
+            if (data.getUid() == appUid && data.getIsForeground()) {
                 assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
                         data.getRxPackets(), data.getTxPackets());
-                // IsForeground cannot be judged since foreground activity that launched
-                // while screen off (PROCESS_STATE_TOP_SLEEPING) will be treated as background
-                // in NetworkPolicyManagerService.
                 return true; // found
             }
             return false;
@@ -2017,25 +2023,27 @@
         doTestMobileBytesTransferThat(Atom.DATA_USAGE_BYTES_TRANSFER_FIELD_NUMBER, (atom) -> {
             final AtomsProto.DataUsageBytesTransfer data =
                     ((Atom) atom).getDataUsageBytesTransfer();
-            assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
-                    data.getRxPackets(), data.getTxPackets());
-            // TODO: verify the RAT type field with the value gotten from device.
-            if (subtypeCombined) {
-                assertThat(data.getRatType()).isEqualTo(NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
-            } else {
-                assertThat(data.getRatType()).isGreaterThan(
-                        NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
+            if (data.getState() == 1 /*NetworkStats.SET_FOREGROUND*/) {
+                assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
+                        data.getRxPackets(), data.getTxPackets());
+                // TODO: verify the RAT type field with the value gotten from device.
+                if (subtypeCombined) {
+                    assertThat(data.getRatType()).isEqualTo(
+                            NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
+                } else {
+                    assertThat(data.getRatType()).isGreaterThan(
+                            NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
+                }
+
+                // Assert that subscription info is valid.
+                assertThat(data.getSimMcc()).matches("^\\d{3}$");
+                assertThat(data.getSimMnc()).matches("^\\d{2,3}$");
+                assertThat(data.getCarrierId()).isNotEqualTo(
+                        -1); // TelephonyManager#UNKNOWN_CARRIER_ID
+
+                return true; // found
             }
-            // Foreground state cannot be judged since foreground activity that launched
-            // while screen off (PROCESS_STATE_TOP_SLEEPING) will be treated as background
-            // in NetworkPolicyManagerService.
-
-            // Assert that subscription info is valid.
-            assertThat(data.getSimMcc()).matches("^\\d{3}$");
-            assertThat(data.getSimMnc()).matches("^\\d{2,3}$");
-            assertThat(data.getCarrierId()).isNotEqualTo(-1); // TelephonyManager#UNKNOWN_CARRIER_ID
-
-            return true;
+            return false;
         });
     }
 
@@ -2071,6 +2079,107 @@
         assertThat(atom.getState()).isEqualTo(AppBreadcrumbReported.State.START);
     }
 
+    public void testPushedBlobStoreStats() throws Exception {
+        StatsdConfig.Builder conf = createConfigBuilder();
+        addAtomEvent(conf, Atom.BLOB_COMMITTED_FIELD_NUMBER, false);
+        addAtomEvent(conf, Atom.BLOB_LEASED_FIELD_NUMBER, false);
+        addAtomEvent(conf, Atom.BLOB_OPENED_FIELD_NUMBER, false);
+        uploadConfig(conf);
+
+        Thread.sleep(WAIT_TIME_SHORT);
+
+        runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testBlobStore");
+
+        List<EventMetricData> data = getEventMetricDataList();
+        assertThat(data).hasSize(3);
+
+        BlobCommitted blobCommitted = data.get(0).getAtom().getBlobCommitted();
+        final long blobId = blobCommitted.getBlobId();
+        final long blobSize = blobCommitted.getSize();
+        assertThat(blobCommitted.getUid()).isEqualTo(getUid());
+        assertThat(blobId).isNotEqualTo(0);
+        assertThat(blobSize).isNotEqualTo(0);
+        assertThat(blobCommitted.getResult()).isEqualTo(BlobCommitted.Result.SUCCESS);
+
+        BlobLeased blobLeased = data.get(1).getAtom().getBlobLeased();
+        assertThat(blobLeased.getUid()).isEqualTo(getUid());
+        assertThat(blobLeased.getBlobId()).isEqualTo(blobId);
+        assertThat(blobLeased.getSize()).isEqualTo(blobSize);
+        assertThat(blobLeased.getResult()).isEqualTo(BlobLeased.Result.SUCCESS);
+
+        BlobOpened blobOpened = data.get(2).getAtom().getBlobOpened();
+        assertThat(blobOpened.getUid()).isEqualTo(getUid());
+        assertThat(blobOpened.getBlobId()).isEqualTo(blobId);
+        assertThat(blobOpened.getSize()).isEqualTo(blobSize);
+        assertThat(blobOpened.getResult()).isEqualTo(BlobOpened.Result.SUCCESS);
+    }
+
+    // Constants that match the constants for AtomTests#testBlobStore
+    private static final long BLOB_COMMIT_CALLBACK_TIMEOUT_SEC = 5;
+    private static final long BLOB_EXPIRY_DURATION_MS = 24 * 60 * 60 * 1000;
+    private static final long BLOB_FILE_SIZE_BYTES = 23 * 1024L;
+    private static final long BLOB_LEASE_EXPIRY_DURATION_MS = 60 * 60 * 1000;
+
+    public void testPulledBlobStoreStats() throws Exception {
+        StatsdConfig.Builder config = createConfigBuilder();
+        addGaugeAtomWithDimensions(config,
+                Atom.BLOB_INFO_FIELD_NUMBER,
+                null);
+        uploadConfig(config);
+
+        final long testStartTimeMs = System.currentTimeMillis();
+        Thread.sleep(WAIT_TIME_SHORT);
+        runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testBlobStore");
+        Thread.sleep(WAIT_TIME_LONG);
+        setAppBreadcrumbPredicate();
+        Thread.sleep(WAIT_TIME_SHORT);
+
+        // Add commit callback time to test end time to account for async execution
+        final long testEndTimeMs =
+                System.currentTimeMillis() + BLOB_COMMIT_CALLBACK_TIMEOUT_SEC * 1000;
+
+        // Find the BlobInfo for the blob created in the test run
+        AtomsProto.BlobInfo blobInfo = null;
+        for (Atom atom : getGaugeMetricDataList()) {
+            if (atom.hasBlobInfo()) {
+                final AtomsProto.BlobInfo temp = atom.getBlobInfo();
+                if (temp.getCommitters().getCommitter(0).getUid() == getUid()) {
+                    blobInfo = temp;
+                    break;
+                }
+            }
+        }
+        assertThat(blobInfo).isNotNull();
+
+        assertThat(blobInfo.getSize()).isEqualTo(BLOB_FILE_SIZE_BYTES);
+
+        // Check that expiry time is reasonable
+        assertThat(blobInfo.getExpiryTimestampMillis()).isGreaterThan(
+                testStartTimeMs + BLOB_EXPIRY_DURATION_MS);
+        assertThat(blobInfo.getExpiryTimestampMillis()).isLessThan(
+                testEndTimeMs + BLOB_EXPIRY_DURATION_MS);
+
+        // Check that commit time is reasonable
+        final long commitTimeMs = blobInfo.getCommitters().getCommitter(
+                0).getCommitTimestampMillis();
+        assertThat(commitTimeMs).isGreaterThan(testStartTimeMs);
+        assertThat(commitTimeMs).isLessThan(testEndTimeMs);
+
+        // Check that WHITELIST and PRIVATE access mode flags are set
+        assertThat(blobInfo.getCommitters().getCommitter(0).getAccessMode()).isEqualTo(0b1001);
+        assertThat(blobInfo.getCommitters().getCommitter(0).getNumWhitelistedPackage()).isEqualTo(
+                1);
+
+        assertThat(blobInfo.getLeasees().getLeaseeCount()).isGreaterThan(0);
+        assertThat(blobInfo.getLeasees().getLeasee(0).getUid()).isEqualTo(getUid());
+
+        // Check that lease expiry time is reasonable
+        final long leaseExpiryMs = blobInfo.getLeasees().getLeasee(
+                0).getLeaseExpiryTimestampMillis();
+        assertThat(leaseExpiryMs).isGreaterThan(testStartTimeMs + BLOB_LEASE_EXPIRY_DURATION_MS);
+        assertThat(leaseExpiryMs).isLessThan(testEndTimeMs + BLOB_LEASE_EXPIRY_DURATION_MS);
+    }
+
     private void assertDataUsageAtomDataExpected(long rxb, long txb, long rxp, long txp) {
         assertThat(rxb).isGreaterThan(0L);
         assertThat(txb).isGreaterThan(0L);
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 572f9e7..a966d2b 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -1465,7 +1465,7 @@
 
     public void testCanBubble_ranking() throws Exception {
         if ((mActivityManager.isLowRamDevice() && !FeatureUtil.isWatch())
-                || FeatureUtil.isAutomotive()) {
+                || FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
             return;
         }
 
@@ -2876,8 +2876,8 @@
 
     public void testNotificationManagerBubblePolicy_flag_intentBubble()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -2896,8 +2896,8 @@
 
     public void testNotificationManagerBubblePolicy_noFlag_service()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
@@ -2922,8 +2922,8 @@
 
     public void testNotificationManagerBubblePolicy_noFlag_phonecall()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
@@ -2948,8 +2948,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_noFlag_foreground() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -2975,8 +2975,8 @@
 
     public void testNotificationManagerBubble_checkActivityFlagsDocumentLaunchMode()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3016,8 +3016,8 @@
 
     public void testNotificationManagerBubblePolicy_flag_shortcutBubble()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3041,8 +3041,8 @@
 
     public void testNotificationManagerBubblePolicy_noFlag_invalidShortcut()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3066,8 +3066,8 @@
 
     public void testNotificationManagerBubblePolicy_noFlag_invalidNotif()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3089,8 +3089,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_appAll_globalOn() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3112,8 +3112,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_appAll_globalOff() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3134,8 +3134,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_appAll_channelNo() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3156,8 +3156,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_appSelected_channelNo() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3178,8 +3178,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_appSelected_channelYes() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3201,8 +3201,8 @@
     }
 
     public void testNotificationManagerBubblePolicy_appNone_channelNo() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
@@ -3224,8 +3224,8 @@
 
     public void testNotificationManagerBubblePolicy_noFlag_shortcutRemoved()
             throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
 
@@ -3251,8 +3251,8 @@
     }
 
     public void testNotificationManagerBubbleNotificationSuppression() throws Exception {
-        if (FeatureUtil.isAutomotive()) {
-            // Automotive does not support notification bubbles.
+        if (FeatureUtil.isAutomotive() || FeatureUtil.isTV()) {
+            // These do not support bubbles.
             return;
         }
         try {
diff --git a/tests/backup/AndroidTest.xml b/tests/backup/AndroidTest.xml
index 1f99fdb..ec0ade5 100644
--- a/tests/backup/AndroidTest.xml
+++ b/tests/backup/AndroidTest.xml
@@ -27,6 +27,7 @@
        -remove SwitchUserTargetPreparer
     -->
     <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
     <target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
         <option name="user-type" value="system" />
     </target_preparer>
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
index f58152e..850870a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
@@ -160,17 +160,13 @@
                 + " in landscape and reverse-landscape", sameSize);
     }
 
-    private ActivityLifecycleCounts getLifecycleCountsForRotation(ComponentName activityName,
-            RotationSession session, int before, int after, boolean canHandleConfigChange)  {
-        final int currentRotation = mWmState.getRotation();
-        // The test verifies the events from "before" rotation to "after" rotation. So when
-        // preparing "before" rotation, the changes should be consumed to avoid being mixed into
-        // the result to verify.
-        final boolean is90DegreeDelta = Math.abs(currentRotation - before) % 2 != 0;
+    private void prepareRotation(ComponentName activityName, RotationSession session,
+            int currentRotation, int initialRotation, boolean canHandleConfigChange) {
+        final boolean is90DegreeDelta = Math.abs(currentRotation - initialRotation) % 2 != 0;
         if (is90DegreeDelta) {
             separateTestJournal();
         }
-        session.set(before);
+        session.set(initialRotation);
         if (is90DegreeDelta) {
             // Consume the changes of "before" rotation to make sure the activity is in a stable
             // state to apply "after" rotation.
@@ -181,6 +177,15 @@
                     .countWithRetry("activity rotated with 90 degree delta",
                             countSpec(expectedCallback, CountSpec.GREATER_THAN, 0)));
         }
+    }
+
+    private ActivityLifecycleCounts getLifecycleCountsForRotation(ComponentName activityName,
+            RotationSession session, int before, int after, boolean canHandleConfigChange)  {
+        final int currentRotation = mWmState.getRotation();
+        // The test verifies the events from "before" rotation to "after" rotation. So when
+        // preparing "before" rotation, the changes should be consumed to avoid being mixed into
+        // the result to verify.
+        prepareRotation(activityName, session, currentRotation, before, canHandleConfigChange);
         separateTestJournal();
         session.set(after);
         mWmState.computeState(activityName);
@@ -202,13 +207,12 @@
     private void testRotation(ComponentName activityName, int rotationStep, int numRelaunch,
             int numConfigChange) {
         launchActivity(activityName);
-
         mWmState.computeState(activityName);
 
         final int initialRotation = 4 - rotationStep;
         final RotationSession rotationSession = createManagedRotationSession();
-        rotationSession.set(initialRotation);
-        mWmState.computeState(activityName);
+        prepareRotation(activityName, rotationSession, mWmState.getRotation(), initialRotation,
+                numConfigChange > 0);
         final int actualStackId =
                 mWmState.getTaskByActivity(activityName).mRootTaskId;
         final int displayId = mWmState.getRootTask(actualStackId).mDisplayId;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java
index 7075f4c..a876088 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java
@@ -208,6 +208,7 @@
 
         // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
         // will come up.
+        launchActivity(LAUNCHING_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         launchActivity(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
 
         // Move activity back to fullscreen stack.
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
index ae9a40c..bdb28b2 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
@@ -135,7 +135,10 @@
         sendAndAssertTargetConsumedKey(primaryActivity, KEYCODE_1, DEFAULT_DISPLAY);
 
         assumeTrue(supportsMultiDisplay());
-        final InvisibleVirtualDisplaySession session = createManagedInvisibleDisplaySession();
+
+        // VirtualDisplay can't maintain perDisplayFocus because it is not trusted,
+        // so uses SimulatedDisplay instead.
+        final SimulatedDisplaySession session = createManagedSimulatedDisplaySession();
         final int secondaryDisplayId = session.getDisplayId();
         final SecondaryActivity secondaryActivity = session.startActivityAndFocus();
         sendAndAssertTargetConsumedKey(secondaryActivity, KEYCODE_2, INVALID_DISPLAY);
@@ -497,13 +500,7 @@
         }
 
         SecondaryActivity startActivityAndFocus() {
-            final int displayId = getDisplayId();
-            // An untrusted virtual display won't have focus until the display is touched.
-            final SecondaryActivity activity = WindowManagerTestBase.startActivity(
-                    SecondaryActivity.class, displayId, false /* hasFocus */);
-            tapOnCenterOfDisplay(displayId);
-            activity.waitAndAssertWindowFocusState(true);
-            return activity;
+            return WindowFocusTests.startActivityAndFocus(getDisplayId(), false /* hasFocus */);
         }
 
         @Override
@@ -516,4 +513,40 @@
             }
         }
     }
+
+    private SimulatedDisplaySession createManagedSimulatedDisplaySession() {
+        return mObjectTracker.manage(new SimulatedDisplaySession());
+    }
+
+    private class SimulatedDisplaySession implements AutoCloseable {
+        private final VirtualDisplaySession mVirtualDisplaySession;
+        private final WindowManagerState.DisplayContent mVirtualDisplay;
+
+        SimulatedDisplaySession() {
+            mVirtualDisplaySession = new VirtualDisplaySession();
+            mVirtualDisplay = mVirtualDisplaySession.setSimulateDisplay(true).createDisplay();
+        }
+
+        int getDisplayId() {
+            return mVirtualDisplay.mId;
+        }
+
+        SecondaryActivity startActivityAndFocus() {
+            return WindowFocusTests.startActivityAndFocus(getDisplayId(), true /* hasFocus */);
+        }
+
+        @Override
+        public void close() {
+            mVirtualDisplaySession.close();
+        }
+    }
+
+    private static SecondaryActivity startActivityAndFocus(int displayId, boolean hasFocus) {
+        // An untrusted virtual display won't have focus until the display is touched.
+        final SecondaryActivity activity = WindowManagerTestBase.startActivity(
+                SecondaryActivity.class, displayId, hasFocus);
+        tapOnCenterOfDisplay(displayId);
+        activity.waitAndAssertWindowFocusState(true);
+        return activity;
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index 24636e3..04e96ad 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -19,6 +19,7 @@
 import static android.server.wm.WindowInsetsAnimationControllerTests.ControlListener.Event.CANCELLED;
 import static android.server.wm.WindowInsetsAnimationControllerTests.ControlListener.Event.FINISHED;
 import static android.server.wm.WindowInsetsAnimationControllerTests.ControlListener.Event.READY;
+import static android.server.wm.WindowInsetsAnimationTestBase.showImeWithHardKeyboardSetting;
 import static android.server.wm.WindowInsetsAnimationUtils.INSETS_EVALUATOR;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
@@ -26,8 +27,6 @@
 
 import static androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread;
 
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasItem;
 import static org.hamcrest.Matchers.hasSize;
@@ -124,6 +123,7 @@
         mActivity = startActivity(TestActivity.class);
         mRootView = mActivity.getWindow().getDecorView();
         mListener = new ControlListener(mErrorCollector);
+        showImeWithHardKeyboardSetting(mObjectTracker);
         assumeTestCompatibility();
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
index 6fe77e4..da69b92 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
@@ -34,11 +34,13 @@
 import static org.mockito.Mockito.spy;
 
 import android.os.Bundle;
+import android.provider.Settings;
+import android.server.wm.WindowInsetsAnimationTestBase.AnimCallback.AnimationStep;
+import android.server.wm.settings.SettingsSession;
 import android.util.ArraySet;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowInsetsAnimation;
-import android.server.wm.WindowInsetsAnimationTestBase.AnimCallback.AnimationStep;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -154,6 +156,23 @@
         }
     }
 
+    /**
+     * Workaround for b/158637229: force the keyboard to show even when there is a hardware keyboard
+     * during IME related insets tests to avoid issues when testing on devices that have a hardware
+     * keyboard.
+     *
+     * @param tracker the test's {@link ObjectTracker}, used to clean up the setting override after
+     *                the test finishes.
+     */
+    static void showImeWithHardKeyboardSetting(ObjectTracker tracker) {
+        final SettingsSession<Integer> showImeWithHardKeyboardSetting = new SettingsSession<>(
+                Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD),
+                Settings.Secure::getInt,
+                Settings.Secure::putInt);
+        tracker.manage(showImeWithHardKeyboardSetting);
+        showImeWithHardKeyboardSetting.set(1);
+    }
+
     public static class AnimCallback extends WindowInsetsAnimation.Callback {
 
         public static class AnimationStep {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 0f29d97..6dc0c7b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -17,6 +17,7 @@
 package android.server.wm;
 
 import static android.graphics.PixelFormat.TRANSLUCENT;
+import static android.server.wm.WindowInsetsAnimationTestBase.showImeWithHardKeyboardSetting;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE;
@@ -40,6 +41,8 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
@@ -78,6 +81,9 @@
     private final static long TIME_SLICE = 50; // milliseconds
     private final static AnimationCallback ANIMATION_CALLBACK = new AnimationCallback();
 
+    private static final String AM_BROADCAST_CLOSE_SYSTEM_DIALOGS =
+            "am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS";
+
     @Rule
     public final ErrorCollector mErrorCollector = new ErrorCollector();
 
@@ -175,6 +181,8 @@
 
     @Test
     public void testImeShowAndHide() {
+        showImeWithHardKeyboardSetting(mObjectTracker);
+
         final TestActivity activity = startActivity(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
         getInstrumentation().runOnMainSync(() -> {
@@ -394,6 +402,12 @@
         // Swiping from top of display can show bars.
         dragFromTopToCenter(rootView);
         PollingCheck.waitFor(TIMEOUT, () -> rootView.getRootWindowInsets().isVisible(types));
+
+        // The swipe action brings down the notification shade which causes subsequent tests to
+        // fail.
+        if (isAutomotive(mContext)) {
+            broadcastCloseSystemDialogs();
+        }
     }
 
     @Test
@@ -448,6 +462,8 @@
 
     @Test
     public void testShowImeOnCreate() throws Exception {
+        showImeWithHardKeyboardSetting(mObjectTracker);
+
         final TestShowOnCreateActivity activity = startActivity(TestShowOnCreateActivity.class);
         final View rootView = activity.getWindow().getDecorView();
         ANIMATION_CALLBACK.waitForFinishing(TIMEOUT);
@@ -509,6 +525,14 @@
 
     }
 
+    private static void broadcastCloseSystemDialogs() {
+        executeShellCommand(AM_BROADCAST_CLOSE_SYSTEM_DIALOGS);
+    }
+
+    private static boolean isAutomotive(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
     private static void hideInsets(View view, int types) throws InterruptedException {
         ANIMATION_CALLBACK.reset();
         getInstrumentation().runOnMainSync(() -> {
diff --git a/tests/tests/appenumeration/AndroidTest.xml b/tests/tests/appenumeration/AndroidTest.xml
index bc8d224..2932d51 100644
--- a/tests/tests/appenumeration/AndroidTest.xml
+++ b/tests/tests/appenumeration/AndroidTest.xml
@@ -48,6 +48,7 @@
         <option name="test-file-name" value="CtsAppEnumerationQueriesPackage.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesNothingTargetsQ.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesNothingHasPermission.apk" />
+        <option name="test-file-name" value="CtsAppEnumerationQueriesNothingHasProvider.apk" />
         <option name="test-file-name" value="CtsAppEnumerationWildcardBrowsableActivitySource.apk" />
         <option name="test-file-name" value="CtsAppEnumerationWildcardContactsActivitySource.apk" />
         <option name="test-file-name" value="CtsAppEnumerationWildcardDocumentEditorActivitySource.apk" />
diff --git a/tests/tests/appenumeration/app/source/Android.bp b/tests/tests/appenumeration/app/source/Android.bp
index 8c95b27..cfa3871 100644
--- a/tests/tests/appenumeration/app/source/Android.bp
+++ b/tests/tests/appenumeration/app/source/Android.bp
@@ -164,6 +164,18 @@
 }
 
 android_test_helper_app {
+    name: "CtsAppEnumerationQueriesNothingHasProvider",
+    manifest: "AndroidManifest-queriesNothing-hasProvider.xml",
+    defaults: ["CtsAppEnumerationQueriesDefaults"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+}
+
+android_test_helper_app {
     name: "CtsAppEnumerationSharedUidSource",
     manifest: "AndroidManifest-queriesNothing-sharedUser.xml",
     defaults: ["CtsAppEnumerationQueriesDefaults"],
diff --git a/tests/tests/appenumeration/app/source/AndroidManifest-queriesNothing-hasProvider.xml b/tests/tests/appenumeration/app/source/AndroidManifest-queriesNothing-hasProvider.xml
new file mode 100644
index 0000000..1e94c1b
--- /dev/null
+++ b/tests/tests/appenumeration/app/source/AndroidManifest-queriesNothing-hasProvider.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.appenumeration.queries.nothing.hasprovider">
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.appenumeration.cts.query.TestActivity"
+                  android:exported="true" />
+        <provider android:name="android.appenumeration.cts.query.TestProvider"
+                  android:authorities="android.appenumeration.queries.nothing.hasprovider"
+                  android:exported="true" >
+
+        </provider>
+    </application>
+</manifest>
diff --git a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
index 3e9d789..a4ae8b2 100644
--- a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
+++ b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
@@ -43,25 +43,41 @@
 import android.content.IntentSender;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.PatternMatcher;
 import android.os.RemoteCallback;
 import android.util.SparseArray;
 
+import java.util.ArrayList;
+
 public class TestActivity extends Activity {
 
     SparseArray<RemoteCallback> callbacks = new SparseArray<>();
 
     private Handler mainHandler;
+    private Handler backgroundHandler;
+    private HandlerThread backgroundThread;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         mainHandler = new Handler(getMainLooper());
+        backgroundThread = new HandlerThread("testBackground");
+        backgroundThread.start();
+        backgroundHandler = new Handler(backgroundThread.getLooper());
         super.onCreate(savedInstanceState);
         handleIntent(getIntent());
     }
 
+    @Override
+    protected void onDestroy() {
+        backgroundThread.quitSafely();
+        super.onDestroy();
+    }
+
     private void handleIntent(Intent intent) {
         RemoteCallback remoteCallback = intent.getParcelableExtra(EXTRA_REMOTE_CALLBACK);
         try {
@@ -123,6 +139,9 @@
                 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
                 awaitPackageBroadcast(
                         remoteCallback, packageName, Intent.ACTION_PACKAGE_ADDED, 3000);
+            } else if (Constants.ACTION_QUERY_RESOLVER.equals(action)) {
+                final String authority = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+                queryResolverForVisiblePackages(remoteCallback, authority);
             } else {
                 sendError(remoteCallback, new Exception("unknown action " + action));
             }
@@ -199,6 +218,33 @@
         finish();
     }
 
+    private void queryResolverForVisiblePackages(RemoteCallback remoteCallback, String authority) {
+        backgroundHandler.post(() -> {
+            Uri queryUri = Uri.parse("content://" + authority + "/test");
+            Cursor query = getContentResolver().query(queryUri, null, null, null, null);
+            if (query == null || !query.moveToFirst()) {
+                sendError(remoteCallback,
+                        new IllegalStateException(
+                                "Query of " + queryUri + " could not be completed"));
+                return;
+            }
+            ArrayList<String> visiblePackages = new ArrayList<>();
+            while (!query.isAfterLast()) {
+                visiblePackages.add(query.getString(0));
+                query.moveToNext();
+            }
+            query.close();
+
+            mainHandler.post(() -> {
+                Bundle result = new Bundle();
+                result.putStringArray(EXTRA_RETURN_RESULT, visiblePackages.toArray(new String[]{}));
+                remoteCallback.sendResult(result);
+                finish();
+            });
+
+        });
+    }
+
     private void sendError(RemoteCallback remoteCallback, Exception failure) {
         Bundle result = new Bundle();
         result.putSerializable(EXTRA_ERROR, failure);
diff --git a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestProvider.java b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestProvider.java
new file mode 100644
index 0000000..b5bc7f0
--- /dev/null
+++ b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestProvider.java
@@ -0,0 +1,62 @@
+/*
+ * 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.appenumeration.cts.query;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+
+import java.util.Collections;
+
+public class TestProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        MatrixCursor matrixCursor = new MatrixCursor(new String[]{"seenPackage"}, 0);
+        getContext().getPackageManager().getInstalledPackages(0 /*flags*/).forEach(packageInfo -> {
+            matrixCursor.addRow(Collections.singletonList(packageInfo.packageName));
+        });
+        return matrixCursor;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
index c24744f..460ce09 100644
--- a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
+++ b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
@@ -43,6 +43,8 @@
     public static final String QUERIES_ACTIVITY_ACTION = PKG_BASE + "queries.activity.action";
     /** A package that has no queries but gets the QUERY_ALL_PACKAGES permission */
     public static final String QUERIES_NOTHING_PERM = PKG_BASE + "queries.nothing.haspermission";
+    /** A package that has no queries but has a provider that can be queried */
+    public static final String QUERIES_NOTHING_PROVIDER = PKG_BASE + "queries.nothing.hasprovider";
     /** A package that has no queries tag or permissions but targets Q */
     public static final String QUERIES_NOTHING_Q = PKG_BASE + "queries.nothing.q";
     /** A package that has no queries tag or permission to query any specific packages */
@@ -127,9 +129,12 @@
             PKG_BASE + "cts.action.GET_INSTALLED_PACKAGES";
     public static final String ACTION_START_SENDER_FOR_RESULT =
             PKG_BASE + "cts.action.START_SENDER_FOR_RESULT";
+    public static final String ACTION_QUERY_RESOLVER =
+            PKG_BASE + "cts.action.QUERY_RESOLVER_FOR_VISIBILITY";
 
     public static final String EXTRA_REMOTE_CALLBACK = "remoteCallback";
     public static final String EXTRA_ERROR = "error";
     public static final String EXTRA_FLAGS = "flags";
     public static final String EXTRA_DATA = "data";
+    public static final String EXTRA_AUTHORITY = "authority";
 }
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index fe9b79d..cbea10a 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -23,11 +23,13 @@
 import static android.appenumeration.cts.Constants.ACTION_MANIFEST_SERVICE;
 import static android.appenumeration.cts.Constants.ACTION_QUERY_ACTIVITIES;
 import static android.appenumeration.cts.Constants.ACTION_QUERY_PROVIDERS;
+import static android.appenumeration.cts.Constants.ACTION_QUERY_RESOLVER;
 import static android.appenumeration.cts.Constants.ACTION_QUERY_SERVICES;
 import static android.appenumeration.cts.Constants.ACTION_START_DIRECTLY;
 import static android.appenumeration.cts.Constants.ACTION_START_FOR_RESULT;
 import static android.appenumeration.cts.Constants.ACTIVITY_CLASS_DUMMY_ACTIVITY;
 import static android.appenumeration.cts.Constants.ACTIVITY_CLASS_TEST;
+import static android.appenumeration.cts.Constants.EXTRA_AUTHORITY;
 import static android.appenumeration.cts.Constants.EXTRA_DATA;
 import static android.appenumeration.cts.Constants.EXTRA_ERROR;
 import static android.appenumeration.cts.Constants.EXTRA_FLAGS;
@@ -35,6 +37,7 @@
 import static android.appenumeration.cts.Constants.QUERIES_ACTIVITY_ACTION;
 import static android.appenumeration.cts.Constants.QUERIES_NOTHING;
 import static android.appenumeration.cts.Constants.QUERIES_NOTHING_PERM;
+import static android.appenumeration.cts.Constants.QUERIES_NOTHING_PROVIDER;
 import static android.appenumeration.cts.Constants.QUERIES_NOTHING_Q;
 import static android.appenumeration.cts.Constants.QUERIES_NOTHING_SHARED_USER;
 import static android.appenumeration.cts.Constants.QUERIES_PACKAGE;
@@ -65,6 +68,7 @@
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 
 import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
@@ -100,6 +104,7 @@
 import org.junit.rules.TestName;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
 import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
@@ -430,6 +435,22 @@
         }
     }
 
+    @Test
+    public void queriesResolver_grantsVisibilityToProvider() throws Exception {
+        assertNotVisible(QUERIES_NOTHING_PROVIDER, QUERIES_NOTHING_PERM);
+
+        String[] result = sendCommandBlocking(
+                QUERIES_NOTHING_PERM, QUERIES_NOTHING_PROVIDER, null, ACTION_QUERY_RESOLVER)
+                .getStringArray(Intent.EXTRA_RETURN_RESULT);
+        Arrays.sort(result);
+        assertThat(QUERIES_NOTHING_PERM + " not visible to " + QUERIES_NOTHING_PROVIDER
+                        + " during resolver interaction",
+                Arrays.binarySearch(result, QUERIES_NOTHING_PERM),
+                greaterThanOrEqualTo(0));
+
+        assertVisible(QUERIES_NOTHING_PROVIDER, QUERIES_NOTHING_PERM);
+    }
+
     private void assertNotVisible(String sourcePackageName, String targetPackageName)
             throws Exception {
         if (!sGlobalFeatureEnabled) return;
diff --git a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
index 5ad060a..dee467e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
+++ b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
@@ -48,7 +48,7 @@
     }
 
     private static String TAG = "FrameRateCtsActivity";
-    private static final long FRAME_RATE_SWITCH_GRACE_PERIOD_SECONDS = 1;
+    private static final long FRAME_RATE_SWITCH_GRACE_PERIOD_SECONDS = 2;
     private static final long STABLE_FRAME_RATE_WAIT_SECONDS = 1;
     private static final long POST_BUFFER_INTERVAL_MILLIS = 500;
     private static final int PRECONDITION_WAIT_MAX_ATTEMPTS = 5;
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 0946147..2eef41d 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -283,6 +283,12 @@
             mLockCredential.gotoKeyguard();
             mLockCredential.enterAndConfirmLockCredential();
             launchHomeActivity();
+            KeyguardManager keyguardManager = (KeyguardManager)getContext().getSystemService(
+                    Context.KEYGUARD_SERVICE);
+            for (int i = 0; i < 25 && keyguardManager.isDeviceLocked(); i++) {
+                SystemClock.sleep(200);
+            }
+            assertFalse(keyguardManager.isDeviceLocked());
         }
 
         @Override
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 46592ca..55ba086 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -1105,17 +1105,16 @@
                 assertTrue(
                         signedCertIssuer.toASN1Object().equals(signingCertSubject.toASN1Object()));
 
+                X500Name signedCertSubject =
+                        new JcaX509CertificateHolder(x509PrevCert).getSubject();
                 if (i == 1) {
                     // First cert should have subject "CN=Android Keystore Key".
-                    X500Name signedCertSubject =
-                            new JcaX509CertificateHolder(x509PrevCert).getSubject();
                     assertEquals(signedCertSubject, new X500Name("CN=Android Keystore Key"));
                 } else {
                     // Only strongbox implementations should have strongbox in the subject line
-                    assertEquals(expectStrongBox, x509CurrCert.getSubjectDN()
-                                                              .getName()
-                                                              .toLowerCase()
-                                                              .contains("strongbox"));
+                    assertEquals(expectStrongBox, signedCertSubject.toString()
+                                                                   .toLowerCase()
+                                                                   .contains("strongbox"));
                 }
             } catch (InvalidKeyException | CertificateException | NoSuchAlgorithmException
                     | NoSuchProviderException | SignatureException e) {
diff --git a/tests/tests/net/Android.bp b/tests/tests/net/Android.bp
index 052ab26..2b99a40 100644
--- a/tests/tests/net/Android.bp
+++ b/tests/tests/net/Android.bp
@@ -72,15 +72,15 @@
     test_config_template: "AndroidTestTemplate.xml",
 }
 
-// Networking CTS tests that have a min_sdk_version of the latest released SDK. These tests can
-// be installed on release devices at any point in the release cycle and are useful for qualifying
-// mainline modules on release devices.
+// Networking CTS tests that target the latest released SDK. These tests can be installed on release
+// devices at any point in the Android release cycle and are useful for qualifying mainline modules
+// on release devices.
 android_test {
     name: "CtsNetTestCasesLatestSdk",
     defaults: ["CtsNetTestCasesDefaults"],
     jni_uses_sdk_apis: true,
     min_sdk_version: "29",
-    target_sdk_version: "29",
+    target_sdk_version: "30",
     test_suites: [
         "device-tests",
         "mts",
diff --git a/tests/tests/net/src/android/net/cts/MultinetworkApiTest.java b/tests/tests/net/src/android/net/cts/MultinetworkApiTest.java
index 985e313..6d3db89 100644
--- a/tests/tests/net/src/android/net/cts/MultinetworkApiTest.java
+++ b/tests/tests/net/src/android/net/cts/MultinetworkApiTest.java
@@ -68,7 +68,6 @@
         mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
         mCR = getContext().getContentResolver();
         mCtsNetUtils = new CtsNetUtils(getContext());
-        mCtsNetUtils.storePrivateDnsSetting();
     }
 
     @Override
@@ -223,6 +222,7 @@
 
     @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
     public void testResNApiNXDomainPrivateDns() throws InterruptedException {
+        mCtsNetUtils.storePrivateDnsSetting();
         // Enable private DNS strict mode and set server to dns.google before doing NxDomain test.
         // b/144521720
         try {
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index 4517327..773551b 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -17,23 +17,31 @@
 package android.os.cts
 
 import android.companion.CompanionDeviceManager
+import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
 import android.net.MacAddress
 import android.platform.test.annotations.AppModeFull
 import android.test.InstrumentationTestCase
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
 import com.android.compatibility.common.util.SystemUtil.runShellCommand
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
 import com.android.compatibility.common.util.ThrowingSupplier
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
 
 const val COMPANION_APPROVE_WIFI_CONNECTIONS =
         "android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS"
 const val DUMMY_MAC_ADDRESS = "00:00:00:00:00:10"
 const val MANAGE_COMPANION_DEVICES = "android.permission.MANAGE_COMPANION_DEVICES"
 const val SHELL_PACKAGE_NAME = "com.android.shell"
-val InstrumentationTestCase.context get() = instrumentation.context
+val InstrumentationTestCase.context get() = InstrumentationRegistry.getTargetContext()
 
 /**
  * Test for [CompanionDeviceManager]
  */
+@RunWith(AndroidJUnit4::class)
 class CompanionDeviceManagerTest : InstrumentationTestCase() {
 
     val cdm by lazy { context.getSystemService(CompanionDeviceManager::class.java) }
@@ -58,7 +66,13 @@
         }, *permissions)
     }
 
+    @Before
+    fun assumeHasFeature() {
+        assumeTrue(context.packageManager.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP))
+    }
+
     @AppModeFull(reason = "Companion API for non-instant apps only")
+    @Test
     fun testIsDeviceAssociated() {
         val userId = context.userId
         val packageName = context.packageName
@@ -78,6 +92,7 @@
     }
 
     @AppModeFull(reason = "Companion API for non-instant apps only")
+    @Test
     fun testIsDeviceAssociatedWithCompanionApproveWifiConnectionsPermission() {
         assertTrue(isCdmAssociated(
             DUMMY_MAC_ADDRESS, SHELL_PACKAGE_NAME, MANAGE_COMPANION_DEVICES,
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index 102741c..22329e6 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -19,6 +19,8 @@
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
 
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
     <!-- Install main test suite apk -->
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 82e2a2a..18224dd5 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -65,6 +65,10 @@
     private static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PERMISSION
             = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
 
+    private static final Date MANAGE_COMPANION_DEVICES_PATCH_DATE = parseDate("2020-07-01");
+    private static final String MANAGE_COMPANION_DEVICES_PERMISSION =
+            "android.Manifest.permission.MANAGE_COMPANION_DEVICES";
+
     private static final String LOG_TAG = "PermissionProtectionTest";
 
     private static final String PLATFORM_PACKAGE_NAME = "android";
@@ -437,9 +441,14 @@
     }
 
     private boolean shouldSkipPermission(String permissionName) {
-        return parseDate(SECURITY_PATCH).before(HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE) &&
-                HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PERMISSION.equals(permissionName);
-
+        switch (permissionName) {
+            case HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PERMISSION:
+                return parseDate(SECURITY_PATCH).before(HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE);
+            case MANAGE_COMPANION_DEVICES_PERMISSION:
+                return parseDate(SECURITY_PATCH).before(MANAGE_COMPANION_DEVICES_PATCH_DATE);
+            default:
+                return false;
+        }
     }
 
     private class ExpectedPermissionInfo {
diff --git a/tests/tests/permission3/AndroidTest.xml b/tests/tests/permission3/AndroidTest.xml
index 2e48ea8..557de85 100644
--- a/tests/tests/permission3/AndroidTest.xml
+++ b/tests/tests/permission3/AndroidTest.xml
@@ -25,6 +25,8 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
 
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPermission3TestCases.apk" />
diff --git a/tests/tests/role/AndroidTest.xml b/tests/tests/role/AndroidTest.xml
index 71a4861..4a8189f 100644
--- a/tests/tests/role/AndroidTest.xml
+++ b/tests/tests/role/AndroidTest.xml
@@ -23,6 +23,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java
index a992b9b..c03877c 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java
@@ -82,8 +82,8 @@
     private static final int MAX_RSRQ = -3;
     private static final int MIN_RSRQ = -35;
     // Maximum and minimum possible RSSNR values.
-    private static final int MAX_RSSNR = 50;
-    private static final int MIN_RSSNR = 0;
+    private static final int MAX_RSSNR = 30;
+    private static final int MIN_RSSNR = -20;
     // Maximum and minimum possible CQI values.
     private static final int MAX_CQI = 30;
     private static final int MIN_CQI = 0;
diff --git a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
index f7160dd..5e2f627 100644
--- a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -57,8 +57,11 @@
 import android.net.TetheringManager.TetheringRequest;
 import android.net.cts.util.CtsNetUtils;
 import android.net.cts.util.CtsNetUtils.TestNetworkCallback;
+import android.net.wifi.WifiClient;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.SoftApCallback;
 import android.os.Bundle;
+import android.os.ConditionVariable;
 import android.os.PersistableBundle;
 import android.os.ResultReceiver;
 import android.telephony.CarrierConfigManager;
@@ -135,6 +138,40 @@
         dropShellPermissionIdentity();
     }
 
+    private static class StopSoftApCallback implements SoftApCallback {
+        private final ConditionVariable mWaiting = new ConditionVariable();
+        @Override
+        public void onStateChanged(int state, int failureReason) {
+            if (state == WifiManager.WIFI_AP_STATE_DISABLED) mWaiting.open();
+        }
+
+        @Override
+        public void onConnectedClientsChanged(List<WifiClient> clients) { }
+
+        public void waitForSoftApStopped() {
+            if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
+                fail("stopSoftAp Timeout");
+            }
+        }
+    }
+
+    // Wait for softAp to be disabled. This is necessary on devices where stopping softAp
+    // deletes the interface. On these devices, tethering immediately stops when the softAp
+    // interface is removed, but softAp is not yet fully disabled. Wait for softAp to be
+    // fully disabled, because otherwise the next test might fail because it attempts to
+    // start softAp before it's fully stopped.
+    private void expectSoftApDisabled() {
+        final StopSoftApCallback callback = new StopSoftApCallback();
+        try {
+            mWm.registerSoftApCallback(c -> c.run(), callback);
+            // registerSoftApCallback will immediately call the callback with the current state, so
+            // this callback will fire even if softAp is already disabled.
+            callback.waitForSoftApStopped();
+        } finally {
+            mWm.unregisterSoftApCallback(callback);
+        }
+    }
+
     private class TetherChangeReceiver extends BroadcastReceiver {
         private class TetherState {
             final ArrayList<String> mAvailable;
@@ -294,6 +331,7 @@
         mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs);
 
         mTM.stopTethering(TETHERING_WIFI);
+        expectSoftApDisabled();
         mTetherChangeReceiver.expectTethering(false /* active */, wifiRegexs);
     }
 
@@ -544,6 +582,7 @@
 
     private void stopWifiTethering(final TestTetheringEventCallback callback) {
         mTM.stopTethering(TETHERING_WIFI);
+        expectSoftApDisabled();
         callback.expectTetheredInterfacesChanged(null);
         callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
     }
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 22052e1..6a1c4d6 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -770,17 +770,10 @@
         Thread.sleep(1000);
         assertEquals("Loaded", mOnUiThread.getTitle());
 
-        // Test that when AppCache is enabled and a valid path is provided, we
-        // get an AppCache callback of some kind.
-        mSettings.setAppCachePath(getActivity().getDir("appcache", 0).getPath());
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        new PollingCheck(WEBVIEW_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return mOnUiThread.getTitle() != null
-                        && mOnUiThread.getTitle().endsWith("Callback");
-            }
-        }.run();
+        // We used to test that when AppCache is enabled and a valid path is
+        // provided, we got an AppCache callback of some kind, but AppCache is
+        // deprecated on the web and will be removed from Chromium in the
+        // future, so this test has been removed.
     }
 
     // Ideally, we need a test case for the enabled case. However, it seems that
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
index 8e316e6..a692f12 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
@@ -89,4 +89,12 @@
             manager.getTxPacketCounters("wlan0");
         } catch (Exception ignore) {}
     }
+
+    @Test
+    public void testSetOnServiceDeadCallback() {
+        try {
+            WifiNl80211Manager manager = mContext.getSystemService(WifiNl80211Manager.class);
+            manager.setOnServiceDeadCallback(() -> {});
+        } catch (Exception ignore) {}
+    }
 }
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
index ca14b0e..fad4230 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -247,7 +247,9 @@
         assertEquals("Ranging request not success",
                 result.getStatus(), RangingResult.STATUS_SUCCESS);
         ResponderLocation responderLocation = result.getUnverifiedResponderLocation();
-        assertNotNull("ResponderLocation should not be null", responderLocation);
+        if (responderLocation == null) {
+            return;
+        }
         assertTrue("ResponderLocation is not valid", responderLocation.isLciSubelementValid());
 
         // Check LCI related APIs