Merge "[CTS] [tagging] Skip zero-init tests on svelte devices." into sc-dev
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgradeWrongSHA_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgradeWrongSHA_apk.asciipb
index f5a43a6..f866875 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgradeWrongSHA_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgradeWrongSHA_apk.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/CtsShimPrivUpgradeWrongSHA.apk"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgrade_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgrade_apk.asciipb
index 7055e93..ccefcc1 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgrade_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgrade_apk.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/CtsShimPrivUpgrade.apk"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgradeWrongSHA_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgradeWrongSHA_apk.asciipb
index 9695b38..264169d 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgradeWrongSHA_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgradeWrongSHA_apk.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/CtsShimPrivUpgradeWrongSHA.apk"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgrade_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgrade_apk.asciipb
index b991911..543d7cc 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgrade_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgrade_apk.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/CtsShimPrivUpgrade.apk"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
index 8e4aba3..6a1a592 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim_not_pre_installed.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v1_apex.asciipb
index 6a2b658..c01e04d 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v1_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v1_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v1.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index f661261..91c5d50 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_file.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index 5fc4b2a..d7e36fc 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_folder.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apex.asciipb
index 5be3661..849bab8 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index d063f7b..e59bbb1 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 489413e..4aeed69 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_certificate.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index 5e8ebb1..21717fc 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_package_name.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index 40c9d40..74573f6 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_no_hashtree.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
index 47bae74f..5672e5c 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_rebootless.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index 174c25e..acc83c0 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
index 5feae5e..13268eb 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index 24c0f65..355f90b 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index 71d362d..b840674 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index d1ed77a..60a8a3e 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index b0258fd..c360e44 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index 23a04cc..9941db2 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 0b03b4e..e041816 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index f04f17a..987a82a 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 53b97bb..2531fbb 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_wrong_sha.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_apex.asciipb
index 8bd42a5..6e6b103 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
new file mode 100644
index 0000000..655689a
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "7552332"
+    target: "CtsShim"
+    source_file: "aosp_arm64/com.android.apex.cts.shim.v3_rebootless.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//arm/com.android.apex.cts.shim.v3_rebootless.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "sc-dev"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index 973387c..ba0e7b8 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index 68b51c5..c470fe8 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
index b3e0b54..09b85f6 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim_not_pre_installed.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v1_apex.asciipb
index 6f2f51b..c057c89 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v1_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v1_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v1.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index f1120d1..82422cb 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_file.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index e0292c8..f29ff0d 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_folder.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apex.asciipb
index 76559f7..8f2a136 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index 500ebd0..766bf19 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 1ed4ed1..b88b655 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_certificate.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index 636c311..9d7558d 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_package_name.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index f6c604c..e5c6b65 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_no_hashtree.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
index 859ef2b..0be6a59 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_rebootless.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index 31710ef5..f1e7a2c 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
index 4851708..a986691 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index 96e61a3..be1b3a8 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index 31c119d..be9efdc 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index 0aae024..d675fce 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index 7858502..f3774cc 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index e7d8140..2f7c565 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 314ba5e..5bbee67 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index c7b268b..d8a6bd5 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 8573417..207fa1d 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_wrong_sha.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_apex.asciipb
index d2552a6..6ef3eb5 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
new file mode 100644
index 0000000..5264200
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "7552332"
+    target: "CtsShim"
+    source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_rebootless.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//x86/com.android.apex.cts.shim.v3_rebootless.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "sc-dev"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index 91dc4a5..face859 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index 579bf83..84a1dbe 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__arm_CtsShimTargetPSdk_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__arm_CtsShimTargetPSdk_apk.asciipb
index b3d3d44..d62c281 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__arm_CtsShimTargetPSdk_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__arm_CtsShimTargetPSdk_apk.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_arm64/CtsShimTargetPSdk.apk"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__x86_CtsShimTargetPSdk_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__x86_CtsShimTargetPSdk_apk.asciipb
index 7b49cb4..cb1fd5f 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__x86_CtsShimTargetPSdk_apk.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__x86_CtsShimTargetPSdk_apk.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7471822"
+    build_id: "7552332"
     target: "CtsShim"
     source_file: "aosp_x86_64/CtsShimTargetPSdk.apk"
   }
@@ -10,4 +10,6 @@
   git_project: "platform/cts"
   git_branch: "sc-dev"
   transform: TRANSFORM_NONE
+  transform_options {
+  }
 }
diff --git a/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png b/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png
index b4b3909..6fe984e 100644
--- a/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png
+++ b/apps/CameraITS/tests/scene1_1/scene1_1_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png b/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png
index b4b3909..6fe984e 100644
--- a/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png
+++ b/apps/CameraITS/tests/scene1_2/scene1_2_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py b/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py
index fa13835..51afe0d 100644
--- a/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py
+++ b/apps/CameraITS/tests/scene1_2/test_tonemap_sequence.py
@@ -28,23 +28,26 @@
 _MAX_DELTA_SAME = 0.03  # match number in test_burst_sameness_manual
 _MIN_DELTA_DIFF = 0.10
 _NAME = os.path.splitext(os.path.basename(__file__))[0]
-_NUM_FRAMES = 3
+_NUM_CAPTURES = 3
+_NUM_FRAMES_PER_CAPTURE = 4
 _PATCH_H = 0.1  # center 10%
 _PATCH_W = 0.1
 _PATCH_X = 0.5 - _PATCH_W/2
 _PATCH_Y = 0.5 - _PATCH_H/2
 _RGB_G_CH = 1
-_TMAP_NO_DELTA_FRAMES = list(range(_NUM_FRAMES-1)) + list(
-    range(_NUM_FRAMES, 2*_NUM_FRAMES-1))
+_TMAP_NO_DELTA_FRAMES = list(range(_NUM_CAPTURES-1)) + list(
+    range(_NUM_CAPTURES, 2*_NUM_CAPTURES-1))
 
 
-def do_captures_and_extract_means(cam, req, fmt, tonemap, log_path):
+def do_captures_and_extract_means(
+    cam, req, fmt, num_frames_per_cap, tonemap, log_path):
   """Do captures, save image and extract means from center patch.
 
   Args:
     cam: camera object.
     req: camera request.
     fmt: capture format.
+    num_frames_per_cap: int; number of frames per capture
     tonemap: string to determine 'linear' or 'default' tonemap.
     log_path: location to save images.
 
@@ -52,9 +55,10 @@
     appended means list.
   """
   green_means = []
-  for i in range(_NUM_FRAMES):
-    cap = cam.do_capture(req, fmt)
-    img = image_processing_utils.convert_capture_to_rgb_image(cap)
+
+  for i in range(_NUM_CAPTURES):
+    cap = cam.do_capture([req]*num_frames_per_cap, fmt)
+    img = image_processing_utils.convert_capture_to_rgb_image(cap[-1])
     image_processing_utils.write_image(
         img, '%s_%s_%d.jpg' % (os.path.join(log_path, _NAME), tonemap, i))
     patch = image_processing_utils.get_image_patch(
@@ -68,11 +72,11 @@
 class TonemapSequenceTest(its_base_test.ItsBaseTest):
   """Tests a sequence of shots with different tonemap curves.
 
-  There should be _NUM_FRAMES with a linear tonemap followed by a second set of
-  _NUM_FRAMES with the default tonemap.
+  There should be _NUM_CAPTURES with a linear tonemap followed by a second set
+  of _NUM_CAPTURES with the default tonemap.
 
-  asserts the frames in each _NUM_FRAMES bunch are similar
-  asserts the frames in the 2 _NUM_FRAMES bunches are different by >10%
+  asserts the frames in each _NUM_CAPTURES bunch are similar
+  asserts the frames in the 2 _NUM_CAPTURES bunches are different by >10%
   """
 
   def test_tonemap_sequence(self):
@@ -84,48 +88,51 @@
       props = cam.get_camera_properties()
       props = cam.override_with_hidden_physical_camera_props(props)
       camera_properties_utils.skip_unless(
-          camera_properties_utils.manual_sensor(props) and
-          camera_properties_utils.manual_post_proc(props) and
-          camera_properties_utils.per_frame_control(props) and
-          not camera_properties_utils.mono_camera(props))
+          not camera_properties_utils.mono_camera(props) and
+          camera_properties_utils.linear_tonemap(props))
+      if camera_properties_utils.per_frame_control(props):
+        num_frames_per_cap = 1
+      else:
+        num_frames_per_cape = _NUM_FRAMES_PER_CAPTURE
       log_path = self.log_path
 
       # Load chart for scene
       its_session_utils.load_scene(
           cam, props, self.scene, self.tablet, self.chart_distance)
 
+      # define formats
       largest_yuv = capture_request_utils.get_largest_yuv_format(props)
       match_ar = (largest_yuv['width'], largest_yuv['height'])
       fmt = capture_request_utils.get_smallest_yuv_format(
           props, match_ar=match_ar)
-      sens, exp, _, _, f_dist = cam.do_3a(do_af=True, get_results=True)
       means = []
 
       # linear tonemap req & captures
-      req = capture_request_utils.manual_capture_request(
-          sens, exp, f_dist, True, props)
+      cam.do_3a()
+      req = capture_request_utils.auto_capture_request(
+          linear_tonemap=True, props=props)
       means.extend(do_captures_and_extract_means(
-          cam, req, fmt, 'linear', log_path))
+          cam, req, fmt, num_frames_per_cap, 'linear', log_path))
 
       # default tonemap req & captures
-      req = capture_request_utils.manual_capture_request(
-          sens, exp, f_dist, False)
+      cam.do_3a()
+      req = capture_request_utils.auto_capture_request()
       means.extend(do_captures_and_extract_means(
-          cam, req, fmt, 'default', log_path))
+          cam, req, fmt, num_frames_per_cap, 'default', log_path))
 
       # Compute the delta between each consecutive frame pair
-      deltas = [np.fabs(means[i+1]-means[i]) for i in range(2*_NUM_FRAMES-1)]
+      deltas = [np.fabs(means[i+1]-means[i]) for i in range(2*_NUM_CAPTURES-1)]
       logging.debug('Deltas between consecutive frames: %s', str(deltas))
 
       # assert frames similar with same tonemap
       if not all([deltas[i] < _MAX_DELTA_SAME for i in _TMAP_NO_DELTA_FRAMES]):
-        raise AssertionError(
-            f'deltas: {str(deltas)}, MAX_DELTA: {_MAX_DELTA_SAME}')
+        raise AssertionError('Captures too different with same tonemap! '
+                             f'deltas: {deltas}, MAX_DELTA: {_MAX_DELTA_SAME}')
 
       # assert frames different with tonemap change
-      if deltas[_NUM_FRAMES-1] <= _MIN_DELTA_DIFF:
-        raise AssertionError(f'delta: {deltas[_NUM_FRAMES-1]:.5f}, '
-                             f'THRESH: {_MIN_DELTA_DIFF}')
+      if deltas[_NUM_CAPTURES-1] <= _MIN_DELTA_DIFF:
+        raise AssertionError('Captures too similar with different tonemaps! '
+                             f'deltas: {deltas}, THRESH: {_MIN_DELTA_DIFF}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene2_a/test_format_combos.py b/apps/CameraITS/tests/scene2_a/test_format_combos.py
index 740de49..7568da7 100644
--- a/apps/CameraITS/tests/scene2_a/test_format_combos.py
+++ b/apps/CameraITS/tests/scene2_a/test_format_combos.py
@@ -16,7 +16,6 @@
 
 import logging
 import os
-import sys
 
 from mobly import test_runner
 
@@ -28,6 +27,7 @@
 import target_exposure_utils
 
 
+AUTO_REQUEST_MODE = 1
 NAME = os.path.splitext(os.path.basename(__file__))[0]
 STOP_AT_FIRST_FAILURE = False  # change to True to have test break @ 1st FAIL
 
@@ -54,25 +54,21 @@
       its_session_utils.load_scene(
           cam, props, self.scene, self.tablet, self.chart_distance)
 
-      # Check skip conditions
-      camera_properties_utils.skip_unless(
-          camera_properties_utils.compute_target_exposure(props) and
-          camera_properties_utils.raw16(props))
-
       successes = []
       failures = []
       debug = self.debug_mode
 
-      # Two different requests: auto, and manual.
-      e, s = target_exposure_utils.get_target_exposure_combos(
-          self.log_path, cam)['midExposureTime']
+      # Up to 2 possible request types: auto and manual
       req_aut = capture_request_utils.auto_capture_request()
-      req_man = capture_request_utils.manual_capture_request(s, e)
-      reqs = [req_aut,  # R0
-              req_man]  # R1
+      reqs = [req_aut]
+      if camera_properties_utils.compute_target_exposure(props):
+        e, s = target_exposure_utils.get_target_exposure_combos(
+            self.log_path, cam)['midExposureTime']
+        req_man = capture_request_utils.manual_capture_request(s, e)
+        reqs.append(req_man)
 
-      # 10 different combos of output formats; some are single surfaces, and
-      # some are multiple surfaces.
+      # Up to 10 different combos of output formats.
+      # Some are single surfaces and some are multiple surfaces.
       wyuv, hyuv = capture_request_utils.get_available_output_sizes(
           'yuv', props)[-1]
       wjpg, hjpg = capture_request_utils.get_available_output_sizes(
@@ -81,47 +77,55 @@
       fmt_yuv_full = {'format': 'yuv'}
       fmt_jpg_prev = {'format': 'jpeg', 'width': wjpg, 'height': hjpg}
       fmt_jpg_full = {'format': 'jpeg'}
-      fmt_raw_full = {'format': 'raw'}
       fmt_combos = [
-          [fmt_yuv_prev],  # F0
-          [fmt_yuv_full],  # F1
-          [fmt_jpg_prev],  # F2
-          [fmt_jpg_full],  # F3
-          [fmt_raw_full],  # F4
-          [fmt_yuv_prev, fmt_jpg_prev],  # F5
-          [fmt_yuv_prev, fmt_jpg_full],  # F6
-          [fmt_yuv_prev, fmt_raw_full],  # F7
-          [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full],  # F8
-          [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full]   # F9
+          [fmt_yuv_prev],
+          [fmt_yuv_full],
+          [fmt_jpg_prev],
+          [fmt_jpg_full],
+          [fmt_yuv_prev, fmt_jpg_prev],
+          [fmt_yuv_prev, fmt_jpg_full],
       ]
+      if camera_properties_utils.raw16(props):
+        fmt_raw_full = {'format': 'raw'}
+        fmt_combos.extend([
+            [fmt_raw_full],
+            [fmt_yuv_prev, fmt_raw_full],
+            [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full],
+            [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full]])
 
       if camera_properties_utils.y8(props):
         wy8, hy8 = capture_request_utils.get_available_output_sizes(
             'y8', props)[-1]
         fmt_y8_prev = {'format': 'y8', 'width': wy8, 'height': hy8}
         fmt_y8_full = {'format': 'y8'}
-        fmt_combos.append([fmt_y8_prev])
-        fmt_combos.append([fmt_y8_full])
+        fmt_combos.extend([
+            [fmt_y8_prev],
+            [fmt_y8_full]])
 
-      # Two different burst lengths: single frame, and 3 frames.
-      burst_lens = [
-          1,  # B0
-          3  # B1
-      ]
+      # Two different burst lengths: single frame and 3 frames.
+      burst_lens = [1, 3]
 
       # There are 2xlen(fmt_combos)x2 different combinations.
       # Run through them all.
       n = 0
       for r, req in enumerate(reqs):
+        if req['android.control.mode'] == AUTO_REQUEST_MODE:
+          req_str = 'auto'
+        else:
+          req_str = 'manual'
         for f, fmt_combo in enumerate(fmt_combos):
           for b, burst_len in enumerate(burst_lens):
             try:
               caps = cam.do_capture([req] * burst_len, fmt_combo)
               successes.append((n, r, f, b))
-              logging.debug('==> Success[%02d]: R%d F%d B%d', n, r, f, b)
+              logging.debug('Success[%02d]', n)
+              logging.debug(' req: %s', req_str)
+              logging.debug(' fmt: %s', str(fmt_combo))
+              logging.debug(' burst_len: %d\n', burst_len)
 
               # Dump the captures out to jpegs in debug mode.
               if debug:
+                name_with_path = os.path.join(self.log_path, NAME)
                 if not isinstance(caps, list):
                   caps = [caps]
                 elif isinstance(caps[0], list):
@@ -129,16 +133,21 @@
                 for c, cap in enumerate(caps):
                   img = image_processing_utils.convert_capture_to_rgb_image(
                       cap, props=props)
-                  img_name = '%s_n%02d_r%d_f%d_b%d_c%d.jpg' % (os.path.join(
-                      self.log_path, NAME), n, r, f, b, c)
+                  img_name = (f'{name_with_path}_{n:02d}_{req_str}_fmt{f}_'
+                              f'burst{burst_len}_cap{c}.jpg')
                   image_processing_utils.write_image(img, img_name)
             # pylint: disable=broad-except
             except Exception as e:
               logging.error(e)
-              logging.error('==> Failure[%02d]: R%d F%d B%d', n, r, f, b)
+              logging.error('Failure[%02d]', n)
+              logging.debug(' req: %s', req_str)
+              logging.error(' fmt: %s', str(fmt_combo))
+              logging.error(' burst_len: %d\n', burst_len)
               failures.append((n, r, f, b))
               if STOP_AT_FIRST_FAILURE:
-                sys.exit(1)
+                raise AssertionError(
+                    f'Capture fail at combo req: {req_str}, fmt: {fmt_combo}, '
+                    f'burst: {burst_len}')
             n += 1
 
       num_fail = len(failures)
@@ -146,19 +155,13 @@
       num_total = len(reqs)*len(fmt_combos)*len(burst_lens)
       num_not_run = num_total - num_success - num_fail
 
-      logging.debug('Failures (%d / %d):', num_fail, num_total)
-      for (n, r, f, b) in failures:
-        logging.debug('  %02d: R%d F%d B%d', n, r, f, b)
-      logging.debug('Successes (%d / %d)', num_success, num_total)
-      for (n, r, f, b) in successes:
-        logging.debug('  %02d: R%d F%d B%d', n, r, f, b)
-      if num_not_run > 0:
-        logging.debug('Number of tests not run: %d / %d',
-                      num_not_run, num_total)
+      logging.debug('Success: %d / %d', num_success, num_total)
 
-      # The test passes if all the combinations successfully capture.
-      assert num_fail == 0
-      assert num_success == num_total
+      # assert all combinations successfully capture
+      if num_fail != 0:
+        raise AssertionError(f'Number of fails: {num_fail} / {num_total}')
+      if num_not_run > 0:
+        raise AssertionError(f'Number of combos not run: {num_not_run}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tests/scene3/test_flip_mirror.py b/apps/CameraITS/tests/scene3/test_flip_mirror.py
index 44e8269..2dff574 100644
--- a/apps/CameraITS/tests/scene3/test_flip_mirror.py
+++ b/apps/CameraITS/tests/scene3/test_flip_mirror.py
@@ -61,8 +61,8 @@
   template = cv2.imread(opencv_processing_utils.CHART_FILE, cv2.IMREAD_ANYDEPTH)
 
   # take img, crop chart, scale and prep for cv2 template match
-  s, e, _, _, fd = cam.do_3a(get_results=True, mono_camera=mono_camera)
-  req = capture_request_utils.manual_capture_request(s, e, fd)
+  cam.do_3a()
+  req = capture_request_utils.auto_capture_request()
   cap = cam.do_capture(req, fmt)
   y, _, _ = image_processing_utils.convert_capture_to_planes(cap, props)
   y = image_processing_utils.rotate_img_per_argv(y)
@@ -73,7 +73,8 @@
       patch.astype(np.uint8), chart.scale)
 
   # check image has content
-  assert np.max(patch)-np.min(patch) > 255/8
+  if np.max(patch)-np.min(patch) < 255/8:
+    raise AssertionError('Image patch has no content! Check setup.')
 
   # save full images if in debug
   if debug:
@@ -113,17 +114,16 @@
     opts.append(opt_val)
 
   # determine if 'nominal' or 'rotated' is best orientation
-  assert_flag = (opts[0] == max(opts) or opts[3] == max(opts))
-  assert assert_flag, ('Optimum orientation is %s' %
-                       CHART_ORIENTATIONS[np.argmax(opts)])
+  if not (opts[0] == max(opts) or opts[3] == max(opts)):
+    raise AssertionError(
+        f'Optimum orientation is {CHART_ORIENTATIONS[np.argmax(opts)]}')
   # print warning if rotated
   if opts[3] == max(opts):
-    logging.warning('Image is rotated 180 degrees. Try "rotate" flag.')
+    logging.warning('Image is rotated 180 degrees. Tablet might be rotated.')
 
 
 class FlipMirrorTest(its_base_test.ItsBaseTest):
-  """Test to verify if the image is flipped or mirrored.
-  """
+  """Test to verify if the image is flipped or mirrored."""
 
   def test_flip_mirror(self):
     """Test if image is properly oriented."""
@@ -139,14 +139,10 @@
       debug = self.debug_mode
       chart_loc_arg = self.chart_loc_arg
 
-      # Load chart for scene
+      # load chart for scene
       its_session_utils.load_scene(
           cam, props, self.scene, self.tablet, self.chart_distance)
 
-      # Check skip conditions
-      camera_properties_utils.skip_unless(
-          camera_properties_utils.read_3a(props))
-
       # initialize chart class and locate chart in scene
       chart = opencv_processing_utils.Chart(
           cam, props, self.log_path, chart_loc=chart_loc_arg)
diff --git a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
index fc7e75f..5f5ff36 100644
--- a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
+++ b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
@@ -317,11 +317,12 @@
   else:
     logging.debug('pose_reference is CAMERA')
     i_refs = [k for (k, v) in cam_reference.items() if v]
+    i_ref = i_refs[0]
     if len(i_refs) > 1:
-      raise AssertionError('More than 1 reference camera. Check translation '
-                           f'matrices. cam_reference: {cam_reference}')
+      logging.debug('Warning: more than 1 reference camera. Check translation '
+                    f'matrices. cam_reference: {cam_reference}')
+      i_2nd = i_refs[1]  # use second camera since both at same location
     else:
-      i_ref = i_refs[0]
       i_2nd = next(k for (k, v) in cam_reference.items() if not v)
   return i_ref, i_2nd
 
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index d5a2b6b..d5d3b06 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -603,5 +603,9 @@
 
   logging.info('Test execution completed.')
 
+  # Power down tablet
+  cmd = f'adb -s {tablet_id} shell input keyevent KEYCODE_POWER'
+  subprocess.Popen(cmd.split())
+
 if __name__ == '__main__':
   main()
diff --git a/apps/CameraITS/utils/camera_properties_utils.py b/apps/CameraITS/utils/camera_properties_utils.py
index ea393d7..c6bc32c 100644
--- a/apps/CameraITS/utils/camera_properties_utils.py
+++ b/apps/CameraITS/utils/camera_properties_utils.py
@@ -822,6 +822,20 @@
       'android.sensor.availableTestPatternModes')
 
 
+def linear_tonemap(props):
+  """Determines if camera supports CONTRAST_CURVE or GAMMA_VALUE in tonemap.
+
+  Args:
+    props: Camera properties object.
+
+  Returns:
+    Boolean. True if android.tonemap.availableToneMapModes has
+             CONTRAST_CURVE (0) or GAMMA_VALUE (3).
+  """
+  return (0 in props.get('android.tonemap.availableToneMapModes') or
+          3 in props.get('android.tonemap.availableToneMapModes'))
+
+
 if __name__ == '__main__':
   unittest.main()
 
diff --git a/apps/CameraITS/utils/capture_request_utils.py b/apps/CameraITS/utils/capture_request_utils.py
index 3855440..0ef4294 100644
--- a/apps/CameraITS/utils/capture_request_utils.py
+++ b/apps/CameraITS/utils/capture_request_utils.py
@@ -18,9 +18,19 @@
 import unittest
 
 
-def auto_capture_request():
-  """Returns a capture request with everything set to auto."""
-  return {
+def auto_capture_request(linear_tonemap=False, props=None):
+  """Returns a capture request with everything set to auto.
+
+  Args:
+   linear_tonemap: [Optional] boolean whether linear tonemap should be used.
+   props: [Optional] object from its_session_utils.get_camera_properties().
+          Must present when linear_tonemap is True.
+
+  Returns:
+    Auto capture request, ready to be passed to the
+    its_session_utils.device.do_capture()
+  """
+  req = {
       'android.control.mode': 1,
       'android.control.aeMode': 1,
       'android.control.awbMode': 1,
@@ -29,6 +39,24 @@
       'android.tonemap.mode': 1,
       'android.lens.opticalStabilizationMode': 0
   }
+  if linear_tonemap:
+    if props is None:
+      raise AssertionError('props is None with linear_tonemap.')
+    # CONTRAST_CURVE mode
+    if 0 in props['android.tonemap.availableToneMapModes']:
+      req['android.tonemap.mode'] = 0
+      req['android.tonemap.curve'] = {
+          'red': [0.0, 0.0, 1.0, 1.0],  # coordinate pairs: x0, y0, x1, y1
+          'green': [0.0, 0.0, 1.0, 1.0],
+          'blue': [0.0, 0.0, 1.0, 1.0]
+      }
+    # GAMMA_VALUE mode
+    elif 3 in props['android.tonemap.availableToneMapModes']:
+      req['android.tonemap.mode'] = 3
+      req['android.tonemap.gamma'] = 1.0
+    else:
+      raise AssertionError('Linear tonemap is not supported')
+  return req
 
 
 def manual_capture_request(sensitivity,
@@ -48,7 +76,7 @@
    linear_tonemap: [Optional] whether a linear tonemap should be used in this
      request.
    props: [Optional] the object returned from
-     its_session_utils.get_camera_properties().Must present when linear_tonemap
+     its_session_utils.get_camera_properties(). Must present when linear_tonemap
      is True.
 
   Returns:
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index a68507f..4c47388 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -1159,7 +1159,7 @@
   camera_id_combo = collections.namedtuple('CameraIdCombo', ['id', 'sub_id'])
   id_combos = []
   for one_id in ids:
-    one_combo = one_id.split(':')
+    one_combo = one_id.split(SUB_CAMERA_SEPARATOR)
     if len(one_combo) == 1:
       id_combos.append(camera_id_combo(one_combo[0], None))
     elif len(one_combo) == 2:
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 8e4721c..1931efe 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -4500,8 +4500,12 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_tunnel" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.software.leanback" />
             <meta-data android:name="test_excluded_features"
                        android:value="android.hardware.type.automotive" />
+            <meta-data android:name="display_mode"
+                       android:value="multi_display_mode" />
         </activity>
 
         <activity android:name=".tv.TvInputDiscoveryTestActivity"
diff --git a/apps/CtsVerifier/jni/audio_loopback/Android.bp b/apps/CtsVerifier/jni/audio_loopback/Android.bp
index 8232db9..81a8a45 100644
--- a/apps/CtsVerifier/jni/audio_loopback/Android.bp
+++ b/apps/CtsVerifier/jni/audio_loopback/Android.bp
@@ -12,7 +12,11 @@
         "frameworks/av/media/ndk/include",
         "system/core/include/cutils",
         "cts/apps/CtsVerifier/jni/megaaudio/player",
-        "cts/apps/CtsVerifier/jni/megaaudio/recorder"
+        "cts/apps/CtsVerifier/jni/megaaudio/recorder",
+        "external/oboe/include",
+        "external/oboe/src",
+        "external/oboe/src/common",
+        "external/oboe/src/aaudio",
     ],
     header_libs: ["jni_headers"],
     shared_libs: [
diff --git a/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp b/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
index 6cc3be9..b475c50 100644
--- a/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
+++ b/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
@@ -19,10 +19,21 @@
 #include <jni.h>
 #include <stdint.h>
 
+// If the NDK is before O then define this in your build
+// so that AAudio.h will not be included.
+// #define OBOE_NO_INCLUDE_AAUDIO
+
+// Oboe Includes
+//#include <oboe/Oboe.h>
+#include <AAudioExtensions.h>
+
 #include "NativeAudioAnalyzer.h"
 
 extern "C" {
 
+//
+// com.android.cts.verifier.audio.NativeAnalyzerThread
+//
 JNIEXPORT jlong JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_openAudio
   (JNIEnv * /*env */, jobject /* obj */,
           jint /* micSource */) {
@@ -131,4 +142,20 @@
     return 0;
 }
 
+//
+// com.android.cts.verifier.audio.audiolib.AudioUtils
+//
+JNIEXPORT jboolean JNICALL
+    Java_com_android_cts_verifier_audio_audiolib_AudioUtils_isMMapSupported(JNIEnv *env __unused) {
+
+    return oboe::AAudioExtensions().isMMapSupported();
+}
+
+JNIEXPORT jboolean JNICALL
+    Java_com_android_cts_verifier_audio_audiolib_AudioUtils_isMMapExclusiveSupported(
+        JNIEnv *env __unused) {
+
+    return oboe::AAudioExtensions().isMMapExclusiveSupported();
+}
+
 }
diff --git a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
index c8c7a69..ed4ca46 100644
--- a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
@@ -30,8 +30,6 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
-            <include layout="@layout/audio_loopback_header_layout"/>
-
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -43,10 +41,130 @@
                 <include layout="@layout/audio_loopback_device_layout" />
 
                 <LinearLayout
-                    android:orientation="vertical"
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Pro Audio:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_pro_audio"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="MMAP Supported:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_mmap"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="MMAP Exclusive Supported:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_mmap_exclusive"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Low Latency Support:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_low_latency"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Test Path:"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_testpath"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Required Max Latency (ms):"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_must_latency"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text="Recommended Max Latency (ms):"/>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:text=""
+                        android:id="@+id/audio_loopback_recommended_latency"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="horizontal"
                     android:layout_width="match_parent"
                     android:layout_height="match_parent"
                     android:id="@+id/audio_loopback_layout">
+
                     <Button
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
@@ -57,7 +175,6 @@
                         android:nextFocusDown="@+id/pass_button"
                         android:nextFocusLeft="@+id/audio_loopback_level_seekbar"
                         android:nextFocusRight="@+id/pass_button" />
-
                 </LinearLayout>
 
                 <include layout="@layout/audio_loopback_footer_layout"/>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index a4e9c6b..e68e316 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -790,14 +790,13 @@
         This test checks that APIs to notify the companion app of its associated device going in and
         out of Bluetooth range are working correctly.
         Before proceeding, make sure you have a Bluetooth LE device nearby and
-        discoverable. Also, make sure that bluetooth is turned on the device.
+        discoverable. Also, make sure that bluetooth is turned on. Note that, the nearby device can
+        not be a phone since it considers advertising as classic device scan.
         First, you press the go button, wait for a dialog to pop up and select your device from the
         list. Second, make sure your bluetooth device is unreachable(you can power off/reboot your
         Bluetooth device or put it into a Faraday bag) and press the Device Gone button.
         Lastly, make your bluetooth device reachable by waiting for the device to power on or
-        removing it from the Faraday bag and press the Device Present button. Note that, if you are
-        using a phone for the testing, please manually pair on another Bluetooth phone before
-        pressing Device Gone and Device Present.
+        removing it from the Faraday bag and press the Device Present button.
     </string>
 
     <string name="companion_service_test_gone_text">
@@ -4478,16 +4477,19 @@
          2. Press the \"Disable USB data signaling\" button to disable USB data signaling on
          the device. When disabled, all USB data connections (except from charging functions)
          are prohibited.\n
-         3. Press the \"Go\" button to go to Settings and confirm that the following preferences
-         cannot be selected:\n
+         3. Press the \"Go\" button to go to Settings and confirm that the "USB" preferences in
+         \"System > Developer Options\" cannot be selected and "USB" preference in
+         \"Connected devices\" has disappeared.:\n
               - Connected devices > USB\n
               - System > Developer Options > USB debugging\n
               - System > Developer Options > Default USB configuration\n
               - System > Developer Options > Disable USB audio routing\n
          4. Verify that you cannot mount the device as a USB drive on your desktop computer and
          cannot access files from your phone through USB.\n
-         5. Press the \"Enable USB data signaling\" button to re-enable USB data signaling on
-         the device.\n
+         5. Press the \"Enable USB data signaling\" button to re-enable USB data signaling and
+         replug USB cable in the device. After that the "USB" preferences in
+         \"System > Developer Options\" can be selected and "USB" preference in
+         \"Connected devices\" has appeared.\n
          Please mark the test accordingly.
     </string>
     <string name="device_owner_enable_usb_data_signaling_test">Enable USB data signaling</string>
@@ -5080,14 +5082,15 @@
     <!-- Audio Loopback Latency Test -->
     <string name="audio_loopback_latency_test">Audio Loopback Latency Test</string>
     <string name="audio_loopback_info">
-          This test requires some form of audio loopback. This can be either:\n
+        This test verifies that the device can achieve the required or recommended loopback latency.
+        To pass the test, the device need only achieve this on one of the following audio paths:\n
           - a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>  connected to a 3.5mm headset jack.\n
           - a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>  connected to a USB audio adapter.\n
-          - a USB interface with patch cords connecting the input and output jaccks.
+          - a USB interface with patch cords connecting the input and output jacks.\n
           Please connect one of these Loopback mechanisms, and proceed with the instructions
-          on the screen.
-          The system will measure the input-output audio latency by injecting a pulse on the output,
-          and computing the distance between replicas of the pulse.
+          on the screen. The required &amp; recommended latencies will be displayed.
+          The system will measure the input-output audio latency by injecting an audio signal to
+          the output and compute the time between generating the signal and recording it back.
           You can vary the Audio Level slider to ensure the pulse will feed back at adequate levels.
           Repeat until a confidence level >= 0.6 is achieved.
     </string>
@@ -6015,12 +6018,6 @@
 
     <string name="loopback_test_question">Does this device allow for the connection of a loopback audio peripheral?</string>
     <string name="loopback_dlg_caption">Loopback Peripheral Required</string>
-    <string name="loopback_dlg_text">This test requires an Audio Loopback Peripheral to be connected to the device.\n
-        This can be done in one of three ways:\n
-        1. Connect a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a> to the 3.5mm headset jack.\n
-        2. Connect a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a> to a USB-C headset adapter.\n
-        3. Connect a USB audio interface peripheral and connect the outputs to the inputs with audio patch cables.
-    </string>
 
     <string name="display_cutout_test">DisplayCutout Test</string>
     <string name="display_cutout_test_instruction">\n
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
index e0ff267..b5e5738 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackBaseActivity.java
@@ -26,7 +26,6 @@
 import android.os.Message;
 import android.util.Log;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.ProgressBar;
@@ -35,7 +34,9 @@
 
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
 import com.android.cts.verifier.audio.audiolib.StatUtils;
+import com.android.cts.verifier.audio.audiolib.AudioUtils;
 import com.android.cts.verifier.CtsVerifierReportLog;
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
@@ -49,29 +50,56 @@
 public class AudioLoopbackBaseActivity extends PassFailButtons.Activity {
     private static final String TAG = "AudioLoopbackBaseActivity";
 
+    // JNI load
+    static {
+        try {
+            System.loadLibrary("audioloopback_jni");
+        } catch (UnsatisfiedLinkError e) {
+            Log.e(TAG, "Error loading Audio Loopback JNI library");
+            Log.e(TAG, "e: " + e);
+            e.printStackTrace();
+        }
+
+        /* TODO: gracefully fail/notify if the library can't be loaded */
+    }
     protected AudioManager mAudioManager;
 
     // UI
-    OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
-
-    Button mLoopbackPortYesBtn;
-    Button mLoopbackPortNoBtn;
-
     TextView mInputDeviceTxt;
     TextView mOutputDeviceTxt;
 
     TextView mAudioLevelText;
     SeekBar mAudioLevelSeekbar;
 
+    TextView mTestPathTxt;
+
     TextView mResultText;
     ProgressBar mProgressBar;
     int mMaxLevel;
 
+    String mYesString;
+    String mNoString;
+
+    // These flags determine the maximum allowed latency
+    private boolean mClaimsProAudio;
+    private boolean mClaimsOutput;
+    private boolean mClaimsInput;
+
+    // Useful info
+    private boolean mSupportsMMAP = AudioUtils.isMMapSupported();
+    private boolean mSupportsMMAPExclusive = AudioUtils.isMMapExclusiveSupported();
+
     // Peripheral(s)
     boolean mIsPeripheralAttached;  // CDD ProAudio section C-1-3
     AudioDeviceInfo mOutputDevInfo;
     AudioDeviceInfo mInputDevInfo;
 
+    protected static final int TESTPERIPHERAL_NONE          = 0;
+    protected static final int TESTPERIPHERAL_ANALOG_JACK   = 1;
+    protected static final int TESTPERIPHERAL_USB           = 2;
+    protected static final int TESTPERIPHERAL_DEVICE        = 3; // device speaker + mic
+    protected int mTestPeripheral = TESTPERIPHERAL_NONE;
+
     // Loopback Logic
     NativeAnalyzerThread mNativeAnalyzerThread = null;
 
@@ -86,7 +114,15 @@
     protected double mMeanConfidence;
 
     protected static final double CONFIDENCE_THRESHOLD = 0.6;
-    protected static final double PROAUDIO_LATENCY_MS_LIMIT = 20.0;
+    // impossibly low latencies (indicating something in the test went wrong).
+    protected static final float EPSILON = 1.0f;
+    protected static final double PROAUDIO_RECOMMENDED_LATENCY_MS = 20.0;
+    protected static final double PROAUDIO_RECOMMENDED_USB_LATENCY_MS = 25.0;
+    protected static final double PROAUDIO_MUST_LATENCY_MS = 20.0;
+    protected static final double BASIC_RECOMMENDED_LATENCY_MS = 50.0;
+    protected static final double BASIC_MUST_LATENCY_MS = 800.0;
+    protected double mMustLatency;
+    protected double mRecommendedLatency;
 
     // The audio stream callback threads should stop and close
     // in less than a few hundred msec. This is a generous timeout value.
@@ -95,29 +131,11 @@
     //
     // Common UI Handling
     //
-    void enableLayout(int layoutId, boolean enable) {
-        ViewGroup group = (ViewGroup)findViewById(layoutId);
-        for (int i = 0; i < group.getChildCount(); i++) {
-            group.getChildAt(i).setEnabled(enable);
-        }
-    }
-
     private void connectLoopbackUI() {
-        // Has Loopback - Yes
-        mLoopbackPortYesBtn = (Button)findViewById(R.id.loopback_tests_yes_btn);
-        mLoopbackPortYesBtn.setOnClickListener(mBtnClickListener);
-
-        // Has Looback - No
-        mLoopbackPortNoBtn = (Button)findViewById(R.id.loopback_tests_no_btn);
-        mLoopbackPortNoBtn.setOnClickListener(mBtnClickListener);
-
         // Connected Device
         mInputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackInputLbl));
         mOutputDeviceTxt = ((TextView)findViewById(R.id.audioLoopbackOutputLbl));
 
-        // Loopback Info
-        findViewById(R.id.loopback_tests_info_btn).setOnClickListener(mBtnClickListener);
-
         mAudioLevelText = (TextView)findViewById(R.id.audio_loopback_level_text);
         mAudioLevelSeekbar = (SeekBar)findViewById(R.id.audio_loopback_level_seekbar);
         mMaxLevel = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
@@ -136,16 +154,14 @@
             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                         progress, 0);
+                Log.i(TAG,"Level set to: " + progress);
                 refreshLevel();
-                Log.i(TAG,"Changed stream volume to: " + progress);
             }
         });
 
         mResultText = (TextView)findViewById(R.id.audio_loopback_results_text);
         mProgressBar = (ProgressBar)findViewById(R.id.audio_loopback_progress_bar);
         showWait(false);
-
-        enableTestUI(false);
     }
 
     //
@@ -162,8 +178,8 @@
         // Any valid peripherals
         // Do we leave in the Headset test to support a USB-Dongle?
         for (AudioDeviceInfo devInfo : devices) {
-            if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||     // USB Peripheral
-                    devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET ||    // USB dongle+LBPlug
+            if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE || // USB Peripheral
+                    devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET || // USB dongle+LBPlug
                     devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || // Loopback Plug?
                     devInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { // Aux-cable loopback?
                 if (devInfo.isSink()) {
@@ -178,7 +194,10 @@
         }
 
         mIsPeripheralAttached = mOutputDevInfo != null || mInputDevInfo != null;
+        calculateTestPeripheral();
         showConnectedAudioPeripheral();
+        calculateLatencyThresholds();
+        displayLatencyThresholds();
     }
 
     protected void handleDeviceConnection(AudioDeviceInfo deviceInfo) {
@@ -202,6 +221,27 @@
         }
     }
 
+    protected void calculateTestPeripheral() {
+        if (!mIsPeripheralAttached) {
+            mTestPeripheral = TESTPERIPHERAL_DEVICE;
+        } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||
+                mInputDevInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
+            mTestPeripheral = TESTPERIPHERAL_USB;
+        } else if (mInputDevInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET ||
+                mInputDevInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) {
+            mTestPeripheral = TESTPERIPHERAL_ANALOG_JACK;
+        } else {
+            // Huh?
+            Log.e(TAG, "No valid peripheral found!?");
+            mTestPeripheral = TESTPERIPHERAL_NONE;
+        }
+    }
+
+    protected boolean isPeripheralValidForTest() {
+        return mTestPeripheral == TESTPERIPHERAL_ANALOG_JACK
+                || mTestPeripheral == TESTPERIPHERAL_USB;
+
+    }
     protected void showConnectedAudioPeripheral() {
         mInputDeviceTxt.setText(
                 mInputDevInfo != null ? mInputDevInfo.getProductName().toString()
@@ -209,6 +249,71 @@
         mOutputDeviceTxt.setText(
                 mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString()
                         : "");
+
+        String pathName;
+        switch (mTestPeripheral) {
+            case TESTPERIPHERAL_ANALOG_JACK:
+                pathName = "Headset Jack";
+                break;
+
+            case TESTPERIPHERAL_USB:
+                pathName = "USB";
+                break;
+
+            case TESTPERIPHERAL_DEVICE:
+                pathName = "Device Speaker + Microphone";
+                break;
+
+            case TESTPERIPHERAL_NONE:
+            default:
+                pathName = "Error. Unknown Test Path";
+                break;
+        }
+        mTestPathTxt.setText(pathName);
+    }
+
+    private void calculateLatencyThresholds() {
+        switch (mTestPeripheral) {
+            case TESTPERIPHERAL_ANALOG_JACK:
+                mRecommendedLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency =  mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_MUST_LATENCY_MS;
+                break;
+
+            case TESTPERIPHERAL_USB:
+                mRecommendedLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_USB_LATENCY_MS : BASIC_MUST_LATENCY_MS;
+                break;
+
+            case TESTPERIPHERAL_DEVICE:
+                // This isn't a valid case so we won't pass it, but it can be run
+                mRecommendedLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS : BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency = mClaimsProAudio
+                        ? PROAUDIO_RECOMMENDED_LATENCY_MS :BASIC_MUST_LATENCY_MS;
+                break;
+
+            case TESTPERIPHERAL_NONE:
+            default:
+                mRecommendedLatency = BASIC_RECOMMENDED_LATENCY_MS;
+                mMustLatency = BASIC_MUST_LATENCY_MS;
+                break;
+        }
+    }
+
+    private void displayLatencyThresholds() {
+        if (isPeripheralValidForTest()) {
+            ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText("" + mMustLatency);
+            ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(
+                    "" + mRecommendedLatency);
+        } else {
+            String naStr = getResources().getString(R.string.audio_proaudio_NA);
+            ((TextView) findViewById(R.id.audio_loopback_must_latency)).setText(naStr);
+            ((TextView) findViewById(R.id.audio_loopback_recommended_latency)).setText(naStr);
+        }
     }
 
     /**
@@ -224,50 +329,11 @@
         mAudioLevelText.setText(levelText);
     }
 
-    private void showLoopbackInfoDialog() {
-        new AlertDialog.Builder(this)
-                .setTitle(R.string.loopback_dlg_caption)
-                .setMessage(R.string.loopback_dlg_text)
-                .setPositiveButton(R.string.audio_general_ok, null)
-                .show();
-    }
-
     //
     // show active progress bar
     //
     protected void showWait(boolean show) {
-        if (show) {
-            mProgressBar.setVisibility(View.VISIBLE) ;
-        } else {
-            mProgressBar.setVisibility(View.INVISIBLE) ;
-        }
-    }
-
-
-    private class OnBtnClickListener implements OnClickListener {
-        @Override
-        public void onClick(View v) {
-            switch (v.getId()) {
-                case R.id.loopback_tests_yes_btn:
-                    Log.i(TAG, "User confirms Headset Port existence");
-                    recordLoopbackStatus(true);
-                    mLoopbackPortYesBtn.setEnabled(false);
-                    mLoopbackPortNoBtn.setEnabled(false);
-                    break;
-
-                case R.id.loopback_tests_no_btn:
-                    Log.i(TAG, "User denies Headset Port existence");
-                    recordLoopbackStatus(false);
-                    getPassButton().setEnabled(true);
-                    mLoopbackPortYesBtn.setEnabled(false);
-                    mLoopbackPortNoBtn.setEnabled(false);
-                    break;
-
-                case R.id.loopback_tests_info_btn:
-                    showLoopbackInfoDialog();
-                    break;
-            }
-        }
+        mProgressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
     }
 
     //
@@ -277,10 +343,14 @@
     private static final String KEY_LATENCY = "latency";
     private static final String KEY_CONFIDENCE = "confidence";
     private static final String KEY_SAMPLE_RATE = "sample_rate";
+    private static final String KEY_IS_PRO_AUDIO = "is_pro_audio";
     private static final String KEY_IS_LOW_LATENCY = "is_low_latency";
     private static final String KEY_IS_PERIPHERAL_ATTACHED = "is_peripheral_attached";
     private static final String KEY_INPUT_PERIPHERAL_NAME = "input_peripheral";
     private static final String KEY_OUTPUT_PERIPHERAL_NAME = "output_peripheral";
+    private static final String KEY_TEST_PERIPHERAL = "test_peripheral";
+    private static final String KEY_TEST_MMAP = "supports_mmap";
+    private static final String KEY_TEST_MMAPEXCLUSIVE = "supports_mmap_exclusive";
 
     @Override
     public String getTestId() {
@@ -327,6 +397,30 @@
                 ResultType.NEUTRAL,
                 ResultUnit.NONE);
 
+        reportLog.addValue(
+                KEY_IS_PRO_AUDIO,
+                mClaimsProAudio,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_TEST_PERIPHERAL,
+                mTestPeripheral,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_TEST_MMAP,
+                mSupportsMMAP,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_TEST_MMAPEXCLUSIVE ,
+                mSupportsMMAPExclusive,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
         if (mIsPeripheralAttached) {
             reportLog.addValue(
                     KEY_INPUT_PERIPHERAL_NAME,
@@ -384,20 +478,29 @@
     }
 
     protected void handleTestCompletion() {
-        Log.i(TAG, "handleTestCompletion() ...");
-
         mMeanLatencyMillis = StatUtils.calculateMean(mLatencyMillis);
-        mMeanAbsoluteDeviation = StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
+        mMeanAbsoluteDeviation =
+                StatUtils.calculateMeanAbsoluteDeviation(mMeanLatencyMillis, mLatencyMillis);
         mMeanConfidence = StatUtils.calculateMean(mConfidence);
 
-        String result = String.format(
-            "Test Finished\nMean Latency:%.2f ms\nMean Absolute Deviation: %.2f\n" +
-                " Confidence: %.2f\n" +
-                " Low Latency Path: %s",
-            mMeanLatencyMillis,
-            mMeanAbsoluteDeviation,
-            mMeanConfidence,
-            (mNativeAnalyzerThread.isLowLatencyStream() ? "yes" : "no"));
+
+        String result;
+        if (mMeanConfidence < CONFIDENCE_THRESHOLD) {
+            result = String.format(
+                    "Test Finished\nInsufficient Confidence (%.2f < %.2f). No Results.",
+                    mMeanConfidence, CONFIDENCE_THRESHOLD);
+        } else {
+            result = String.format(
+                    "Test Finished\nMean Latency:%.2f ms (required:%.2f)\n" +
+                            "Mean Absolute Deviation: %.2f\n" +
+                            " Confidence: %.2f\n" +
+                            " Low Latency Path: %s",
+                    mMeanLatencyMillis,
+                    mMustLatency,
+                    mMeanAbsoluteDeviation,
+                    mMeanConfidence,
+                    mNativeAnalyzerThread.isLowLatencyStream() ? mYesString : mNoString);
+        }
 
         // Make sure the test thread is finished. It should already be done.
         if (mNativeAnalyzerThread != null) {
@@ -407,11 +510,7 @@
                 e.printStackTrace();
             }
         }
-        Log.i(TAG, result);
-
         mResultText.setText(result);
-
-        Log.i(TAG, "... Done");
     }
 
     protected void handleTestPhaseCompletion() {
@@ -424,7 +523,6 @@
                     mTestPhase,
                     mLatencyMillis[mTestPhase],
                     mConfidence[mTestPhase]);
-            Log.i(TAG, result);
 
             mResultText.setText(result);
             try {
@@ -453,9 +551,8 @@
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED:
                     Log.v(TAG,"got message native rec started!!");
                     showWait(true);
-                    mResultText.setText(String.format("Test Running (phase: %d, low-latency: %s)...",
-                            (mTestPhase + 1),
-                            (mNativeAnalyzerThread.isLowLatencyStream() ? "yes" : "no")));
+                    mResultText.setText(String.format("[phase: %d] - Test Running...",
+                            (mTestPhase + 1)));
                     break;
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR:
                     Log.v(TAG,"got message native rec can't start!!");
@@ -473,9 +570,8 @@
                     break;
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING:
                     Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_ANALYZING");
-                    mResultText.setText(String.format("Analyzing (phase: %d, low-latency: %s)...",
-                            mTestPhase + 1,
-                            (mNativeAnalyzerThread.isLowLatencyStream() ? "yes" : "no")));
+                    mResultText.setText(String.format("[phase: %d] - Analyzing ...",
+                            mTestPhase + 1));
                     break;
                 case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
                     Log.i(TAG, "NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE");
@@ -491,17 +587,36 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mClaimsOutput = AudioSystemFlags.claimsOutput(this);
+        mClaimsInput = AudioSystemFlags.claimsInput(this);
+        mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
+
+        mYesString = getResources().getString(R.string.audio_general_yes);
+        mNoString = getResources().getString(R.string.audio_general_no);
+
+        // Pro Audio
+        ((TextView)findViewById(R.id.audio_loopback_pro_audio)).setText(
+                "" + (mClaimsProAudio ? mYesString : mNoString));
+
+        // MMAP
+        ((TextView)findViewById(R.id.audio_loopback_mmap)).setText(
+                "" + (mSupportsMMAP ? mYesString : mNoString));
+        ((TextView)findViewById(R.id.audio_loopback_mmap_exclusive)).setText(
+                "" + (mSupportsMMAPExclusive ? mYesString : mNoString));
+
+        // Low Latency
+        ((TextView)findViewById(R.id.audio_loopback_low_latency)).setText(
+                "" + (AudioSystemFlags.claimsLowLatencyAudio(this) ? mYesString : mNoString));
+
+        mTestPathTxt = ((TextView)findViewById(R.id.audio_loopback_testpath));
+
         mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
 
         mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
 
         connectLoopbackUI();
-    }
 
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-
+        calculateLatencyThresholds();
+        displayLatencyThresholds();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
index 26f770c..f808073 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -64,7 +64,6 @@
     protected void onCreate(Bundle savedInstanceState) {
         // we need to do this first so that the layout is inplace when the super-class inits
         setContentView(R.layout.audio_loopback_latency_activity);
-        super.onCreate(savedInstanceState);
 
         mTestButton =(Button)findViewById(R.id.audio_loopback_test_btn);
         mTestButton.setOnClickListener(mBtnClickListener);
@@ -72,6 +71,8 @@
         setPassFailButtonClickListeners();
         getPassButton().setEnabled(false);
         setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
+
+        super.onCreate(savedInstanceState);
     }
 
     protected void startAudioTest() {
@@ -84,8 +85,12 @@
 
         // We are not enforcing the latency target (PROAUDIO_LATENCY_MS_LIMIT)
         // test is allowed to pass as long as an analysis is done.
-        boolean resultValid = mMeanConfidence >= CONFIDENCE_THRESHOLD
-                && mMeanLatencyMillis > 1.0;
+        boolean resultValid =
+                isPeripheralValidForTest()
+                && mMeanConfidence >= CONFIDENCE_THRESHOLD
+                && mMeanLatencyMillis > EPSILON
+                && mMeanLatencyMillis < mMustLatency;
+
         getPassButton().setEnabled(resultValid);
 
         recordTestResults();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
index ba01e25..d32749f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
@@ -30,6 +30,7 @@
 
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
 import com.android.cts.verifier.CtsVerifierReportLog;
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
@@ -77,28 +78,6 @@
         super();
     }
 
-    private boolean claimsProAudio() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
-    }
-
-    private boolean claimsLowLatencyAudio() {
-        // CDD Section C-1-1: android.hardware.audio.low_latency
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
-    }
-
-    private boolean claimsMIDI() {
-        // CDD Section C-1-4: android.software.midi
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
-    }
-
-    private boolean claimsUSBHostMode() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
-    }
-
-    private boolean claimsUSBPeripheralMode() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
-    }
-
     // HDMI Stuff
     private boolean isHDMIValid() {
         if (mHDMIDeviceInfo == null) {
@@ -208,7 +187,7 @@
         setPassFailButtonClickListeners();
         setInfoResources(R.string.proaudio_test, R.string.proaudio_info, -1);
 
-        mClaimsProAudio = claimsProAudio();
+        mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
         ((TextView)findViewById(R.id.proAudioHasProAudioLbl)).setText("" + mClaimsProAudio);
 
         if (!mClaimsProAudio) {
@@ -218,16 +197,16 @@
             showDialog(INFO_DIALOG_ID, args);
         }
 
-        mClaimsLowLatencyAudio = claimsLowLatencyAudio();
+        mClaimsLowLatencyAudio = AudioSystemFlags.claimsLowLatencyAudio(this);
         ((TextView)findViewById(R.id.proAudioHasLLALbl)).setText("" + mClaimsLowLatencyAudio);
 
-        mClaimsMIDI = claimsMIDI();
+        mClaimsMIDI = AudioSystemFlags.claimsMIDI(this);
         ((TextView)findViewById(R.id.proAudioHasMIDILbl)).setText("" + mClaimsMIDI);
 
-        mClaimsUSBHostMode = claimsUSBHostMode();
+        mClaimsUSBHostMode = AudioSystemFlags.claimsUSBHostMode(this);
         ((TextView)findViewById(R.id.proAudioMidiHasUSBHostLbl)).setText("" + mClaimsUSBHostMode);
 
-        mClaimsUSBPeripheralMode = claimsUSBPeripheralMode();
+        mClaimsUSBPeripheralMode = AudioSystemFlags.claimsUSBPeripheralMode(this);
         ((TextView)findViewById(
                 R.id.proAudioMidiHasUSBPeripheralLbl)).setText("" + mClaimsUSBPeripheralMode);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioSystemFlags.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioSystemFlags.java
new file mode 100644
index 0000000..bffbdc8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioSystemFlags.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.audio.audiolib;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.AudioDeviceInfo;
+import android.util.Log;
+
+public class AudioSystemFlags {
+    static final String TAG = AudioSystemFlags.class.getName();
+
+    public static boolean claimsOutput(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+    }
+
+    public static boolean claimsInput(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE);
+    }
+
+    public static boolean claimsProAudio(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
+    }
+
+    public static boolean claimsLowLatencyAudio(Context context) {
+        // CDD Section C-1-1: android.hardware.audio.low_latency
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
+    }
+
+    public static boolean claimsMIDI(Context context) {
+        // CDD Section C-1-4: android.software.midi
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
+    }
+
+    public static boolean claimsUSBHostMode(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
+    }
+
+    public static boolean claimsUSBPeripheralMode(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
index 55b7f9a..97f6a85 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
@@ -81,4 +81,7 @@
     public static int calcFrameSizeInBytes(int encoding, int numChannels) {
         return sampleSizeInBytes(encoding) * numChannels;
     }
+
+    public static native boolean isMMapSupported();
+    public static native boolean isMMapExclusiveSupported();
 }
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
index 3b11c4c..85db63f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
@@ -57,12 +57,12 @@
                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"22,4\" SampleRates=\"44100,48000,88200,96000\"/>" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox 44VSL\" ProfileDescription=\"Presonus AudioBox 44VSL\" ProductName=\"USB-Audio - AudioBox 44 VSL\">" +
-                "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
-                "<InputDevInfo ChanCounts=\"1,2,3,4\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3,7,15\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<InputDevInfo ChanCounts=\"1,2,3,4\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3,7,15\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox 22VSL\" ProfileDescription=\"Presonus AudioBox 22VSL\" ProductName=\"USB-Audio - AudioBox 22 VSL\">" +
-                "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
-                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
+                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox USB\" ProfileDescription=\"Presonus AudioBox USB\" ProductName=\"USB-Audio - AudioBox USB\">" +
                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"44100,48000\" />" +
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS
index 8e3d9b9..9847737 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 24950
-eugenesusla@google.com
\ No newline at end of file
+evanxinchen@google.com
+guojing@google.com
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java
index fd5198a..a813454 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubbleActivity.java
@@ -4,12 +4,11 @@
 import static android.view.View.VISIBLE;
 
 import android.app.Activity;
+import android.content.Intent;
 import android.graphics.Insets;
-import android.graphics.Rect;
 import android.os.Bundle;
 import android.view.View;
 import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 import android.widget.EditText;
@@ -24,6 +23,7 @@
     public static final String EXTRA_TEST_NAME = "test_id";
     public static final String TEST_MIN_HEIGHT = "minHeight";
     public static final String TEST_MAX_HEIGHT = "maxHeight";
+    public static final String EXTRA_INSETS = "insets";
 
     private View mRoot;
     private TextView mTitle;
@@ -31,14 +31,13 @@
     private EditText mEditText;
 
     private String mTestName = null;
-    private Rect mBounds = new Rect();
+    private Insets mInsets;
     private boolean mIsLargeScreen;
 
     private ViewTreeObserver.OnGlobalLayoutListener mListener =
             new ViewTreeObserver.OnGlobalLayoutListener() {
                 @Override
                 public void onGlobalLayout() {
-                    mRoot.getBoundsOnScreen(mBounds);
                     checkHeight();
                     mRoot.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                 }
@@ -60,7 +59,9 @@
     }
 
     private void setUpTestForExtras() {
-        mTestName = getIntent().getStringExtra(EXTRA_TEST_NAME);
+        Intent i = getIntent();
+        mTestName = i.getStringExtra(EXTRA_TEST_NAME);
+        mInsets = i.getParcelableExtra(EXTRA_INSETS);
         if (mTestName == null) {
             mTestMessage.setVisibility(GONE);
             return;
@@ -87,18 +88,18 @@
                 mTestMessage.setText("Test Passed!");
             }
         } else if (TEST_MAX_HEIGHT.equals(mTestName)) {
-            WindowMetrics windowMetrics =
+            // These are max size which won't include insets.
+            WindowMetrics windowMetricsMax =
                     getSystemService(WindowManager.class).getMaximumWindowMetrics();
-            WindowInsets metricInsets = windowMetrics.getWindowInsets();
-            Insets insets = metricInsets.getInsetsIgnoringVisibility(
-                    WindowInsets.Type.navigationBars()
-                            | WindowInsets.Type.statusBars()
-                            | WindowInsets.Type.displayCutout());
+            // These show the metrics for the bubble activity / the bounds will be that of TaskView
+            WindowMetrics bubbleWindowMetrics =
+                    getSystemService(WindowManager.class).getCurrentWindowMetrics();
             if (mIsLargeScreen) {
-                final float percentOfScreen = windowMetrics.getBounds().height() * 0.70f;
-                if (mBounds.height() < percentOfScreen) {
+                final float percentOfScreen = windowMetricsMax.getBounds().height() * 0.70f;
+                if (bubbleWindowMetrics.getBounds().height() < percentOfScreen) {
                     mTestMessage.setText("Test failed --"
-                            + " the bubble expanded view is too small, it is: " + mBounds.height()
+                            + " the bubble expanded view is too small, it is: "
+                            + bubbleWindowMetrics.getBounds().height()
                             + " and minimum is: " + percentOfScreen);
                 } else {
                     mTestMessage.setText("Test Passed!");
@@ -108,8 +109,8 @@
                 // padding for the manage button so we allow some flux (200dp).
                 int maxHeightBuffer = getResources().getDimensionPixelSize(
                         R.dimen.bubble_expanded_view_max_height_buffer);
-                int bottomInset = windowMetrics.getBounds().bottom - insets.bottom;
-                int diff = bottomInset - mBounds.bottom;
+                int bottomInset = windowMetricsMax.getBounds().bottom - mInsets.bottom;
+                int diff = bottomInset - bubbleWindowMetrics.getBounds().bottom;
                 if (diff > maxHeightBuffer) {
                     mTestMessage.setText("Test failed -- bottom of the bubble expanded view "
                             + "isn't close enough to the bottom inset: " + diff);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
index 7efae29..5701c90 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
@@ -24,6 +24,7 @@
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
+import static com.android.cts.verifier.notifications.BubbleActivity.EXTRA_INSETS;
 import static com.android.cts.verifier.notifications.BubbleActivity.EXTRA_TEST_NAME;
 import static com.android.cts.verifier.notifications.BubbleActivity.TEST_MAX_HEIGHT;
 import static com.android.cts.verifier.notifications.BubbleActivity.TEST_MIN_HEIGHT;
@@ -42,6 +43,7 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Handler;
@@ -49,6 +51,9 @@
 import android.provider.Settings;
 import android.util.ArraySet;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 import android.widget.Button;
 import android.widget.TextView;
 
@@ -771,13 +776,15 @@
 
         @Override
         public void performTestAction() {
-            mNotificationManager.cancelAll();
-
-            // but post one more so the tester can actually access the overflow
+            // Make sure one is a bubble
             Notification.Builder builder = getConversationNotif(getTestTitle());
             Notification.BubbleMetadata metadata = getBubbleBuilder().build();
             builder.setBubbleMetadata(metadata);
             mNotificationManager.notify(NOTIFICATION_ID, builder.build());
+
+            // Cancel the others
+            mNotificationManager.cancel(NOTIFICATION_ID + 1);
+            mNotificationManager.cancel(NOTIFICATION_ID + 2);
         }
     }
 
@@ -903,12 +910,24 @@
 
         @Override
         public void performTestAction() {
+            WindowMetrics windowMetrics =
+                    getSystemService(WindowManager.class).getCurrentWindowMetrics();
+            WindowInsets metricInsets = windowMetrics.getWindowInsets();
+            Insets insets = metricInsets.getInsetsIgnoringVisibility(
+                    WindowInsets.Type.navigationBars()
+                            | WindowInsets.Type.statusBars()
+                            | WindowInsets.Type.displayCutout());
+
             mNotificationManager.cancelAll();
             Context context = getApplicationContext();
             Intent intent = new Intent(context, BubbleActivity.class);
-            intent.putExtra(EXTRA_TEST_NAME, TEST_MAX_HEIGHT);
+            Bundle extras = new Bundle();
+            extras.putString(EXTRA_TEST_NAME, TEST_MAX_HEIGHT);
+            // Pass the insets because the bubble'd activity window won't have them.
+            extras.putParcelable(EXTRA_INSETS, insets);
+            intent.putExtras(extras);
             final PendingIntent pendingIntent = PendingIntent.getActivity(context, 2, intent,
-                    PendingIntent.FLAG_MUTABLE);
+                    PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
             Notification.BubbleMetadata.Builder b = new Notification.BubbleMetadata.Builder(
                     pendingIntent,
                     Icon.createWithResource(getApplicationContext(), R.drawable.ic_android));
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java
index 1a9fcd9..b0b6bd5 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/RemoteEventQuerier.java
@@ -147,7 +147,7 @@
     private AtomicReference<IQueryService> mQuery = new AtomicReference<>();
     private CountDownLatch mConnectionCountdown;
 
-    private static final int MAX_INITIALISATION_ATTEMPTS = 100;
+    private static final int MAX_INITIALISATION_ATTEMPTS = 300;
     private static final long INITIALISATION_ATTEMPT_DELAY_MS = 100;
 
     private void ensureInitialised() {
@@ -195,7 +195,9 @@
         intent.setClassName(mPackageName, "com.android.eventlib.QueryService");
 
         AtomicBoolean didBind = new AtomicBoolean(false);
-        if (mEventLogsQuery.getUserHandle() != null) {
+        if (mEventLogsQuery.getUserHandle() != null
+                && mEventLogsQuery.getUserHandle().getIdentifier()
+                != sTestApis.users().instrumented().id()) {
             try (PermissionContext p =
                          sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
                 didBind.set(sContext.bindServiceAsUser(
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
index 5819c39..6a82a27 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
@@ -16,6 +16,8 @@
 
 package com.android.bedstead.harrier;
 
+import android.util.Log;
+
 import androidx.annotation.Nullable;
 
 import com.android.bedstead.harrier.annotations.CalledByHostDrivenTest;
@@ -169,7 +171,6 @@
             } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                 throw new NeneException("Error expanding repeated annotations", e);
             }
-
         }
 
         if (annotation.annotationType().getAnnotation(ParameterizedAnnotation.class) != null
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
index 1b19a50..9049d08 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
@@ -16,6 +16,9 @@
 
 package com.android.bedstead.harrier;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+
+import static com.android.bedstead.nene.permissions.Permissions.NOTIFY_PENDING_SYSTEM_UPDATE;
 import static com.android.bedstead.nene.users.UserType.MANAGED_PROFILE_TYPE_NAME;
 import static com.android.bedstead.nene.users.UserType.SECONDARY_USER_TYPE_NAME;
 import static com.android.bedstead.nene.utils.Versions.meetsSdkVersionRequirements;
@@ -23,6 +26,7 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
@@ -41,6 +45,7 @@
 import com.android.bedstead.harrier.annotations.FailureMode;
 import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature;
 import com.android.bedstead.harrier.annotations.RequireFeature;
+import com.android.bedstead.harrier.annotations.RequireGmsInstrumentation;
 import com.android.bedstead.harrier.annotations.RequirePackageInstalled;
 import com.android.bedstead.harrier.annotations.RequirePackageNotInstalled;
 import com.android.bedstead.harrier.annotations.RequireSdkVersion;
@@ -107,6 +112,8 @@
  */
 public final class DeviceState implements TestRule {
 
+    private static final String GMS_PKG = "com.google.android.gms";
+
     private final Context mContext = ApplicationProvider.getApplicationContext();
     private static final TestApis sTestApis = new TestApis();
     private static final String SKIP_TEST_TEARDOWN_KEY = "skip-test-teardown";
@@ -115,8 +122,14 @@
     private boolean mSkipTestTeardown;
     private boolean mSkipClassTeardown;
     private boolean mSkipTests;
+    private boolean mFailTests;
     private boolean mUsingBedsteadJUnit4 = false;
     private String mSkipTestsReason;
+    private String mFailTestsReason;
+
+    // Marks if the conditions for requiring running under GMS instrumentation have been set
+    // if not - we assume the test should never run under GMS instrumentation
+    private boolean mHasRequireGmsInstrumentation = false;
 
     private static final String TV_PROFILE_TYPE_NAME = "com.android.tv.profile";
 
@@ -155,8 +168,9 @@
                 Log.d(LOG_TAG, "Preparing state for test " + description.getMethodName());
 
                 assumeFalse(mSkipTestsReason, mSkipTests);
+                assertFalse(mFailTestsReason, mFailTests);
 
-                Collection<Annotation> annotations = getAnnotations(description);
+                List<Annotation> annotations = getAnnotations(description);
                 PermissionContextImpl permissionContext = applyAnnotations(annotations);
 
                 Log.d(LOG_TAG,
@@ -183,7 +197,7 @@
             }};
     }
 
-    private PermissionContextImpl applyAnnotations(Collection<Annotation> annotations)
+    private PermissionContextImpl applyAnnotations(List<Annotation> annotations)
             throws Throwable {
         PermissionContextImpl permissionContext = null;
         for (Annotation annotation : annotations) {
@@ -329,6 +343,14 @@
                 continue;
             }
 
+            if (annotation instanceof RequireGmsInstrumentation) {
+                RequireGmsInstrumentation requireGmsInstrumentationAnnotation =
+                        (RequireGmsInstrumentation) annotation;
+                requireGmsInstrumentation(requireGmsInstrumentationAnnotation.min(),
+                        requireGmsInstrumentationAnnotation.max());
+                continue;
+            }
+
             if (annotation instanceof RequireSdkVersion) {
                 RequireSdkVersion requireSdkVersionAnnotation =
                         (RequireSdkVersion) annotation;
@@ -374,6 +396,12 @@
             if (annotation instanceof EnsureHasPermission) {
                 EnsureHasPermission ensureHasPermissionAnnotation =
                         (EnsureHasPermission) annotation;
+
+                for (String permission : ensureHasPermissionAnnotation.value()) {
+                    ensureCanGetPermission(permission);
+                }
+
+
                 try {
                     if (permissionContext == null) {
                         permissionContext = sTestApis.permissions().withPermission(
@@ -409,13 +437,18 @@
             }
         }
 
+        if (!mHasRequireGmsInstrumentation) {
+            // TODO(scottjonathan): Only enforce if we've configured GMS Instrumentation
+            requireNoGmsInstrumentation();
+        }
+
         return permissionContext;
     }
 
-    private Collection<Annotation> getAnnotations(Description description) {
+    private List<Annotation> getAnnotations(Description description) {
         if (mUsingBedsteadJUnit4 && description.isTest()) {
-            // The annotations are already exploded
-            return description.getAnnotations();
+            // The annotations are already exploded for tests
+            return new ArrayList<>(description.getAnnotations());
         }
 
         // Otherwise we should build a new collection by recursively gathering annotations
@@ -457,8 +490,17 @@
             public void evaluate() throws Throwable {
                 Log.d(LOG_TAG, "Preparing state for suite " + description.getMethodName());
 
-                Collection<Annotation> annotations = getAnnotations(description);
-                PermissionContextImpl permissionContext = applyAnnotations(annotations);
+                PermissionContextImpl permissionContext = null;
+                try {
+                    List<Annotation> annotations = getAnnotations(description);
+                    permissionContext = applyAnnotations(annotations);
+                } catch (AssumptionViolatedException e) {
+                    mSkipTests = true;
+                    mSkipTestsReason = e.getMessage();
+                } catch (AssertionError e) {
+                    mFailTests = true;
+                    mFailTestsReason = e.getMessage();
+                }
 
                 Log.d(LOG_TAG,
                         "Finished preparing state for suite " + description.getMethodName());
@@ -524,9 +566,49 @@
                 !sTestApis.packages().features().contains(feature), failureMode);
     }
 
-    private void requireSdkVersion(int min, int max, FailureMode failureMode) {
+    private void requireNoGmsInstrumentation() {
+        boolean instrumentingGms =
+                sTestApis.context().instrumentedContext().getPackageName().equals(GMS_PKG);
+
         checkFailOrSkip(
-                "Sdk version must be between " + min +  " and " + max + " (inclusive)",
+                "This test never runs using gms instrumentation",
+                !instrumentingGms,
+                FailureMode.SKIP
+        );
+    }
+
+    private void requireGmsInstrumentation(int min, int max) {
+        mHasRequireGmsInstrumentation = true;
+        boolean instrumentingGms =
+                sTestApis.context().instrumentedContext().getPackageName().equals(GMS_PKG);
+
+        if (meetsSdkVersionRequirements(min, max)) {
+            checkFailOrSkip(
+                    "For SDK versions between " + min +  " and " + max
+                            + " (inclusive), this test only runs when using gms instrumentation",
+                    instrumentingGms,
+                    FailureMode.SKIP
+            );
+        } else {
+            checkFailOrSkip(
+                    "For SDK versions between " + min +  " and " + max
+                            + " (inclusive), this test only runs when not using gms "
+                            + "instrumentation",
+                    !instrumentingGms,
+                    FailureMode.SKIP
+            );
+        }
+    }
+
+    private void requireSdkVersion(int min, int max, FailureMode failureMode) {
+        requireSdkVersion(min, max, failureMode,
+                "Sdk version must be between " + min +  " and " + max + " (inclusive)");
+    }
+
+    private void requireSdkVersion(
+            int min, int max, FailureMode failureMode, String failureMessage) {
+        checkFailOrSkip(
+                failureMessage,
                 meetsSdkVersionRequirements(min, max),
                 failureMode
         );
@@ -1077,9 +1159,14 @@
     private void ensureHasDeviceOwner(UserType onUser, FailureMode failureMode, boolean isPrimary, Set<String> affiliationIds) {
         // TODO(scottjonathan): Should support non-remotedpc device owner (default to remotedpc)
         // TODO(scottjonathan): Should allow setting the device owner on a different user
-        if (isPrimary && mPrimaryDpc != null) {
+        UserReference userReference = resolveUserTypeToUser(onUser);
+        if (isPrimary && mPrimaryDpc != null && !userReference.equals(mPrimaryDpc.user())) {
             throw new IllegalStateException("Only one DPC can be marked as primary per test (current primary is " + mPrimaryDpc + ")");
         }
+        if (!userReference.equals(sTestApis.users().instrumented())) {
+            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
+        }
 
         DeviceOwner currentDeviceOwner = sTestApis.devicePolicy().getDeviceOwner();
 
@@ -1106,21 +1193,21 @@
             }
 
             // TODO(scottjonathan): Remove accounts
-            ensureHasNoProfileOwner(onUser);
+            ensureHasNoProfileOwner(userReference);
 
             if (!mHasChangedDeviceOwner) {
                 mOriginalDeviceOwner = currentDeviceOwner;
                 mHasChangedDeviceOwner = true;
             }
 
-            mDeviceOwner = RemoteDpc.setAsDeviceOwner(resolveUserTypeToUser(onUser))
+            mDeviceOwner = RemoteDpc.setAsDeviceOwner(userReference)
                     .devicePolicyController();
-
-            if (isPrimary) {
-                mPrimaryDpc = mDeviceOwner;
-            }
         }
 
+        if (isPrimary) {
+            mPrimaryDpc = mDeviceOwner;
+        }
+        
         RemoteDpc.forDevicePolicyController(mDeviceOwner).devicePolicyManager()
                 .setAffiliationIds(affiliationIds);
     }
@@ -1133,10 +1220,15 @@
 
     private void ensureHasProfileOwner(
             UserReference user, boolean isPrimary, Set<String> affiliationIds) {
-        if (isPrimary && mPrimaryDpc != null) {
+        if (isPrimary && mPrimaryDpc != null && !user.equals(mPrimaryDpc.user())) {
             throw new IllegalStateException("Only one DPC can be marked as primary per test");
         }
 
+        if (!user.equals(sTestApis.users().instrumented())) {
+            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
+        }
+
         ProfileOwner currentProfileOwner = sTestApis.devicePolicy().getProfileOwner(user);
         DeviceOwner currentDeviceOwner = sTestApis.devicePolicy().getDeviceOwner();
 
@@ -1146,7 +1238,8 @@
         }
 
         if (currentProfileOwner != null
-                && currentProfileOwner.componentName().equals(RemoteDpc.DPC_COMPONENT_NAME)) {
+                && currentProfileOwner.componentName().equals(
+                RemoteDpc.DPC_COMPONENT_NAME)) {
             mProfileOwners.put(user, currentProfileOwner);
         } else {
             if (!mChangedProfileOwners.containsKey(user)) {
@@ -1161,7 +1254,9 @@
         }
 
         if (affiliationIds != null) {
-            profileOwner(user).devicePolicyManager().setAffiliationIds(affiliationIds);
+            RemoteDpc profileOwner = profileOwner(user);
+            profileOwner.devicePolicyManager()
+                    .setAffiliationIds(affiliationIds);
         }
     }
 
@@ -1361,6 +1456,7 @@
             DevicePolicyController profileOwner =
                     mProfileOwners.get(sTestApis.users().instrumented());
 
+
             if (profileOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
                 return RemoteDpc.forDevicePolicyController(profileOwner);
             }
@@ -1375,4 +1471,18 @@
 
         throw new IllegalStateException("No Harrier-managed profile owner or device owner.");
     }
+
+    private void ensureCanGetPermission(String permission) {
+        // TODO(scottjonathan): Apply gms permission switches automatically rather than hard-coding
+        // TODO(scottjonathan): Add a config to only enforce gms permission when needed
+        if (permission.equals(NOTIFY_PENDING_SYSTEM_UPDATE)) {
+            requireGmsInstrumentation(1, Build.VERSION_CODES.R);
+        }
+        // TODO(scottjonathan): Apply version-specific constraints automatically
+        if (permission.equals(INTERACT_ACROSS_USERS_FULL)) {
+            requireSdkVersion(
+                    Build.VERSION_CODES.Q, Integer.MAX_VALUE, FailureMode.SKIP,
+                    "This test requires INTERACT_ACROSS_USERS_FULL which can only be used on Q+");
+        }
+    }
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
index fa1fd10..6afc119 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
@@ -19,6 +19,7 @@
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeNone;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnAffiliatedDeviceOwnerSecondaryUser;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnAffiliatedProfileOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnDeviceOwnerUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfCorporateOwnedProfileOwner;
@@ -37,6 +38,7 @@
 @IncludeNone
 @IncludeRunOnDeviceOwnerUser
 @IncludeRunOnAffiliatedDeviceOwnerSecondaryUser
+@IncludeRunOnAffiliatedProfileOwnerSecondaryUser
 @IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser
 @IncludeRunOnProfileOwnerProfile
 @IncludeRunOnParentOfCorporateOwnedProfileOwner
@@ -59,6 +61,9 @@
     private static final IncludeRunOnAffiliatedDeviceOwnerSecondaryUser
             INCLUDE_RUN_ON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER =
             Policy.class.getAnnotation(IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.class);
+    private static final IncludeRunOnAffiliatedProfileOwnerSecondaryUser
+            INCLUDE_RUN_ON_AFFILIATED_PROFILE_OWNER_SECONDARY_USER =
+            Policy.class.getAnnotation(IncludeRunOnAffiliatedProfileOwnerSecondaryUser.class);
     private static final IncludeRunOnProfileOwnerProfile
             INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE =
             Policy.class.getAnnotation(IncludeRunOnProfileOwnerProfile.class);
@@ -105,11 +110,11 @@
             case NO:
                 break;
             case AFFILIATED:
-                annotations.add(INCLUDE_RUN_ON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
+                annotations.add(INCLUDE_RUN_ON_AFFILIATED_PROFILE_OWNER_SECONDARY_USER);
                 break;
             case AFFILIATED_OR_NO_DO:
                 annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PRIMARY_USER);
-                annotations.add(INCLUDE_RUN_ON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
+                annotations.add(INCLUDE_RUN_ON_AFFILIATED_PROFILE_OWNER_SECONDARY_USER);
                 break;
             case PARENT:
                 annotations.add(INCLUDE_RUN_ON_PROFILE_OWNER_PROFILE);
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireGmsInstrumentation.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireGmsInstrumentation.java
new file mode 100644
index 0000000..94864c3
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireGmsInstrumentation.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations;
+
+import com.android.bedstead.harrier.DeviceState;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark that a test method should be run using GMS Instrumentation for certain versions.
+ *
+ * <p>This will apply {@link RequireSdkVersion} to ensure that on the given versions, this test
+ * only runs when the instrumented package is `com.google.android.gms`. It will also skip the test
+ * if it is run with gms instrumentation on a version which does not require it.
+ *
+ * <p>This allows for two test configurations to be set up, one which instruments GMS and one
+ * which does not - and both pointed at the same test sources.
+ *
+ * <p>Your test configuration may be configured so that this test is only run on a device with the
+ * given state. Otherwise, you can use {@link DeviceState} to ensure that the test is
+ * not run when the sdk version is not correct.
+ */
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequireGmsInstrumentation {
+    int min() default 1;
+    int max() default Integer.MAX_VALUE;
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java
index 7e7fd39..4b277da 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/RequireSdkVersion.java
@@ -27,7 +27,7 @@
  * Mark that a test method should only run on specified sdk versions.
  *
  * <p>Your test configuration may be configured so that this test is only run on a device with the
- * given user. Otherwise, you can use {@link DeviceState} to ensure that the test is
+ * given version. Otherwise, you can use {@link DeviceState} to ensure that the test is
  * not run when the sdk version is not correct.
  */
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
index ebec893..b8aea09 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
@@ -16,11 +16,8 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
-import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
-
 import static com.android.bedstead.harrier.DeviceState.UserType.SYSTEM_USER;
 
-import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser;
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
new file mode 100644
index 0000000..65f5851
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations.parameterized;
+
+import static com.android.bedstead.harrier.DeviceState.UserType.SYSTEM_USER;
+
+import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
+import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Parameterize a test so that it runs on a affiliated secondary user on a device with a
+ * Device Owner - with the profile owner set as primary.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ParameterizedAnnotation
+@RequireRunOnSecondaryUser
+@EnsureHasDeviceOwner(onUser = SYSTEM_USER, affiliationIds = "affiliated")
+@EnsureHasProfileOwner(affiliationIds = "affiliated", isPrimary = true)
+public @interface IncludeRunOnAffiliatedProfileOwnerSecondaryUser {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
index 2f3adeb..84bf602 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
@@ -16,11 +16,8 @@
 
 package com.android.bedstead.harrier.annotations.parameterized;
 
-import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
-
 import static com.android.bedstead.harrier.DeviceState.UserType.SYSTEM_USER;
 
-import com.android.bedstead.harrier.annotations.RequireFeature;
 import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser;
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
index 0c06d59..7da942a 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
@@ -16,7 +16,7 @@
 
 package com.android.bedstead.harrier.policies;
 
-import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.DeviceOwnerControl.AFFILIATED;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.DeviceOwnerControl.USER;
 import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.ProfileOwnerControl.AFFILIATED_OR_NO_DO;
 
 import android.app.admin.DevicePolicyManager;
@@ -32,6 +32,6 @@
  * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)} and
  * {@link DevicePolicyManager#setLockTaskPackages(ComponentName, String[])}.
  */
-@EnterprisePolicy(deviceOwner = AFFILIATED, profileOwner = AFFILIATED_OR_NO_DO)
+@EnterprisePolicy(deviceOwner = USER, profileOwner = AFFILIATED_OR_NO_DO)
 public final class LockTask {
 }
diff --git a/common/device-side/bedstead/nene/Android.bp b/common/device-side/bedstead/nene/Android.bp
index 53c9637..f329665 100644
--- a/common/device-side/bedstead/nene/Android.bp
+++ b/common/device-side/bedstead/nene/Android.bp
@@ -10,7 +10,8 @@
     ],
     manifest: "src/main/AndroidManifest.xml",
     static_libs: [
-        "compatibility-device-util-axt"
+        "compatibility-device-util-axt",
+        "guava"
     ],
     min_sdk_version: "27"
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java
index da8638a..becd320 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/context/Context.java
@@ -29,7 +29,9 @@
 
     private static final String ANDROID_PACKAGE = "android";
 
-    private static final android.content.Context sContext =
+    private static final android.content.Context sInstrumentedContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final android.content.Context sInstrumentationContext =
             InstrumentationRegistry.getInstrumentation().getContext();
     private final TestApis mTestApis;
 
@@ -41,14 +43,28 @@
      * Get the {@link android.content.Context} for the instrumented test app.
      */
     public android.content.Context instrumentedContext() {
-        return sContext;
+        return sInstrumentedContext;
     }
 
     /**
      * Get the {@link android.content.Context} for the instrumented test app in another user.
      */
     public android.content.Context instrumentedContextAsUser(UserReference user) {
-        return sContext.createContextAsUser(user.userHandle(), /* flags= */ 0);
+        return sInstrumentedContext.createContextAsUser(user.userHandle(), /* flags= */ 0);
+    }
+
+    /**
+     * Get the {@link android.content.Context} for the instrumentation app.
+     */
+    public android.content.Context instrumentationContext() {
+        return sInstrumentationContext;
+    }
+
+    /**
+     * Get the {@link android.content.Context} for the instrumentation app in another user.
+     */
+    public android.content.Context instrumentationContextAsUser(UserReference user) {
+        return sInstrumentationContext.createContextAsUser(user.userHandle(), /* flags= */ 0);
     }
 
     /**
@@ -56,7 +72,7 @@
      */
     public android.content.Context androidContextAsUser(UserReference user) {
         try {
-            return sContext.createPackageContextAsUser(
+            return sInstrumentedContext.createPackageContextAsUser(
                     ANDROID_PACKAGE, /* flags= */ 0, user.userHandle());
         } catch (PackageManager.NameNotFoundException e) {
             throw new NeneException("Could not find android installed in user " + user, e);
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
index fc579df..af75f79 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
@@ -45,6 +45,8 @@
 import com.android.bedstead.nene.utils.Versions;
 import com.android.compatibility.common.util.BlockingBroadcastReceiver;
 
+import com.google.common.io.Files;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -212,14 +214,14 @@
                     + "(Trying to install into user " + resolvedUser + ")");
         }
 
-        BlockingBroadcastReceiver broadcastReceiver = BlockingBroadcastReceiver.create(
-                mTestApis.context().instrumentedContext(), mPackageAddedIntentFilter);
-        broadcastReceiver.register();
+        BlockingBroadcastReceiver broadcastReceiver =
+                registerPackageInstalledBroadcastReceiver(user);
 
         try {
             // Expected output "Success"
             ShellCommand.builderForUser(user, "pm install")
                     .addOperand("-r") // Reinstall automatically
+                    .addOperand("-t") // Allow test-only install
                     .addOperand(apkFile.getAbsolutePath())
                     .validate(ShellCommandUtils::startsWithSuccess)
                     .execute();
@@ -242,6 +244,7 @@
         // TODO(scottjonathan): Could this be flaky? what if something is added elsewhere at
         //  the same time...
         String installedPackageName = intent.getDataString().split(":", 2)[1];
+
         return mTestApis.packages().find(installedPackageName);
     }
 
@@ -268,9 +271,35 @@
             throw new NullPointerException();
         }
 
-        //        if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
-        return installPreS(user, apkFile);
-//        }
+        if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
+            return installPreS(user, apkFile);
+        }
+
+        User resolvedUser = user.resolve();
+
+        if (resolvedUser == null || resolvedUser.state() != RUNNING_UNLOCKED) {
+            throw new NeneException("Packages can not be installed in non-started users "
+                    + "(Trying to install into user " + resolvedUser + ")");
+        }
+
+        BlockingBroadcastReceiver broadcastReceiver =
+                registerPackageInstalledBroadcastReceiver(user);
+        try {
+            // Expected output "Success"
+            ShellCommand.builderForUser(user, "pm install")
+                    .addOption("-S", apkFile.length)
+                    .addOperand("-r")
+                    .addOperand("-t")
+                    .writeToStdIn(apkFile)
+                    .validate(ShellCommandUtils::startsWithSuccess)
+                    .execute();
+
+            return waitForPackageAddedBroadcast(broadcastReceiver);
+        } catch (AdbException e) {
+            throw new NeneException("Could not install from bytes for user " + user, e);
+        } finally {
+            broadcastReceiver.unregisterQuietly();
+        }
 
         // TODO(scottjonathan): Re-enable this after we have a TestAPI which allows us to install
         //   testOnly apks
@@ -328,30 +357,20 @@
     }
 
     private PackageReference installPreS(UserReference user, byte[] apkFile) {
-        User resolvedUser = user.resolve();
-
-        if (resolvedUser == null || resolvedUser.state() != RUNNING_UNLOCKED) {
-            throw new NeneException("Packages can not be installed in non-started users "
-                    + "(Trying to install into user " + resolvedUser + ")");
-        }
-
-        BlockingBroadcastReceiver broadcastReceiver =
-                registerPackageInstalledBroadcastReceiver(user);
+        // Prior to S we cannot pass bytes to stdin so we write it to a temp file first
+        File outputDir = mTestApis.context().instrumentedContext().getCacheDir();
+        File outputFile = null;
         try {
-            // Expected output "Success"
-            ShellCommand.builderForUser(user, "pm install")
-                    .addOption("-S", apkFile.length)
-                    .addOperand("-r")
-                    .addOperand("-t")
-                    .writeToStdIn(apkFile)
-                    .validate(ShellCommandUtils::startsWithSuccess)
-                    .execute();
-
-            return waitForPackageAddedBroadcast(broadcastReceiver);
-        } catch (AdbException e) {
-            throw new NeneException("Could not install from bytes for user " + user, e);
+            outputFile = File.createTempFile("tmp", ".apk", outputDir);
+            Files.write(apkFile, outputFile);
+            outputFile.setReadable(true, false);
+            return install(user, outputFile);
+        } catch (IOException e) {
+            throw new NeneException("Error when writing bytes to temp file", e);
         } finally {
-            broadcastReceiver.unregisterQuietly();
+            if (outputFile != null) {
+                outputFile.delete();
+            }
         }
     }
 
@@ -402,9 +421,15 @@
                 mTestApis.context().androidContextAsUser(user),
                 mPackageAddedIntentFilter);
 
-        try (PermissionContext p =
-                    mTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+        if (user.equals(mTestApis.users().instrumented())) {
             broadcastReceiver.register();
+        } else {
+            // TODO(scottjonathan): If this is cross-user then it needs _FULL, but older versions
+            //  cannot get full - so we'll need to poll
+            try (PermissionContext p =
+                         mTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+                broadcastReceiver.register();
+            }
         }
 
         return broadcastReceiver;
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java
index 613e3c2..1aedf44 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/permissions/Permissions.java
@@ -16,6 +16,8 @@
 
 package com.android.bedstead.nene.permissions;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -164,7 +166,11 @@
             Log.d(LOG_TAG , "Trying to grant " + permission);
             if (resolvedInstrumentedPackage.grantedPermissions(sUser).contains(permission)) {
                 // Already granted, can skip
-                Log.d(LOG_TAG, permission + " already granted");
+                Log.d(LOG_TAG, permission + " already granted at runtime");
+            } else if (resolvedInstrumentedPackage.requestedPermissions().contains(permission)
+                    && sContext.checkSelfPermission(permission) == PERMISSION_GRANTED) {
+                // Already granted, can skip
+                Log.d(LOG_TAG, permission + " already granted from manifest");
             } else if (SUPPORTS_ADOPT_SHELL_PERMISSIONS
                     && sShellPackage.requestedPermissions().contains(permission)) {
                 adoptedShellPermissions.add(permission);
diff --git a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java
index 3e8c781..792776d 100644
--- a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java
+++ b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/RemoteDpc.java
@@ -45,7 +45,8 @@
 public final class RemoteDpc {
 
     private static final TestApis sTestApis = new TestApis();
-    private static final Context sContext = sTestApis.context().instrumentedContext();
+    // This must be instrumentation not instrumented to access the resources
+    private static final Context sContext = sTestApis.context().instrumentationContext();
 
     public static final ComponentName DPC_COMPONENT_NAME = REMOTE_DPC_COMPONENT_NAME;
 
diff --git a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java
index 5be913f..3d31394 100644
--- a/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java
+++ b/common/device-side/bedstead/remotedpc/src/library/main/java/com/android/bedstead/remotedpc/connected/RemoteDPCBinder.java
@@ -60,16 +60,28 @@
 
         Log.i(LOG_TAG, "Attempting to bind to " + bindIntent);
 
-        try (PermissionContext p =
-                     sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
-            return context.bindServiceAsUser(bindIntent,
-                    connection, /* flags= */ BIND_AUTO_CREATE,
-                    mRemoteDpc.devicePolicyController().user().userHandle());
-        } catch (Exception e) {
-            // TODO(scottjonathan): This should actually be communicated back...
-            //  (catch the exception outside of the tryBind call)
-            Log.e(LOG_TAG, "Error binding", e);
-            return false;
+        if (mRemoteDpc.devicePolicyController().user().equals(sTestApis.users().instrumented())) {
+            try {
+                return context.bindService(bindIntent,
+                        connection, /* flags= */ BIND_AUTO_CREATE);
+            } catch (Exception e) {
+                // TODO(scottjonathan): This should actually be communicated back...
+                //  (catch the exception outside of the tryBind call)
+                Log.e(LOG_TAG, "Error binding", e);
+                return false;
+            }
+        } else {
+            try (PermissionContext p =
+                         sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+                return context.bindServiceAsUser(bindIntent,
+                        connection, /* flags= */ BIND_AUTO_CREATE,
+                        mRemoteDpc.devicePolicyController().user().userHandle());
+            } catch (Exception e) {
+                // TODO(scottjonathan): This should actually be communicated back...
+                //  (catch the exception outside of the tryBind call)
+                Log.e(LOG_TAG, "Error binding", e);
+                return false;
+            }
         }
     }
 
diff --git a/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java b/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java
index 1febeb6..3277580 100644
--- a/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java
+++ b/common/device-side/bedstead/remotedpc/src/processor/main/java/com/android/bedstead/remotedpc/processor/Processor.java
@@ -218,7 +218,7 @@
                 MethodSpec.methodBuilder("tryConnect")
                         .addModifiers(Modifier.PRIVATE)
                         .addException(UNAVAILABLE_PROFILE_EXCEPTION_CLASSNAME)
-                        .addCode("$T retries = 50;", int.class)
+                        .addCode("$T retries = 300;", int.class)
                         .beginControlFlow("while (true)")
                             .beginControlFlow("try")
                                 .addCode("mConnector.connect();")
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java
index 771625c..7a4c309 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestApp.java
@@ -38,7 +38,8 @@
 public class TestApp {
 
     private static final TestApis sTestApis = new TestApis();
-    private static final Context sContext = sTestApis.context().instrumentedContext();
+    // Must be instrumentation context to access resources
+    private static final Context sContext = sTestApis.context().instrumentationContext();
     private final TestAppDetails mDetails;
 
     TestApp(TestAppDetails details) {
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java
index 958bffc..b520263 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppActivityReference.java
@@ -16,6 +16,7 @@
 
 package com.android.bedstead.testapp;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
@@ -26,6 +27,7 @@
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.activities.ActivityReference;
 import com.android.bedstead.nene.packages.ComponentReference;
+import com.android.bedstead.nene.permissions.PermissionContext;
 import com.android.eventlib.events.activities.ActivityCreatedEvent;
 import com.android.eventlib.events.activities.ActivityStartedEvent;
 
@@ -60,10 +62,15 @@
      * Starts the activity.
      */
     public com.android.bedstead.nene.activities.Activity<TestAppActivity> start() {
+        // TODO(scottjonathan): Use a connected call to ensure this succeeds cross-user
         Intent intent = new Intent();
         intent.setComponent(mComponent.componentName());
         intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
-        sTestApis.context().instrumentedContext().startActivity(intent);
+
+        try (PermissionContext p =
+                     sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+            sTestApis.context().instrumentedContext().startActivity(intent);
+        }
 
         ActivityStartedEvent
                 .queryPackage(mComponent.packageName().packageName())
@@ -77,10 +84,14 @@
      * Starts the activity.
      */
     public com.android.bedstead.nene.activities.Activity<TestAppActivity> start(Bundle options) {
+        // TODO(scottjonathan): Use a connected call to ensure this succeeds cross-user
         Intent intent = new Intent();
         intent.setComponent(mComponent.componentName());
         intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
-        sTestApis.context().instrumentedContext().startActivity(intent, options);
+        try (PermissionContext p =
+                     sTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+            sTestApis.context().instrumentedContext().startActivity(intent, options);
+        }
 
         ActivityCreatedEvent
                 .queryPackage(mComponent.packageName().packageName())
diff --git a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java
index c6e6789..2ef6ae8 100644
--- a/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java
+++ b/common/device-side/bedstead/testapp/src/main/library/java/com/android/bedstead/testapp/TestAppProvider.java
@@ -31,7 +31,8 @@
 public final class TestAppProvider {
 
     private static final TestApis sTestApis = new TestApis();
-    private static final Context sContext = sTestApis.context().instrumentedContext();
+    // Must be instrumentation context to access resources
+    private static final Context sContext = sTestApis.context().instrumentationContext();
 
     private boolean mTestAppsInitialised = false;
     private final Set<TestAppDetails> mTestApps = new HashSet<>();
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
new file mode 100644
index 0000000..40616fb
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import android.content.Context;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiDeviceInfo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+public class DisplayUtil {
+
+    /**
+     * Returns if a physical display is connected to DUT. The method may return a false positive,
+     * but no false negative.
+     */
+    public static boolean isDisplayConnected(Context context) throws Exception {
+        // DisplayManager will return a display even if there is no connected display.
+        // For that reason we use HdmiControlManager to check if there's something connected
+        // to the HDMI port.
+        HdmiControlManager cecManager = context.getSystemService(HdmiControlManager.class);
+
+        if (cecManager == null) {
+            // CEC is not available. Can't do anything more, so assume that there is a display.
+            return true;
+        }
+
+        if (cecManager.getPlaybackClient() == null) {
+            // The device is not HDMI playback device (e.g. set-top box), so we assume it has
+            // a built-in display.
+            return true;
+        }
+
+        CountDownLatch notifyLatch = new CountDownLatch(1);
+        cecManager.addHotplugEventListener(event -> {
+            // TODO(b/189837682): Check if the port is HDMI out
+            if (event.isConnected()) {
+                notifyLatch.countDown();
+            }
+        });
+
+        return notifyLatch.await(3, TimeUnit.SECONDS);
+    }
+}
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
index 1764cab..33ccf39 100644
--- a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
+++ b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
@@ -83,14 +83,6 @@
     }
 
     @Test
-    public void testCreateSessionInStoppedUser() throws Exception {
-        Map<String, String> args =
-                Collections.singletonMap(USER_ID_KEY, String.valueOf(mSecondaryUserId));
-        getDevice().stopUser(mSecondaryUserId, /*waitFlag=*/true, /*forceFlag=*/true);
-        runDeviceTestAsUserInPkgA("createSessionInStoppedUser", mInitialUserId, args);
-    }
-
-    @Test
     public void testStopUser_persistData() throws Exception {
         runDeviceTestAsUserInPkgA("testPutDocuments", mSecondaryUserId);
         runDeviceTestAsUserInPkgA("testGetDocuments_exist", mSecondaryUserId);
diff --git a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java
index b0e0f82..b1f2293 100644
--- a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java
+++ b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java
@@ -137,21 +137,4 @@
     public void clearTestData() throws Exception {
         mDb.setSchema(new SetSchemaRequest.Builder().setForceOverride(true).build()).get();
     }
-
-    @Test
-    public void createSessionInStoppedUser() {
-        mUiAutomation.adoptShellPermissionIdentity(
-                "android.permission.INTERACT_ACROSS_USERS_FULL");
-        try {
-            Bundle args = InstrumentationRegistry.getArguments();
-            int userId = Integer.parseInt(args.getString(USER_ID_KEY));
-            ExecutionException exception = expectThrows(ExecutionException.class, () ->
-                    AppSearchSessionShimImpl.createSearchSession(
-                            new AppSearchManager.SearchContext.Builder(DB_NAME).build(),
-                            userId).get());
-            assertThat(exception.getMessage()).contains("is locked or not running.");
-        } finally {
-            mUiAutomation.dropShellPermissionIdentity();
-        }
-    }
 }
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index 8d5fdf8..b25edb2 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -68,3 +68,8 @@
     name: "CtsHostsideTestsAppSecurityUtil",
     srcs: ["src/android/appsecurity/cts/Utils.java"],
 }
+
+filegroup {
+    name: "cts-ec-p256-por_1_2-default-caps.lineage",
+    srcs: ["certs/pkgsigverify/ec-p256-por_1_2-default-caps"],
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index ebad33c..b26416a 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -19,6 +19,7 @@
 import android.platform.test.annotations.SecurityTest;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.ApiLevelUtil;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
 
@@ -130,37 +131,47 @@
 
     public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
         if (isAtLeastR() && isSupportedHardware()) {
-            runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
+            runDeviceCompatTestReported(CLIENT_PKG, ".DocumentsClientTest",
                 "testRestrictStorageAccessFrameworkEnabled_blockFromTree",
-                /* enabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
-                /* disabledChanges */ ImmutableSet.of());
+                /* enabledChanges= */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
+                /* disabledChanges= */ ImmutableSet.of(),
+                /* reportedEnabledChanges= */ ImmutableSet.of(),
+                /* reportedDisabledChanges= */ ImmutableSet.of());
         }
     }
 
     public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
-        if (isAtLeastR() && isSupportedHardware()) {
-            runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
+        // For S+, the flag will be force enabled, so we only run this test against R.
+        if (isAtLeastR() && !isAtLeastS() && isSupportedHardware()) {
+            runDeviceCompatTestReported(CLIENT_PKG, ".DocumentsClientTest",
                 "testRestrictStorageAccessFrameworkDisabled_notBlockFromTree",
                 /* enabledChanges */ ImmutableSet.of(),
-                /* disabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK));
+                /* disabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
+                /* reportedEnabledChanges= */ ImmutableSet.of(),
+                /* reportedDisabledChanges= */ ImmutableSet.of());
         }
     }
 
     @SecurityTest
     public void testAfterMoveDocumentInStorage_revokeUriPermission() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
+        if (isAtLeastS()) {
+            runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
                 "testAfterMoveDocumentInStorage_revokeUriPermission");
-
+        }
     }
 
     private boolean isAtLeastR() {
         try {
-            String apiString = getDevice().getProperty("ro.build.version.sdk");
-            if (apiString == null) {
-                return false;
-            }
-            int apiLevel = Integer.parseInt(apiString);
-            return apiLevel > 29;
+            return ApiLevelUtil.isAfter(getDevice(), 29 /* BUILD.VERSION_CODES.Q */);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    private boolean isAtLeastS() {
+        try {
+            return ApiLevelUtil.isAfter(getDevice(), 30 /* BUILD.VERSION_CODES.R */)
+                || ApiLevelUtil.codenameEquals(getDevice(), "S");
         } catch (Exception e) {
             return false;
         }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 8568a97..c1c2f5c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -1291,7 +1291,6 @@
                 "signatures do not match previously installed version");
     }
 
-
     public void testV4IncToV2NonIncSameKeyUpgradeSucceeds() throws Exception {
         // V4 is only enabled on devices with Incremental feature
         if (!hasIncrementalFeature()) {
@@ -1321,6 +1320,42 @@
                 "signatures do not match previously installed version");
     }
 
+    public void testInstallV4UpdateAfterRotation() throws Exception {
+        // This test performs an end to end verification of the update of an app with a rotated
+        // key. The app under test exports a bound service that performs its own PackageManager key
+        // rotation API verification, and the instrumentation test binds to the service and invokes
+        // the verifySignatures method to verify that the key rotation APIs return the expected
+        // results. The instrumentation test app is signed with the same key and lineage as the
+        // app under test to also provide a second app that can be used for the checkSignatures
+        // verification.
+
+        // Install the initial versions of the apps; the test method verifies the app under test is
+        // signed with the original signing key.
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk");
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk");
+        Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS,
+                "verifySignatures_noRotation_succeeds");
+
+        // Install the second version of the app signed with the rotated key. This test verifies the
+        // app still functions as expected after the update with the rotated key. The
+        // instrumentation test app is not updated here to allow verification of the pre-key
+        // rotation behavior for the checkSignatures APIs. These APIs should behave similar to the
+        // GET_SIGNATURES flag in that if one or both apps have a signing lineage if the oldest
+        // signers in the lineage match then the methods should return that the signatures match
+        // even if one is signed with a newer key in the lineage.
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v2.apk");
+        Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS,
+                "verifySignatures_withRotation_succeeds");
+
+        // Installs the third version of the app under test and the instrumentation test, both
+        // signed with the same rotated key and lineage. This test is intended to verify that the
+        // app can still be updated and function as expected after an update with a rotated key.
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v3.apk");
+        assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest_v2.apk");
+        Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS,
+                "verifySignatures_withRotation_succeeds");
+    }
+
     private boolean hasIncrementalFeature() throws Exception {
         return "true\n".equals(getDevice().executeShellCommand(
                 "pm has-feature android.software.incremental_delivery"));
@@ -1365,6 +1400,13 @@
         }
     }
 
+    private void assertInstallV4FromBuildSucceeds(String apkName) throws Exception {
+        String installResult = installV4PackageFromBuild(apkName);
+        if (!installResult.equals("Success\n")) {
+            fail("Failed to install " + apkName + ": " + installResult);
+        }
+    }
+
     private void assertInstallV4SucceedsAndUninstall(String apkFilenameInResources)
             throws Exception {
         assertInstallV4Succeeds(apkFilenameInResources);
@@ -1488,6 +1530,23 @@
         }
     }
 
+    private String installV4PackageFromBuild(String apkName)
+            throws IOException, DeviceNotAvailableException {
+        File apkFile = null;
+        File v4SignatureFile = null;
+        try {
+            CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+            apkFile = buildHelper.getTestFile(apkName);
+            v4SignatureFile = buildHelper.getTestFile(apkName + ".idsig");
+            String remoteApkFilePath = pushFileToRemote(apkFile);
+            pushFileToRemote(v4SignatureFile);
+            return installV4Package(remoteApkFilePath);
+        } finally {
+            cleanUpFile(apkFile);
+            cleanUpFile(v4SignatureFile);
+        }
+    }
+
     private String pushFileToRemote(File localFile) throws DeviceNotAvailableException {
         String remotePath = "/data/local/tmp/pkginstalltest-" + localFile.getName();
         getDevice().pushFile(localFile, remotePath);
@@ -1496,7 +1555,7 @@
 
     private String installV4Package(String remoteApkPath)
             throws DeviceNotAvailableException {
-        String command = "pm install-incremental -t -g " + remoteApkPath;
+        String command = "pm install-incremental --force-queryable -t -g " + remoteApkPath;
         return getDevice().executeShellCommand(command);
     }
 
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.bp b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.bp
new file mode 100644
index 0000000..3b7100d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.bp
@@ -0,0 +1,80 @@
+//
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+    name: "cts_signature_query_service",
+
+    srcs: ["src/**/*.java"] + ["src/**/I*.aidl"],
+    sdk_version: "current",
+}
+
+// This is the first version of the test app signed with the initial signing
+// key. This app exports the bound service from the cts_signature_query_service
+// library and is used to verify end to end updates with key rotation.
+android_test {
+    name: "CtsSignatureQueryService",
+    defaults: ["cts_support_defaults"],
+    sdk_version: "current",
+    static_libs: ["cts_signature_query_service"],
+    certificate: ":cts-ec-p256",
+    v4_signature: true,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
+
+// This is the second version of the test app signed with the rotated signing
+// key with an updated version number. This app is intended to verify that an
+// app continues to function as expected after an update with a rotated key.
+android_test {
+    name: "CtsSignatureQueryService_v2",
+    defaults: ["cts_support_defaults"],
+    manifest: "AndroidManifest_v2.xml",
+    sdk_version: "current",
+    static_libs: ["cts_signature_query_service"],
+    certificate: ":cts-ec-p256_2",
+    additional_certificates: [":cts-ec-p256"],
+    lineage: ":cts-ec-p256-por_1_2-default-caps.lineage",
+    v4_signature: true,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
+
+// This is the third version of the test app signed with the same rotated
+// signing key as v2. This app is intended to verify that an app can still
+// be updated and function as expected after the signing key has been rotated.
+android_test {
+    name: "CtsSignatureQueryService_v3",
+    defaults: ["cts_support_defaults"],
+    manifest: "AndroidManifest_v3.xml",
+    sdk_version: "current",
+    static_libs: ["cts_signature_query_service"],
+    certificate: ":cts-ec-p256_2",
+    additional_certificates: [":cts-ec-p256"],
+    lineage: ":cts-ec-p256-por_1_2-default-caps.lineage",
+    v4_signature: true,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk b/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk
deleted file mode 100644
index c453d7a..0000000
--- a/hostsidetests/appsecurity/test-apps/KeyRotationTest/Android.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-cert_dir := cts/hostsidetests/appsecurity/certs/pkgsigverify
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := cts_signature_query_service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += $(call all-Iaidl-files-under, src)
-LOCAL_SDK_VERSION := current
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# This is the first version of the test app signed with the initial signing
-# key. This app exports the bound service from the cts_signature_query_service
-# library and is used to verify end to end updates with key rotation.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryService
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-# This is the second version of the test app signed with the rotated signing
-# key with an updated version number. This app is intended to verify that an
-# app continues to function as expected after an update with a rotated key.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryService_v2
-LOCAL_MANIFEST_FILE = AndroidManifest_v2.xml
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
-LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
-LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-default-caps
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-# This is the third version of the test app signed with the same rotated
-# signing key as v2. This app is intended to verify that an app can still
-# be updated and function as expected after the signing key has been rotated.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryService_v3
-LOCAL_MANIFEST_FILE = AndroidManifest_v3.xml
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
-LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
-LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-default-caps
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-cert_dir :=
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.bp b/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.bp
new file mode 100644
index 0000000..f0ba6a9
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.bp
@@ -0,0 +1,84 @@
+//
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// This is the instrumentation test package for the CtsSignatureQueryService
+// app. This app verifies that the standalone app is functioning as expected
+// after a key rotation and provides a companion package that can be used for
+// the PackageManager checkSignatures APIs.
+android_test {
+    name: "CtsSignatureQueryServiceTest",
+    defaults: ["cts_support_defaults"],
+
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "cts_signature_query_service",
+        "androidx.test.core",
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    certificate: ":cts-ec-p256",
+    v4_signature: true,
+    // Disable dexpreopt and <uses-library> check for test.
+    enforce_uses_libs: false,
+    dex_preopt: {
+        enabled: false,
+    },
+}
+
+// This is the instrumentation test package signed with the same signing key and
+// lineage as v2 and v3 of the CtsSignatureQueryService test app.
+android_test {
+    name: "CtsSignatureQueryServiceTest_v2",
+    defaults: ["cts_support_defaults"],
+
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "cts_signature_query_service",
+        "androidx.test.core",
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    certificate: ":cts-ec-p256_2",
+    additional_certificates: [":cts-ec-p256"],
+    lineage: ":cts-ec-p256-por_1_2-default-caps.lineage",
+    v4_signature: true,
+
+    // Disable dexpreopt and <uses-library> check for test.
+    enforce_uses_libs: false,
+    dex_preopt: {
+        enabled: false,
+    },
+}
diff --git a/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.mk b/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.mk
deleted file mode 100644
index 12c1370..0000000
--- a/hostsidetests/appsecurity/test-apps/KeyRotationTest/ServiceTest/Android.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-cert_dir := cts/hostsidetests/appsecurity/certs/pkgsigverify
-
-# This is the instrumentation test package for the CtsSignatureQueryService
-# app. This app verifies that the standalone app is functioning as expected
-# after a key rotation and provides a companion package that can be used for
-# the PackageManager checkSignatures APIs.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryServiceTest
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service androidx.test.core androidx.test.rules
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256
-# Disable dexpreopt and <uses-library> check for test.
-LOCAL_ENFORCE_USES_LIBRARIES := false
-LOCAL_DEX_PREOPT := false
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-# This is the instrumentation test package signed with the same signing key and
-# lineage as v2 and v3 of the CtsSignatureQueryService test app.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsSignatureQueryServiceTest_v2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := cts_signature_query_service androidx.test.core androidx.test.rules
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_COMPATIBILITY_SUITE := cts general-tests
-LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
-LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
-LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-default-caps
-# Disable dexpreopt and <uses-library> check for test.
-LOCAL_ENFORCE_USES_LIBRARIES := false
-LOCAL_DEX_PREOPT := false
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-cert_dir :=
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
index 25c3a05..5c8aaa5 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
index dda3f28..3cb1a4b 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
index b621cce..3bfa2bb 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk
index c8f9be2..0c69d99 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk
Binary files differ
diff --git a/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java b/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
index 6bbaea8..787ded8 100644
--- a/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
+++ b/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
@@ -148,7 +148,6 @@
      * Restore packages added to mRestorePackages and verify only those packages are restored. Use
      * {@link RestoreSession#restorePackage(String, RestoreObserver)}
      */
-
     @Test
     public void testRestorePackage() throws InterruptedException {
         initPackagesToRestore(/* packagesCount */ 1);
diff --git a/hostsidetests/backup/restoresessionapp1/Android.bp b/hostsidetests/backup/restoresessionapp1/Android.bp
index e2071f3..5706063 100644
--- a/hostsidetests/backup/restoresessionapp1/Android.bp
+++ b/hostsidetests/backup/restoresessionapp1/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "src/**/*.java"
     ],
+    v4_signature: true,
     // tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/hostsidetests/backup/restoresessionapp2/Android.bp b/hostsidetests/backup/restoresessionapp2/Android.bp
index eb82929..a724468 100644
--- a/hostsidetests/backup/restoresessionapp2/Android.bp
+++ b/hostsidetests/backup/restoresessionapp2/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "src/**/*.java"
     ],
+    v4_signature: true,
     // tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/hostsidetests/backup/restoresessionapp3/Android.bp b/hostsidetests/backup/restoresessionapp3/Android.bp
index 16a5aff..c150e3c 100644
--- a/hostsidetests/backup/restoresessionapp3/Android.bp
+++ b/hostsidetests/backup/restoresessionapp3/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "src/**/*.java"
     ],
+    v4_signature: true,
     // tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java
index 95d3b9a..53e1ef4 100644
--- a/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java
+++ b/hostsidetests/backup/src/android/cts/backup/RestoreSessionHostSideTest.java
@@ -17,27 +17,39 @@
 package android.cts.backup;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.AppModeFull;
 
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.util.BackupUtils;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.DeviceParameterizedRunner;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.RunUtil;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
 
+import junitparams.Parameters;
+
 /**
  * Tests for system APIs in {@link RestoreSession}
  *
  * <p>These tests use the local transport.
  */
-@RunWith(DeviceJUnit4ClassRunner.class)
+@RunWith(DeviceParameterizedRunner.class)
 @AppModeFull
 public class RestoreSessionHostSideTest extends BaseBackupHostSideTest {
     private static final int USER_SYSTEM = 0;
@@ -53,6 +65,14 @@
     private Optional<String> mOldTransport = Optional.empty();
     private BackupUtils mBackupUtils;
 
+    private static final boolean INCREMENTAL = true;
+    private static final boolean NON_INCREMENTAL = false;
+
+    private static final Object[] bothInstallTypes() {
+        // Non-Incremental and Incremental.
+        return new Boolean[][]{{NON_INCREMENTAL}, {INCREMENTAL}};
+    }
+
     /** Switch to local transport. */
     @Before
     public void setUp() throws Exception {
@@ -74,32 +94,38 @@
 
     /** Test {@link RestoreSession#restorePackage(RestoreObserver, String)} */
     @Test
-    public void testRestorePackage() throws Exception {
-        testRestorePackagesInternal("testRestorePackage", /* packagesToRestore */ 1);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackage(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackage", /* packagesToRestore */
+                1, /* incremental */incremental);
     }
 
     /**
      * Test {@link RestoreSession#restorePackage(RestoreObserver, String, BackupManagerMonitor)}
      */
     @Test
-    public void testRestorePackageWithMonitorParam() throws Exception {
-        testRestorePackagesInternal("testRestorePackageWithMonitorParam",
-                /* packagesToRestore */ 1);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackageWithMonitorParam(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackageWithMonitorParam", /* packagesToRestore */
+                1, /* incremental */incremental);
     }
 
     /** Test {@link RestoreSession#restorePackages(long, RestoreObserver, Set)} */
     @Test
-    public void testRestorePackages() throws Exception {
-        testRestorePackagesInternal("testRestorePackages", /* packagesToRestore */ 2);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackages(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackages", /* packagesToRestore */
+                2, /* incremental */incremental);
     }
 
     /**
      * Test {@link RestoreSession#restorePackages(long, RestoreObserver, Set, BackupManagerMonitor)}
      */
     @Test
-    public void testRestorePackagesWithMonitorParam() throws Exception {
-        testRestorePackagesInternal("testRestorePackagesWithMonitorParam",
-                /* packagesToRestore */ 2);
+    @Parameters(method = "bothInstallTypes")
+    public void testRestorePackagesWithMonitorParam(boolean incremental) throws Exception {
+        testRestorePackagesInternal("testRestorePackagesWithMonitorParam", /* packagesToRestore */
+                2, /* incremental */incremental);
     }
 
     /**
@@ -114,11 +140,11 @@
      *   <li>Verify that shared preferences for the restored packages are restored correctly
      * </ol>
      */
-    private void testRestorePackagesInternal(String deviceTestName, int numPackagesToRestore)
-            throws Exception {
-        installPackage(getApkNameForTestApp(1));
-        installPackage(getApkNameForTestApp(2));
-        installPackage(getApkNameForTestApp(3));
+    private void testRestorePackagesInternal(String deviceTestName, int numPackagesToRestore,
+            boolean incremental) throws Exception {
+        installPackage(getApkNameForTestApp(1), incremental);
+        installPackage(getApkNameForTestApp(2), incremental);
+        installPackage(getApkNameForTestApp(3), incremental);
 
         // Write test values to shared preferences for all test packages.
         checkRestoreSessionDeviceTestForAllApps("testSaveValuesToSharedPrefs");
@@ -185,4 +211,45 @@
     private String setBackupTransport(String transport) throws IOException {
         return mBackupUtils.setBackupTransportForUser(transport, USER_SYSTEM);
     }
+
+    private void installPackage(String apkFileName, boolean incremental) throws Exception {
+        if (!incremental) {
+            super.installPackage(apkFileName);
+            return;
+        }
+
+        assumeTrue(hasIncrementalFeature());
+        String result = installWithAdb(apkFileName);
+        assumeTrue(result, !result.contains("Unknown option --incremental"));
+        assertTrue(result, result.contains("Success"));
+    }
+
+    private String installWithAdb(String apkFileName) throws Exception {
+        final long DEFAULT_TEST_TIMEOUT_MS = 60 * 1000L;
+
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
+
+        List<String> adbCmd = new ArrayList<>();
+        adbCmd.add("adb");
+        adbCmd.add("-s");
+        adbCmd.add(getDevice().getSerialNumber());
+        adbCmd.add("install");
+        adbCmd.add("--incremental");
+        adbCmd.add(buildHelper.getTestFile(apkFileName).getAbsolutePath());
+
+        // Using runUtil instead of executeAdbCommand() because the latter doesn't provide the
+        // option to get stderr or redirect stderr to stdout.
+        File outFile = FileUtil.createTempFile("stdoutredirect", ".txt");
+        OutputStream stdout = new FileOutputStream(outFile);
+        RunUtil runUtil = new RunUtil();
+        runUtil.setRedirectStderrToStdout(true);
+        runUtil.runTimedCmd(DEFAULT_TEST_TIMEOUT_MS, stdout, /* stderr= */ null,
+                adbCmd.toArray(new String[adbCmd.size()]));
+        return FileUtil.readStringFromFile(outFile);
+    }
+
+    private boolean hasIncrementalFeature() throws Exception {
+        return "true\n".equals(getDevice().executeShellCommand(
+                "pm has-feature android.software.incremental_delivery"));
+    }
 }
diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
index fe94c46..e511337 100644
--- a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
@@ -34,6 +34,7 @@
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.After;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -68,6 +69,10 @@
         String teststep;
         PowerPolicyTestHelper testHelper;
 
+        SilentModeInfo smInfo = getSilentModeInfo();
+        Assume.assumeTrue("HW does not support silent mode. Skip the test",
+                smInfo.getMonitoringHWStateSignal());
+
         teststep = "switch to forced silent";
         enterForcedSilentMode();
         testHelper = getTestHelper(testcase, 1, teststep);
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
index 9dba80b..5a3e46f 100644
--- a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
@@ -16,7 +16,7 @@
 
 package android.car.cts.powerpolicy;
 
-import java.util.Arrays;
+import java.util.Objects;
 
 public final class SilentModeInfo {
     private static final String[] ATTR_HEADERS = {"Monitoring HW state signal",
@@ -27,21 +27,22 @@
     public static final SilentModeInfo NO_SILENT = new SilentModeInfo(true, false, false);
     public static final SilentModeInfo FORCED_SILENT = new SilentModeInfo(false, true, true);
 
-    private final boolean[] mAttrs;
+    private final boolean mForcedSilentMode;
+    private final boolean mMonitoringHWStateSignal;
+    private final boolean mSilentModeByHWStateSignal;
 
     private SilentModeInfo(boolean monitoring, boolean byHW, boolean forced) {
-        mAttrs = new boolean[] {monitoring, byHW, forced};
-    }
-
-    private SilentModeInfo(boolean[] attrs) throws Exception {
-        if (attrs.length != NUMBER_OF_ATTRS) {
-            throw new IllegalArgumentException("attrs.length must be 3");
-        }
-        mAttrs = attrs;
+        mMonitoringHWStateSignal = monitoring;
+        mSilentModeByHWStateSignal = byHW;
+        mForcedSilentMode = forced;
     }
 
     public boolean getForcedSilentMode() {
-        return mAttrs[2];
+        return mForcedSilentMode;
+    }
+
+    public boolean getMonitoringHWStateSignal() {
+        return mMonitoringHWStateSignal;
     }
 
     @Override
@@ -49,17 +50,21 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         SilentModeInfo that = (SilentModeInfo) o;
-        return Arrays.equals(mAttrs, that.mAttrs);
+        return mMonitoringHWStateSignal == that.mMonitoringHWStateSignal
+                && mSilentModeByHWStateSignal == that.mSilentModeByHWStateSignal
+                && mForcedSilentMode == that.mForcedSilentMode;
     }
 
     @Override
     public int hashCode() {
-        return Arrays.hashCode(mAttrs);
+        return Objects.hash(mMonitoringHWStateSignal,
+                mSilentModeByHWStateSignal, mForcedSilentMode);
     }
 
     @Override
     public String toString() {
-        return Arrays.toString(mAttrs);
+        return String.format("SilentModeInfo: %b, %b, %b", mMonitoringHWStateSignal,
+                mSilentModeByHWStateSignal, mForcedSilentMode);
     }
 
     public static SilentModeInfo parse(String cmdOutput) throws Exception {
@@ -70,17 +75,27 @@
             throw new IllegalArgumentException(
                     "SilentModeQueryResult.parse(): malformatted cmd output: " + cmdOutput);
         }
-        for (int idx = 0; idx < SilentModeInfo.ATTR_HEADERS.length; idx++) {
+        for (int idx = 0; idx < ATTR_HEADERS.length; idx++) {
             String[] tokens = lines[idx].trim().split(":");
-            if (tokens.length != 2
-                    || !tokens[0].contains(SilentModeInfo.ATTR_HEADERS[idx])) {
+            if (tokens.length != 2) {
                 throw new IllegalArgumentException(
                         "SilentModeQueryResult.parse(): malformatted attr line: " + lines[idx]);
             }
-            attrs[idx] = Boolean.parseBoolean(tokens[1].trim());
+            int hdrIdx;
+            String hdr = tokens[0];
+            String val = tokens[1];
+            for (hdrIdx = 0; hdrIdx < ATTR_HEADERS.length; hdrIdx++) {
+                if (hdr.contains(ATTR_HEADERS[hdrIdx])) {
+                    break;
+                }
+            }
+            if (hdrIdx == ATTR_HEADERS.length) {
+                throw new IllegalArgumentException(
+                        "SilentModeQueryResult.parse(): unknown header: " + hdr);
+            }
+            attrs[hdrIdx] = Boolean.parseBoolean(val.trim());
         }
 
-        return new SilentModeInfo(attrs);
+        return new SilentModeInfo(attrs[0], attrs[1], attrs[2]);
     }
-
 }
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0481.txt b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
new file mode 100644
index 0000000..f8d64e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
@@ -0,0 +1 @@
+This is cve_2021-0481.txt
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0691.sh b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
new file mode 100644
index 0000000..f0baada
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo -n 'u:r:system_app:s0' > /proc/self/attr/current
+cd $1
+ls -l base.apk
+echo aaa > base.apk
+ls -l base.apk
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
new file mode 100644
index 0000000..81e559a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 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.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test that collects test results from test package android.security.cts.CVE_2021_0481.
+ *
+ * When this test builds, it also builds a support APK containing
+ * {@link android.sample.cts.CVE_2021_0481.SampleDeviceTest}, the results of which are
+ * collected from the hostside and reported accordingly.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0481 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0481";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0481.apk";
+
+    private static final String DEVICE_DIR1 = "/data/user_de/0/com.android.settings/shared_prefs/";
+    private static final String DEVICE_DIR2 = "/data/user_de/0/com.android.settings/cache/";
+
+    //defined originally as
+    //private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+    //in com.android.settings.users.EditUserPhotoController class
+    private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+    private static final String TEST_FILE_NAME = "cve_2021_0481.txt";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 172939189)
+    @AppModeFull
+    public void testRunDeviceTest() throws Exception {
+        AdbUtils.pushResource("/" + TEST_FILE_NAME, DEVICE_DIR1 + TEST_FILE_NAME, getDevice());
+        String cmd = "rm " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME;
+        AdbUtils.runCommandLine(cmd, getDevice());
+
+        installPackage();
+
+        //ensure the screen is woken up.
+        //(we need to do this twice. once wakes up the screen, and another unlocks the lock screen)
+        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
+
+        //Check if TEST_FILE_NAME has been copied by "Evil activity"
+        //If the file has been copied then it means the vulnerability is active so the test fails.
+        cmd = "cmp -s " + DEVICE_DIR1 + TEST_FILE_NAME + " " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME + "; echo $?";
+        String result =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i(cmd + " -->" + result);
+        assertThat(result, not(is("0")));
+    }
+
+    private void installPackage() throws Exception {
+        installPackage(TEST_APP, new String[0]);
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
new file mode 100644
index 0000000..9b592bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 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.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test installs sample app and then tries to overwrite *.apk file
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0691 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
+    private static final String TEST_APP = "CVE-2021-0691.apk";
+    private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
+    private static final String DEVICE_APP_DIR = "/data/app/";
+    private static final String SCRIPT_NAME = "cve_2021_0691.sh";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 188554048)
+    @AppModeFull
+    public void testRunDeviceTest() throws Exception {
+        String cmd;
+        String result;
+
+        //push repro script and install test app
+        AdbUtils.pushResource("/" + SCRIPT_NAME, DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+        AdbUtils.runCommandLine("chmod +x " + DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+        installPackage();
+
+        //see repro script in log
+        cmd = "cd " + DEVICE_TMP_DIR + "; cat " + SCRIPT_NAME;
+        CLog.i("repro script: " + cmd);
+        CLog.i(AdbUtils.runCommandLine(cmd, getDevice()));
+
+        /*
+         look for a location of test package dir
+         for example: /data/app/
+         ~~stRisM1TaNKYDnrHq9PHJg==/android.security.cts.CVE_2021_0691-borrWKTczXhO86vR9vwNJg==
+        */
+        cmd = "find " + DEVICE_APP_DIR + " -name \"*" + TEST_PKG + "*==\"";
+        String appDir =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i("look for appDir: " + cmd);
+        CLog.i("appDir=" + appDir);
+
+        //run repro steps as 'system' user (su 1000)
+        cmd = "su 1000 " + DEVICE_TMP_DIR + SCRIPT_NAME + " " + appDir;
+        result =  AdbUtils.runCommandLine(cmd, getDevice());
+        CLog.i("command: " + cmd);
+        CLog.i("result: " + result);
+
+        //compare base.apk against aaa
+        //if differs test passes
+        cmd = "echo aaa | cmp -s " + appDir + "/base.apk; echo $?";
+        result =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i("command: " + cmd);
+        CLog.i("result: " + result);
+        assertThat(result, not(is("0")));
+    }
+
+    private void installPackage() throws Exception {
+        installPackage(TEST_APP, new String[0]);
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
new file mode 100644
index 0000000..db36d6f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+    name: "CVE-2021-0481",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "androidx.test.core",
+        "androidx.appcompat_appcompat",
+    ],
+    sdk_version: "current",
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
new file mode 100644
index 0000000..b5d4b57
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 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"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.security.cts.CVE_2021_0481"
+          android:targetSandboxVersion="2">
+
+  <application>
+    <uses-library android:name="android.test.runner"/>
+
+    <activity android:name=".EvilActivity" >
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.OPEN_DOCUMENT"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.CREATE_DOCUMENT"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.GET_CONTENT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.OPEN_DOCUMENT_TREE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+    </activity>
+
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0481" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
new file mode 100644
index 0000000..535c27a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 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.security.cts.CVE_2021_0481;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import androidx.test.uiautomator.BySelector;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+/**
+ * launch "Settings" app
+ * set up user photo
+ */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+  class ClickableNotFound extends Exception{
+    public ClickableNotFound(String s){
+      super(s);
+    }
+  }
+
+  private static final String BASIC_SAMPLE_PACKAGE
+          = "android.security.cts.CVE_2021_0481";
+  private static final int LAUNCH_TIMEOUT_MS = 20000;
+  private static final String TAG = "TAG_2021_0481";
+  private UiDevice mDevice;
+
+  @Test
+  public void testUserPhotoSetUp() {
+
+    //set mDevice and go to homescreen
+    mDevice = UiDevice.getInstance(getInstrumentation());
+    mDevice.pressHome();
+
+    //start "Settings" app
+    Intent myIntent = new Intent("android.settings.USER_SETTINGS");
+                                //android.provider.Settings.ACTION_USER_SETTINGS
+    myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    try{
+      getApplicationContext().startActivity(myIntent);
+    } catch(android.content.ActivityNotFoundException e){
+      Log.d(TAG, "Activity to be tested  doesn't exist. Test will pass.");
+      return;
+    }
+
+    //wait for "User Settings" activity to appear.
+    SystemClock.sleep(6000);
+
+    //perform UI test steps
+    try {
+      //in "Multiple users" activity showing "You(Owner)"
+      searchAndClick(mDevice, "You (Owner)", 2000);
+       //in "Profile Info" dialog window showing user silhouette
+      searchAndClick(mDevice, "Select photo", 2000);
+      //in unnamed subdialog showing two options: "Take a photo" "Choose an image"
+      searchAndClick(mDevice, "Choose an image", 6000);
+      //in "Browse Files in Other Apps" activity
+      searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000);
+    } catch (ClickableNotFound e){
+      Log.d(TAG, e.toString());
+      assumeNoException(e);
+    }
+    Log.d(TAG, "end of testUserPhotoSetUp()");
+  }
+
+  //see what is on screen and click on object containing name
+  //throw exception if object not found
+  private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound {
+
+    List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
+    boolean clicked = false;
+    Log.d(TAG, "looking for " + name);
+    Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables");
+
+    if(objects != null){
+      for (UiObject2 o : objects) {
+        if(searchAndLog(o, name, ""))
+        {
+          o.click();
+          clicked=true;
+          Log.d(TAG, name + " clicked");
+          SystemClock.sleep(timeOut); //wait for click result to appear onscreen
+          break; //to avoid androidx.test.uiautomator.StaleObjectException
+        }
+      }
+    }
+    if(!clicked) {
+      throw new ClickableNotFound("\"" + name + "\" not found to click on");
+    }
+  }
+
+  //returns true if UiObject2 contains name
+  private boolean searchAndLog(UiObject2 o, String name, String prefix){
+
+    String lname = o.getText();
+    String cname = o.getClassName();
+    String cdesc  = o.getContentDescription();
+
+    Log.d(TAG, prefix + "class=" + cname);
+    Log.d(TAG, prefix + "getText()=" + lname);
+    Log.d(TAG, prefix + "getContentDescription()=" + cdesc);
+    Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());
+
+    if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name)) {
+      Log.d(TAG, prefix + "found-->" + name);
+      return true;
+    } else {
+      java.util.List<UiObject2> objects2 = o.getChildren();
+      if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
+        for (UiObject2 o2 : objects2) {
+          if(searchAndLog(o2, name, prefix + "__")){
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
new file mode 100644
index 0000000..92f0ec3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.security.cts.CVE_2021_0481;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class EvilActivity extends Activity {
+
+    final static String PRIVATE_URI = "file:///data/user_de/0/com.android.settings/shared_prefs/cve_2021_0481.txt";
+    private static final String TAG = "TAG_2021_0481";
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.d(TAG, "EvilActivity started!");
+        setResult(-1, new Intent().setData(Uri.parse(PRIVATE_URI)));
+        finish();
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
new file mode 100644
index 0000000..0028642
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+    name: "CVE-2021-0691",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    sdk_version: "current",
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
new file mode 100644
index 0000000..1a83c8e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 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"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.security.cts.CVE_2021_0691"
+          android:targetSandboxVersion="2">
+
+  <application>
+    <uses-library android:name="android.test.runner"/>
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0691" />
+
+</manifest>
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex
index b6cbd0b..791d0dd 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex
index 3a8cae2..0a26d23 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex
index c8b7c87..5ed2c7e 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex
index e7f11f1..133f7f7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
index 8f409e8..6ce5397 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex
index 202ad88..4228ffe 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
index 52c4436..de090f1 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
index 74e7af1..162044c 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex
index 02ecbf8..9d68887 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
index f815d5a..44f7613 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
index 6f7e30b..389871d 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex
index 87122ab..f8fa44f 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index 46709dd..9658818 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index c4c3dd6..3440043 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
index d976d2a..d6f7d8f 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index 05f2f81..cc214f8 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index 68fcaa2..dab82a0 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
index f993623..9706f2f 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
index 6ee0016..f305cff 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex
index f87d160..3122c96 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex
new file mode 100644
index 0000000..0f5134d
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex
index f678c63..a83bf51 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index aa0ccc8..703b641 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex
index 155add0..806ccc7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
index 6606f91..a94ae75 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex
index 5f71d21..a9c2758 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex
index c8b7c87..5ed2c7e 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex
index e7f11f1..133f7f7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
index 8f409e8..6ce5397 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex
index 202ad88..4228ffe 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
index 067b1e4..de090f1 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
index b90e07f..19ec142 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex
index 02ecbf8..9d68887 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
index 44ef6b0..9929c3d 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
index 6f7e30b..389871d 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex
index 3dcfb26..3f2fc50 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index 19abbaa..cf628ab 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index 9eb9377..ba5af3b 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
index 2e86388..38c073f 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index 05f2f81..cc214f8 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index 68fcaa2..dab82a0 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
index f993623..9706f2f 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
index 6ee0016..f305cff 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex
index 12a9225..7f3e9ec 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex
new file mode 100644
index 0000000..0f5134d
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex
index bcdb96a..1aeb0b0 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index dee3528..20f1c85 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex
index 155add0..806ccc7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
index bcc9805..65f2a3b 100644
--- a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
+++ b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
index bcc9805..65f2a3b 100644
--- a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
+++ b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
Binary files differ
diff --git a/hostsidetests/time/Android.bp b/hostsidetests/time/Android.bp
index 4f82544..72d27e4 100644
--- a/hostsidetests/time/Android.bp
+++ b/hostsidetests/time/Android.bp
@@ -22,6 +22,7 @@
     libs: ["cts-tradefed", "tradefed"],
     static_libs: [
         "cts-statsd-atom-host-test-utils",
+        "host_time_shell_utils",
     ],
     test_suites: ["general-tests", "cts"],
     test_config: "host/AndroidTest.xml",
diff --git a/hostsidetests/time/host/src/android/time/cts/host/BaseLocationTimeZoneManagerHostTest.java b/hostsidetests/time/host/src/android/time/cts/host/BaseLocationTimeZoneManagerHostTest.java
index 7a675a4..1cc28e6 100644
--- a/hostsidetests/time/host/src/android/time/cts/host/BaseLocationTimeZoneManagerHostTest.java
+++ b/hostsidetests/time/host/src/android/time/cts/host/BaseLocationTimeZoneManagerHostTest.java
@@ -15,22 +15,18 @@
  */
 package android.time.cts.host;
 
-import static android.time.cts.host.LocationTimeZoneManager.DUMP_STATE_OPTION_PROTO;
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.PROVIDER_MODE_SIMULATED;
-import static android.time.cts.host.LocationTimeZoneManager.PRIMARY_PROVIDER_INDEX;
-import static android.time.cts.host.LocationTimeZoneManager.SECONDARY_PROVIDER_INDEX;
-import static android.time.cts.host.LocationTimeZoneManager.SHELL_COMMAND_DUMP_STATE;
-import static android.time.cts.host.LocationTimeZoneManager.SHELL_COMMAND_RECORD_PROVIDER_STATES;
-import static android.time.cts.host.LocationTimeZoneManager.SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND;
-import static android.time.cts.host.LocationTimeZoneManager.SHELL_COMMAND_START;
-import static android.time.cts.host.LocationTimeZoneManager.SHELL_COMMAND_STOP;
-import static android.time.cts.host.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND;
-import static android.time.cts.host.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS;
-import static android.time.cts.host.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ;
+import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PRIMARY_PROVIDER_INDEX;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PROVIDER_MODE_SIMULATED;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.SECONDARY_PROVIDER_INDEX;
 
 import android.app.time.LocationTimeZoneManagerServiceStateProto;
+import android.app.time.cts.shell.DeviceConfigShellHelper;
+import android.app.time.cts.shell.DeviceShellCommandExecutor;
+import android.app.time.cts.shell.LocationShellHelper;
+import android.app.time.cts.shell.LocationTimeZoneManagerShellHelper;
+import android.app.time.cts.shell.TimeZoneDetectorShellHelper;
+import android.app.time.cts.shell.host.HostShellCommandExecutor;
 
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.google.protobuf.Parser;
@@ -47,25 +43,32 @@
 
     private boolean mOriginalGeoDetectionEnabled;
 
-    protected TimeZoneDetectorHostHelper mTimeZoneDetectorHostHelper;
+    protected TimeZoneDetectorShellHelper mTimeZoneDetectorShellHelper;
+    private LocationTimeZoneManagerShellHelper mLocationTimeZoneManagerShellHelper;
+    private LocationShellHelper mLocationShellHelper;
+    private DeviceConfigShellHelper mDeviceConfigShellHelper;
+    private DeviceConfigShellHelper.PreTestState mDeviceConfigPreTestState;
 
     @Before
     public void setUp() throws Exception {
-        TimeZoneDetectorHostHelper timeZoneDetectorHostHelper =
-                new TimeZoneDetectorHostHelper(getDevice());
+        DeviceShellCommandExecutor shellCommandExecutor = new HostShellCommandExecutor(getDevice());
+        mTimeZoneDetectorShellHelper = new TimeZoneDetectorShellHelper(shellCommandExecutor);
+        mLocationTimeZoneManagerShellHelper =
+                new LocationTimeZoneManagerShellHelper(shellCommandExecutor);
+        mLocationShellHelper = new LocationShellHelper(shellCommandExecutor);
+        mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor);
 
         // Confirm the service being tested is present. It can be turned off, in which case there's
         // nothing to test.
-        timeZoneDetectorHostHelper.assumeLocationTimeZoneManagerIsPresent();
-
-        // Only set this if the device meets requirements. It is used to work out if there is
-        // tearDown work required.
-        mTimeZoneDetectorHostHelper = timeZoneDetectorHostHelper;
+        mLocationTimeZoneManagerShellHelper.assumeLocationTimeZoneManagerIsPresent();
 
         // All tests start with the location_time_zone_manager disabled so that providers can be
         // configured.
         stopLocationTimeZoneManagerService();
 
+        mDeviceConfigPreTestState = mDeviceConfigShellHelper.setSyncModeForTest(
+                DeviceConfigShellHelper.SYNC_DISABLED_MODE_UNTIL_REBOOT, NAMESPACE_SYSTEM_TIME);
+
         // Configure two simulated providers. At least one is needed to be able to turn on
         // geo detection below. Tests may override these values for their own use.
         setProviderModeOverride(PRIMARY_PROVIDER_INDEX, PROVIDER_MODE_SIMULATED);
@@ -73,28 +76,28 @@
 
         // Make sure locations is enabled, otherwise the geo detection feature will be disabled
         // whatever the geolocation detection setting is set to.
-        mOriginalLocationEnabled = mTimeZoneDetectorHostHelper.isLocationEnabledForCurrentUser();
+        mOriginalLocationEnabled = mLocationShellHelper.isLocationEnabledForCurrentUser();
         if (!mOriginalLocationEnabled) {
-            mTimeZoneDetectorHostHelper.setLocationEnabledForCurrentUser(true);
+            mLocationShellHelper.setLocationEnabledForCurrentUser(true);
         }
 
         // Make sure automatic time zone detection is enabled, otherwise the geo detection feature
         // will be disabled whatever the geolocation detection setting is set to
-        mOriginalAutoDetectionEnabled = mTimeZoneDetectorHostHelper.isAutoDetectionEnabled();
+        mOriginalAutoDetectionEnabled = mTimeZoneDetectorShellHelper.isAutoDetectionEnabled();
         if (!mOriginalAutoDetectionEnabled) {
-            mTimeZoneDetectorHostHelper.setAutoDetectionEnabled(true);
+            mTimeZoneDetectorShellHelper.setAutoDetectionEnabled(true);
         }
 
         // Make sure geolocation time zone detection is enabled.
-        mOriginalGeoDetectionEnabled = mTimeZoneDetectorHostHelper.isGeoDetectionEnabled();
+        mOriginalGeoDetectionEnabled = mTimeZoneDetectorShellHelper.isGeoDetectionEnabled();
         if (!mOriginalGeoDetectionEnabled) {
-            mTimeZoneDetectorHostHelper.setGeoDetectionEnabled(true);
+            mTimeZoneDetectorShellHelper.setGeoDetectionEnabled(true);
         }
     }
 
     @After
     public void tearDown() throws Exception {
-        if (mTimeZoneDetectorHostHelper == null) {
+        if (!mLocationTimeZoneManagerShellHelper.isLocationTimeZoneManagerPresent()) {
             // Setup didn't do anything, no need to tearDown.
             return;
         }
@@ -103,12 +106,13 @@
         stopLocationTimeZoneManagerService();
 
         // Reset settings and server flags as best we can.
-        mTimeZoneDetectorHostHelper.setGeoDetectionEnabled(mOriginalGeoDetectionEnabled);
-        mTimeZoneDetectorHostHelper.setAutoDetectionEnabled(mOriginalAutoDetectionEnabled);
-        mTimeZoneDetectorHostHelper.setLocationEnabledForCurrentUser(mOriginalLocationEnabled);
-        mTimeZoneDetectorHostHelper.resetSystemTimeDeviceConfigKeys();
+        mTimeZoneDetectorShellHelper.setGeoDetectionEnabled(mOriginalGeoDetectionEnabled);
+        mTimeZoneDetectorShellHelper.setAutoDetectionEnabled(mOriginalAutoDetectionEnabled);
+        mLocationShellHelper.setLocationEnabledForCurrentUser(mOriginalLocationEnabled);
         setLocationTimeZoneManagerStateRecordingMode(false);
 
+        mDeviceConfigShellHelper.restoreDeviceConfigStateForTest(mDeviceConfigPreTestState);
+
         // Attempt to start the service. It may not start if there are no providers configured,
         // but that is ok.
         startLocationTimeZoneManagerService();
@@ -116,65 +120,34 @@
 
     protected LocationTimeZoneManagerServiceStateProto dumpLocationTimeZoneManagerServiceState()
             throws Exception {
-        byte[] protoBytes = executeLocationTimeZoneManagerCommand(
-                "%s --%s", SHELL_COMMAND_DUMP_STATE, DUMP_STATE_OPTION_PROTO);
+        byte[] protoBytes = mLocationTimeZoneManagerShellHelper.dumpState();
         Parser<LocationTimeZoneManagerServiceStateProto> parser =
                 LocationTimeZoneManagerServiceStateProto.parser();
         return parser.parseFrom(protoBytes);
     }
 
     protected void setLocationTimeZoneManagerStateRecordingMode(boolean enabled) throws Exception {
-        String command = String.format("%s %s", SHELL_COMMAND_RECORD_PROVIDER_STATES, enabled);
-        executeLocationTimeZoneManagerCommand(command);
+        mLocationTimeZoneManagerShellHelper.recordProviderStates(enabled);
     }
 
     protected void startLocationTimeZoneManagerService() throws Exception {
-        executeLocationTimeZoneManagerCommand(SHELL_COMMAND_START);
+        mLocationTimeZoneManagerShellHelper.start();
     }
 
     protected void stopLocationTimeZoneManagerService() throws Exception {
-        executeLocationTimeZoneManagerCommand(SHELL_COMMAND_STOP);
+        mLocationTimeZoneManagerShellHelper.stop();
     }
 
     protected void setProviderModeOverride(int providerIndex, String mode) throws Exception {
-        String deviceConfigKey;
-        if (providerIndex == PRIMARY_PROVIDER_INDEX) {
-            deviceConfigKey = KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
-        } else {
-            deviceConfigKey = KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
-        }
-
-        if (mode == null) {
-            mTimeZoneDetectorHostHelper.clearSystemTimeDeviceConfigKey(deviceConfigKey);
-        } else {
-            mTimeZoneDetectorHostHelper.setSystemTimeDeviceConfigKey(deviceConfigKey, mode);
-        }
+        mLocationTimeZoneManagerShellHelper.setProviderModeOverride(providerIndex, mode);
     }
 
     protected void simulateProviderSuggestion(int providerIndex, String... zoneIds)
             throws Exception {
-        String timeZoneIds = String.join("&", zoneIds);
-        String testCommand = String.format("%s %s=string_array:%s",
-                SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS,
-                SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ,
-                timeZoneIds);
-        executeProviderTestCommand(providerIndex, testCommand);
+        mLocationTimeZoneManagerShellHelper.simulateProviderSuggestion(providerIndex, zoneIds);
     }
 
     protected void simulateProviderBind(int providerIndex) throws Exception {
-        executeProviderTestCommand(providerIndex, SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND);
-    }
-
-    private void executeProviderTestCommand(int providerIndex, String testCommand)
-            throws Exception {
-        executeLocationTimeZoneManagerCommand("%s %s %s",
-                SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND, providerIndex, testCommand);
-    }
-
-    private byte[] executeLocationTimeZoneManagerCommand(String cmd, Object... args)
-            throws Exception {
-        String command = String.format(cmd, args);
-        return mTimeZoneDetectorHostHelper.executeShellCommandReturnBytes("cmd %s %s",
-                LocationTimeZoneManager.SHELL_COMMAND_SERVICE_NAME, command);
+        mLocationTimeZoneManagerShellHelper.simulateProviderBind(providerIndex);
     }
 }
diff --git a/hostsidetests/time/host/src/android/time/cts/host/LocationManager.java b/hostsidetests/time/host/src/android/time/cts/host/LocationManager.java
deleted file mode 100644
index dab7e33..0000000
--- a/hostsidetests/time/host/src/android/time/cts/host/LocationManager.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.time.cts.host;
-
-/**
- * Constants related to the LocationManager service shell commands.
- */
-final class LocationManager {
-
-    /**
-     * The name of the service for shell commands,
-     */
-    static final String SHELL_COMMAND_SERVICE_NAME = "location";
-
-    /**
-     * A shell command that sets the current user's "location enabled" setting value.
-     */
-    static final String SHELL_COMMAND_SET_LOCATION_ENABLED = "set-location-enabled";
-
-    /**
-     * A shell command that gets the current user's "location enabled" setting value.
-     */
-    static final String SHELL_COMMAND_IS_LOCATION_ENABLED = "is-location-enabled";
-
-    private LocationManager() {
-        // No need to instantiate.
-    }
-}
diff --git a/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManager.java b/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManager.java
deleted file mode 100644
index 5031bce..0000000
--- a/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManager.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.time.cts.host;
-
-/**
- * Constants related to the LocationTimeZoneManager service that are used by shell commands and
- * tests.
- *
- * <p>See {@link android.app.time.LocationTimeZoneManager} for the device-side class that holds
- * this information.
- *
- * @hide
- */
-final class LocationTimeZoneManager {
-
-    /**
-     * The index of the primary location time zone provider, used for shell commands.
-     */
-    static final int PRIMARY_PROVIDER_INDEX = 0;
-
-    /**
-     * The index of the secondary location time zone provider, used for shell commands.
-     */
-    static final int SECONDARY_PROVIDER_INDEX = 1;
-
-    /**
-     * The name of the service for shell commands.
-     */
-    static final String SHELL_COMMAND_SERVICE_NAME = "location_time_zone_manager";
-
-    /**
-     * A shell command that starts the service (after stop).
-     */
-    static final String SHELL_COMMAND_START = "start";
-
-    /**
-     * A shell command that stops the service.
-     */
-    static final String SHELL_COMMAND_STOP = "stop";
-
-    /**
-     * A shell command that tells the service to record state information during tests. The next
-     * argument value is "true" or "false".
-     */
-    static final String SHELL_COMMAND_RECORD_PROVIDER_STATES = "record_provider_states";
-
-    /**
-     * A shell command that tells the service to dump its current state.
-     */
-    static final String SHELL_COMMAND_DUMP_STATE = "dump_state";
-
-    /**
-     * Option for {@link #SHELL_COMMAND_DUMP_STATE} that tells it to dump state as a binary proto.
-     */
-    static final String DUMP_STATE_OPTION_PROTO = "proto";
-
-    /**
-     * A shell command that sends test commands to a provider
-     */
-    static final String SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND =
-            "send_provider_test_command";
-
-    /**
-     * Simulated provider test command that simulates the bind succeeding.
-     */
-    static final String SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND = "on_bind";
-
-    /**
-     * Simulated provider test command that simulates a successful time zone detection.
-     */
-    static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS = "success";
-
-    /**
-     * Argument for {@link #SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS} to specify TZDB time zone IDs.
-     */
-    static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ = "tz";
-
-    /** Constants for interacting with the device_config service. */
-    final static class DeviceConfig {
-
-        /** The name of the device_config service command. */
-        static final String SHELL_COMMAND_SERVICE_NAME = "device_config";
-
-        /** The DeviceConfig namespace used for the location_time_zone_manager. */
-        static final String NAMESPACE = "system_time";
-
-        /**
-         * The key for the server flag that can override the device config for whether the primary
-         * location time zone provider is enabled, disabled, or (for testing) in simulation mode.
-         */
-        static final String KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE =
-                "primary_location_time_zone_provider_mode_override";
-
-        /**
-         * The key for the server flag that can override the device config for whether the secondary
-         * location time zone provider is enabled or disabled, or (for testing) in simulation mode.
-         */
-        static final String KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE =
-                "secondary_location_time_zone_provider_mode_override";
-
-        /**
-         * The "simulated" provider mode.
-         * For use with {@link #KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE} and {@link
-         * #KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE}.
-         */
-        static final String PROVIDER_MODE_SIMULATED = "simulated";
-
-        /**
-         * The "disabled" provider mode (equivalent to there being no provider configured).
-         * For use with {@link #KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE} and {@link
-         * #KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE}.
-         */
-        static final String PROVIDER_MODE_DISABLED = "disabled";
-
-        private DeviceConfig() {
-            // No need to instantiate.
-        }
-    }
-
-    private LocationTimeZoneManager() {
-        // No need to instantiate.
-    }
-}
diff --git a/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerHostTest.java b/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerHostTest.java
index 2048da1..1894805b 100644
--- a/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerHostTest.java
+++ b/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerHostTest.java
@@ -17,10 +17,10 @@
 package android.time.cts.host;
 
 
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.PROVIDER_MODE_DISABLED;
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.PROVIDER_MODE_SIMULATED;
-import static android.time.cts.host.LocationTimeZoneManager.PRIMARY_PROVIDER_INDEX;
-import static android.time.cts.host.LocationTimeZoneManager.SECONDARY_PROVIDER_INDEX;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PROVIDER_MODE_DISABLED;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PROVIDER_MODE_SIMULATED;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PRIMARY_PROVIDER_INDEX;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.SECONDARY_PROVIDER_INDEX;
 
 import static org.junit.Assert.assertEquals;
 
diff --git a/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerStatsTest.java b/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerStatsTest.java
index e5bec10..d24b060 100644
--- a/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerStatsTest.java
+++ b/hostsidetests/time/host/src/android/time/cts/host/LocationTimeZoneManagerStatsTest.java
@@ -16,10 +16,10 @@
 
 package android.time.cts.host;
 
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.PROVIDER_MODE_DISABLED;
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.PROVIDER_MODE_SIMULATED;
-import static android.time.cts.host.LocationTimeZoneManager.PRIMARY_PROVIDER_INDEX;
-import static android.time.cts.host.LocationTimeZoneManager.SECONDARY_PROVIDER_INDEX;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PRIMARY_PROVIDER_INDEX;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PROVIDER_MODE_DISABLED;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.PROVIDER_MODE_SIMULATED;
+import static android.app.time.cts.shell.LocationTimeZoneManagerShellHelper.SECONDARY_PROVIDER_INDEX;
 
 import static java.util.stream.Collectors.toList;
 
@@ -71,7 +71,7 @@
     public void testAtom_locationTimeZoneProviderStateChanged() throws Exception {
         setProviderModeOverride(PRIMARY_PROVIDER_INDEX, PROVIDER_MODE_DISABLED);
         setProviderModeOverride(SECONDARY_PROVIDER_INDEX, PROVIDER_MODE_SIMULATED);
-        mTimeZoneDetectorHostHelper.setGeoDetectionEnabled(false);
+        mTimeZoneDetectorShellHelper.setGeoDetectionEnabled(false);
 
         startLocationTimeZoneManagerService();
 
@@ -80,9 +80,9 @@
 
         // Turn geo detection on and off, twice.
         for (int i = 0; i < 2; i++) {
-            mTimeZoneDetectorHostHelper.setGeoDetectionEnabled(true);
+            mTimeZoneDetectorShellHelper.setGeoDetectionEnabled(true);
             Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
-            mTimeZoneDetectorHostHelper.setGeoDetectionEnabled(false);
+            mTimeZoneDetectorShellHelper.setGeoDetectionEnabled(false);
             Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
         }
 
@@ -130,7 +130,7 @@
         return Collections.singleton(stateId(providerIndex, state));
     }
 
-    private List<StatsLog.EventMetricData> extractEventsForProviderIndex(
+    private static List<StatsLog.EventMetricData> extractEventsForProviderIndex(
             List<StatsLog.EventMetricData> data, int providerIndex) {
         return data.stream().filter(event -> {
             if (!event.getAtom().hasLocationTimeZoneProviderStateChanged()) {
diff --git a/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetector.java b/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetector.java
deleted file mode 100644
index 63b0362..0000000
--- a/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetector.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.time.cts.host;
-
-/**
- * Constants related to the TimeZoneDetector service.
- *
- * <p>See {@link android.app.timezonedetector.TimeZoneDetector} for the device-side class that holds
- * this information.
- */
-interface TimeZoneDetector {
-
-    /**
-     * The name of the service for shell commands.
-     * @hide
-     */
-    String SHELL_COMMAND_SERVICE_NAME = "time_zone_detector";
-
-    /**
-     * A shell command that prints the current "auto time zone detection" global setting value.
-     * @hide
-     */
-    String SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED = "is_auto_detection_enabled";
-
-    /**
-     * A shell command that sets the current "auto time zone detection" global setting value.
-     * @hide
-     */
-    String SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED = "set_auto_detection_enabled";
-
-    /**
-     * A shell command that prints whether the telephony-based time zone detection feature is
-     * supported on the device.
-     * @hide
-     */
-    String SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED = "is_telephony_detection_supported";
-
-    /**
-     * A shell command that prints whether the geolocation-based time zone detection feature is
-     * supported on the device.
-     * @hide
-     */
-    String SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED = "is_geo_detection_supported";
-
-    /**
-     * A shell command that prints the current user's "location-based time zone detection enabled"
-     * setting.
-     * @hide
-     */
-    String SHELL_COMMAND_IS_GEO_DETECTION_ENABLED = "is_geo_detection_enabled";
-
-    /**
-     * A shell command that sets the current user's "location-based time zone detection enabled"
-     * setting.
-     * @hide
-     */
-    String SHELL_COMMAND_SET_GEO_DETECTION_ENABLED = "set_geo_detection_enabled";
-
-    /**
-     * A shell command that injects a geolocation time zone suggestion (as if from the
-     * location_time_zone_manager).
-     * @hide
-     */
-    String SHELL_COMMAND_SUGGEST_GEO_LOCATION_TIME_ZONE = "suggest_geo_location_time_zone";
-
-    /**
-     * A shell command that injects a manual time zone suggestion (as if from the SettingsUI or
-     * similar).
-     * @hide
-     */
-    String SHELL_COMMAND_SUGGEST_MANUAL_TIME_ZONE = "suggest_manual_time_zone";
-
-    /**
-     * A shell command that injects a telephony time zone suggestion (as if from the phone app).
-     * @hide
-     */
-    String SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE = "suggest_telephony_time_zone";
-}
diff --git a/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorHostHelper.java b/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorHostHelper.java
deleted file mode 100644
index 321cbf2..0000000
--- a/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorHostHelper.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2021 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.time.cts.host;
-
-import static android.time.cts.host.LocationManager.SHELL_COMMAND_IS_LOCATION_ENABLED;
-import static android.time.cts.host.LocationManager.SHELL_COMMAND_SET_LOCATION_ENABLED;
-import static android.time.cts.host.LocationTimeZoneManager.DeviceConfig.NAMESPACE;
-import static android.time.cts.host.TimeZoneDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
-import static android.time.cts.host.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_ENABLED;
-import static android.time.cts.host.TimeZoneDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED;
-import static android.time.cts.host.TimeZoneDetector.SHELL_COMMAND_SET_GEO_DETECTION_ENABLED;
-
-import static org.junit.Assume.assumeTrue;
-
-import com.android.tradefed.device.CollectingByteOutputReceiver;
-import com.android.tradefed.device.ITestDevice;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import java.util.Objects;
-
-/**
- * A helper class that helps host tests interact with the time_zone_detector and location_manager
- * services via adb.
- */
-final class TimeZoneDetectorHostHelper {
-
-    private final ITestDevice mDevice;
-
-    TimeZoneDetectorHostHelper(ITestDevice mDevice) {
-        this.mDevice = Objects.requireNonNull(mDevice);
-    }
-
-    boolean isLocationEnabledForCurrentUser() throws Exception {
-        byte[] result = executeLocationManagerCommand(SHELL_COMMAND_IS_LOCATION_ENABLED);
-        return parseShellCommandBytesAsBoolean(result);
-    }
-
-    void setLocationEnabledForCurrentUser(boolean enabled) throws Exception {
-        executeLocationManagerCommand(
-                "%s %s", SHELL_COMMAND_SET_LOCATION_ENABLED, enabled);
-    }
-
-    boolean isAutoDetectionEnabled() throws Exception {
-        byte[] result = executeTimeZoneDetectorCommand(SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED);
-        return parseShellCommandBytesAsBoolean(result);
-    }
-
-    void setAutoDetectionEnabled(boolean enabled) throws Exception {
-        executeTimeZoneDetectorCommand("%s %s", SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED, enabled);
-    }
-
-    boolean isGeoDetectionEnabled() throws Exception {
-        byte[] result = executeTimeZoneDetectorCommand(SHELL_COMMAND_IS_GEO_DETECTION_ENABLED);
-        return parseShellCommandBytesAsBoolean(result);
-    }
-
-    void setGeoDetectionEnabled(boolean enabled) throws Exception {
-        executeTimeZoneDetectorCommand("%s %s", SHELL_COMMAND_SET_GEO_DETECTION_ENABLED, enabled);
-    }
-
-    void assumeLocationTimeZoneManagerIsPresent() throws Exception {
-        assumeTrue(isLocationTimeZoneManagerPresent());
-    }
-
-    private boolean isLocationTimeZoneManagerPresent() throws Exception {
-        // Look for the service name in "cmd -l".
-        byte[] serviceListBytes = executeShellCommandReturnBytes("cmd -l");
-        try (BufferedReader reader = new BufferedReader(
-                new InputStreamReader(
-                        new ByteArrayInputStream(serviceListBytes), StandardCharsets.UTF_8))) {
-            String serviceName;
-            while ((serviceName = reader.readLine()) != null) {
-                serviceName = serviceName.trim();
-                if (LocationTimeZoneManager.SHELL_COMMAND_SERVICE_NAME.equals(serviceName)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    boolean isGeoDetectionSupported() throws Exception {
-        byte[] result = executeTimeZoneDetectorCommand(
-                TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED);
-        return parseShellCommandBytesAsBoolean(result);
-    }
-
-    boolean isTelephonyDetectionSupported() throws Exception {
-        byte[] result = executeTimeZoneDetectorCommand(
-                TimeZoneDetector.SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED);
-        return parseShellCommandBytesAsBoolean(result);
-    }
-
-    void clearSystemTimeDeviceConfigKey(String deviceConfigKey) throws Exception {
-        executeDeviceConfigCommand("delete %s %s", NAMESPACE, deviceConfigKey);
-    }
-
-    void setSystemTimeDeviceConfigKey(String deviceConfigKey, String value) throws Exception {
-        executeDeviceConfigCommand("put %s %s %s", NAMESPACE, deviceConfigKey, value);
-    }
-
-    void resetSystemTimeDeviceConfigKeys() throws Exception {
-        executeDeviceConfigCommand("reset trusted_defaults %s", NAMESPACE);
-    }
-
-    private byte[] executeDeviceConfigCommand(String cmd, Object... args) throws Exception {
-        String command = String.format(cmd, args);
-        return executeShellCommandReturnBytes("cmd %s %s",
-                LocationTimeZoneManager.DeviceConfig.SHELL_COMMAND_SERVICE_NAME, command);
-    }
-
-    private byte[] executeLocationManagerCommand(String cmd, Object... args)
-            throws Exception {
-        String command = String.format(cmd, args);
-        return executeShellCommandReturnBytes("cmd %s %s",
-                LocationManager.SHELL_COMMAND_SERVICE_NAME, command);
-    }
-
-    private byte[] executeTimeZoneDetectorCommand(String cmd, Object... args) throws Exception {
-        String command = String.format(cmd, args);
-        return executeShellCommandReturnBytes("cmd %s %s",
-                TimeZoneDetector.SHELL_COMMAND_SERVICE_NAME, command);
-    }
-
-    byte[] executeShellCommandReturnBytes(String cmd, Object... args) throws Exception {
-        CollectingByteOutputReceiver bytesReceiver = new CollectingByteOutputReceiver();
-        mDevice.executeShellCommand(String.format(cmd, args), bytesReceiver);
-        return bytesReceiver.getOutput();
-    }
-
-    static boolean parseShellCommandBytesAsBoolean(byte[] result) {
-        String resultString = new String(result, 0, result.length, StandardCharsets.ISO_8859_1);
-        if (resultString.startsWith("true")) {
-            return true;
-        } else if (resultString.startsWith("false")) {
-            return false;
-        } else {
-            throw new AssertionError("Command returned unexpected result: " + resultString);
-        }
-    }
-}
diff --git a/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorStatsTest.java b/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorStatsTest.java
index e62af49..92992f7 100644
--- a/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorStatsTest.java
+++ b/hostsidetests/time/host/src/android/time/cts/host/TimeZoneDetectorStatsTest.java
@@ -16,9 +16,16 @@
 
 package android.time.cts.host;
 
+import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME;
+
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.app.time.cts.shell.DeviceConfigShellHelper;
+import android.app.time.cts.shell.DeviceShellCommandExecutor;
+import android.app.time.cts.shell.LocationShellHelper;
+import android.app.time.cts.shell.host.HostShellCommandExecutor;
+import android.app.time.cts.shell.TimeZoneDetectorShellHelper;
 import android.cts.statsdatom.lib.AtomTestUtils;
 import android.cts.statsdatom.lib.ConfigUtils;
 import android.cts.statsdatom.lib.DeviceUtils;
@@ -40,11 +47,20 @@
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class TimeZoneDetectorStatsTest extends BaseHostJUnit4Test {
 
-    protected TimeZoneDetectorHostHelper mTimeZoneDetectorHostHelper;
+    private TimeZoneDetectorShellHelper mTimeZoneDetectorShellHelper;
+    private LocationShellHelper mLocationShellHelper;
+    private DeviceConfigShellHelper mDeviceConfigShellHelper;
+    private DeviceConfigShellHelper.PreTestState mDeviceConfigPreTestState;
 
     @Before
     public void setUp() throws Exception {
-        mTimeZoneDetectorHostHelper = new TimeZoneDetectorHostHelper(getDevice());
+        DeviceShellCommandExecutor shellCommandExecutor = new HostShellCommandExecutor(getDevice());
+        mTimeZoneDetectorShellHelper = new TimeZoneDetectorShellHelper(shellCommandExecutor);
+        mLocationShellHelper = new LocationShellHelper(shellCommandExecutor);
+        mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor);
+        mDeviceConfigPreTestState = mDeviceConfigShellHelper.setSyncModeForTest(
+                DeviceConfigShellHelper.SYNC_DISABLED_MODE_UNTIL_REBOOT, NAMESPACE_SYSTEM_TIME);
+
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
     }
@@ -53,6 +69,7 @@
     public void tearDown() throws Exception {
         ConfigUtils.removeConfig(getDevice());
         ReportUtils.clearReports(getDevice());
+        mDeviceConfigShellHelper.restoreDeviceConfigStateForTest(mDeviceConfigPreTestState);
     }
 
     @Test
@@ -81,23 +98,23 @@
 
                 // The shell reports the same info the atom does for geo detection supported.
                 boolean geoDetectionSupportedFromShell =
-                        mTimeZoneDetectorHostHelper.isGeoDetectionSupported();
+                        mTimeZoneDetectorShellHelper.isGeoDetectionSupported();
                 assertThat(state.getGeoSupported()).isEqualTo(geoDetectionSupportedFromShell);
 
                 // The shell reports the same info the atom does for location enabled.
                 boolean locationEnabledForCurrentUserFromShell =
-                        mTimeZoneDetectorHostHelper.isLocationEnabledForCurrentUser();
+                        mLocationShellHelper.isLocationEnabledForCurrentUser();
                 assertThat(state.getLocationEnabled())
                         .isEqualTo(locationEnabledForCurrentUserFromShell);
 
                 // The shell reports the user's setting for auto detection.
                 boolean autoDetectionEnabledFromShell =
-                        mTimeZoneDetectorHostHelper.isAutoDetectionEnabled();
+                        mTimeZoneDetectorShellHelper.isAutoDetectionEnabled();
                 assertThat(state.getAutoDetectionSetting())
                         .isEqualTo(autoDetectionEnabledFromShell);
 
                 boolean telephonyDetectionSupportedFromShell =
-                        mTimeZoneDetectorHostHelper.isTelephonyDetectionSupported();
+                        mTimeZoneDetectorShellHelper.isTelephonyDetectionSupported();
                 boolean noAutoDetectionSupported =
                         !(telephonyDetectionSupportedFromShell || geoDetectionSupportedFromShell);
                 // The atom reports the functional state for "detection mode", which is derived from
@@ -108,7 +125,7 @@
                     expectedDetectionMode = DetectionMode.MANUAL;
                 } else {
                     boolean geoDetectionSettingEnabledFromShell =
-                            mTimeZoneDetectorHostHelper.isGeoDetectionEnabled();
+                            mTimeZoneDetectorShellHelper.isGeoDetectionEnabled();
                     boolean expectedGeoDetectionEnabled =
                             geoDetectionSupportedFromShell
                                     && locationEnabledForCurrentUserFromShell
diff --git a/libs/install/src/com/android/cts/install/lib/Install.java b/libs/install/src/com/android/cts/install/lib/Install.java
index 6d817ed7..377e88a2 100644
--- a/libs/install/src/com/android/cts/install/lib/Install.java
+++ b/libs/install/src/com/android/cts/install/lib/Install.java
@@ -44,6 +44,8 @@
     private int mRollbackDataPolicy = 0;
     private int mSessionMode = PackageInstaller.SessionParams.MODE_FULL_INSTALL;
     private int mInstallFlags = 0;
+    private boolean mBypassAllowedApexUpdateCheck = true;
+    private boolean mBypassStagedInstallerCheck = true;
 
     private Install(boolean isMultiPackage, TestApp... testApps) {
         mIsMultiPackage = isMultiPackage;
@@ -145,6 +147,24 @@
     }
 
     /**
+     * Sets whether to call {@code pm bypass-allowed-apex-update-check true} when creating install
+     * session.
+     */
+    public Install setBypassAllowedApexUpdateCheck(boolean bypassAllowedApexUpdateCheck) {
+        mBypassAllowedApexUpdateCheck = bypassAllowedApexUpdateCheck;
+        return this;
+    }
+
+    /**
+     * Sets whether to call {@code pm bypass-staged-installer-check true} when creating install
+     * session.
+     */
+    public Install setBypassStangedInstallerCheck(boolean bypassStagedInstallerCheck) {
+        mBypassStagedInstallerCheck = bypassStagedInstallerCheck;
+        return this;
+    }
+
+    /**
      * Commits the install.
      *
      * @return the session id of the install session, if the session is successful.
@@ -198,10 +218,10 @@
      */
     private int createEmptyInstallSession(boolean multiPackage, boolean isApex)
             throws IOException {
-        if (mIsStaged || isApex) {
+        if ((mIsStaged || isApex) && mBypassStagedInstallerCheck) {
             SystemUtil.runShellCommandForNoOutput("pm bypass-staged-installer-check true");
         }
-        if (isApex) {
+        if (isApex && mBypassAllowedApexUpdateCheck) {
             SystemUtil.runShellCommandForNoOutput("pm bypass-allowed-apex-update-check true");
         }
         try {
@@ -223,10 +243,10 @@
             }
             return InstallUtils.getPackageInstaller().createSession(params);
         } finally {
-            if (mIsStaged || isApex) {
+            if ((mIsStaged || isApex) && mBypassStagedInstallerCheck) {
                 SystemUtil.runShellCommandForNoOutput("pm bypass-staged-installer-check false");
             }
-            if (isApex) {
+            if (isApex && mBypassAllowedApexUpdateCheck) {
                 SystemUtil.runShellCommandForNoOutput("pm bypass-allowed-apex-update-check false");
             }
         }
diff --git a/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java b/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
index 5b9e0fe..aa1db34 100644
--- a/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
+++ b/tests/app/DownloadManagerInstallerTest/src/android/app/cts/DownloadManagerInstallerTest.java
@@ -16,10 +16,12 @@
 package android.app.cts;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import android.app.DownloadManager;
 import android.content.IntentFilter;
 import android.net.Uri;
+import android.os.Environment;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -27,13 +29,20 @@
 import org.junit.runner.RunWith;
 
 import java.io.File;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 @RunWith(AndroidJUnit4.class)
 public class DownloadManagerInstallerTest extends DownloadManagerTestBase {
+    private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
+    private static final long POLLING_SLEEP_MILLIS = 100;
 
     @Test
     public void testSetDestinationUri_otherAppObbDir() throws Exception {
-        File obbDir = mContext.getObbDir();
+        // getObbDir() may return {@code null} if shared storage is not currently available.
+        pollForExternalStorageState();
+        final File obbDir = mContext.getObbDir();
+        assertNotNull(obbDir);
 
         String otherAppObbPath = obbDir.getPath().replace(mContext.getPackageName(),
                 "android.app.cts.some_random_package");
@@ -63,4 +72,18 @@
             mContext.unregisterReceiver(receiver);
         }
     }
+
+    /**
+     * Polls for external storage to be mounted.
+     */
+    private static void pollForExternalStorageState() throws Exception {
+        for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
+            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+                return;
+            }
+            Thread.sleep(POLLING_SLEEP_MILLIS);
+        }
+        throw new TimeoutException("Timed out while waiting for ExternalStorageState to be"
+                + " MEDIA_MOUNTED");
+    }
 }
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index 677cbf1..2c54a4c 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -1296,6 +1296,24 @@
         waitForResultOrThrow(DELAY, "service to be destroyed");
     }
 
+    public void testForegroundService_deferThenKeepNotification() throws Exception {
+        // Start FGS with deferred notification; it should not display
+        mExpectedServiceState = STATE_START_1;
+        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to start first time");
+        assertNoNotification(1);
+
+        // Exit foreground but keep notification - it should display immediately
+        mExpectedServiceState = STATE_START_2;
+        startForegroundService(COMMAND_STOP_FOREGROUND_DONT_REMOVE_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to stop foreground");
+        assertNotification(1, LocalForegroundService.getNotificationTitle(1));
+
+        mExpectedServiceState = STATE_DESTROY;
+        mContext.stopService(mLocalForegroundService);
+        waitForResultOrThrow(DELAY, "service to be destroyed");
+    }
+
     class TestSendCallback implements PendingIntent.OnFinished {
         public volatile int result = -1;
 
diff --git a/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
new file mode 100644
index 0000000..9fb12d3
--- /dev/null
+++ b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2021 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.hardware.camera2.cts;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.ConditionVariable;
+import android.util.Log;
+import android.util.Size;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.Test;
+
+import static android.hardware.camera2.cts.CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS;
+import static android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+import static junit.framework.Assert.*;
+
+/**
+ * <p>Basic test for image capture using CONTROL_ZOOM_RATIO. It uses CameraDevice as
+ * producer, and camera sends image data to an imageReader. Image formats
+ * being tested are JPEG and RAW.</p>
+ */
+@RunWith(Parameterized.class)
+public class ZoomCaptureTest extends Camera2AndroidTestCase {
+    private static final String TAG = "ZoomCaptureTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private SimpleImageListener mListener;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @Test
+    public void testJpegZoomCapture() throws Exception {
+        for (String id : mCameraIdsUnderTest) {
+            try {
+                Log.v(TAG, "Testing jpeg zoom capture for Camera " + id);
+                openDevice(id);
+                bufferFormatZoomTestByCamera(ImageFormat.JPEG);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    @Test
+    public void testRawZoomCapture() throws Exception {
+        for (String id : mCameraIdsUnderTest) {
+            try {
+                Log.v(TAG, "Testing raw zoom capture for camera " + id);
+                openDevice(id);
+
+                bufferFormatZoomTestByCamera(ImageFormat.RAW_SENSOR);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    private void bufferFormatZoomTestByCamera(int format) throws Exception {
+        Size[] availableSizes = mStaticInfo.getAvailableSizesForFormatChecked(format,
+                StaticMetadata.StreamDirection.Output);
+        if (availableSizes.length == 0) {
+            return;
+        }
+
+        List<Float> candidateZoomRatios = CameraTestUtils.getCandidateZoomRatios(mStaticInfo);
+        Set<String> physicalCameraIds = null;
+        if (mStaticInfo.isLogicalMultiCamera()) {
+            physicalCameraIds = mStaticInfo.getCharacteristics().getPhysicalCameraIds();
+        }
+        try {
+            mListener  = new SimpleImageListener();
+            // Pick the largest image size:
+            Size maxSize = CameraTestUtils.getMaxSize(availableSizes);
+            createDefaultImageReader(maxSize, format, 1, mListener);
+
+            checkImageReaderSessionConfiguration(
+                    "Camera capture session validation for format: " + format + "failed");
+
+            ArrayList<OutputConfiguration> outputConfigs = new ArrayList<>();
+            OutputConfiguration config = new OutputConfiguration(mReader.getSurface());
+            outputConfigs.add(config);
+
+            CaptureRequest.Builder requestBuilder = prepareCaptureRequestForConfigs(
+                    outputConfigs, CameraDevice.TEMPLATE_PREVIEW);
+
+            Set<String> activePhysicalIdsSeen = new HashSet<String>();
+            for (Float zoomRatio : candidateZoomRatios) {
+                if (VERBOSE) {
+                    Log.v(TAG, "Testing format " + format + " zoomRatio " + zoomRatio +
+                            " for camera " + mCamera.getId());
+                }
+
+                requestBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomRatio);
+                CaptureRequest request = requestBuilder.build();
+
+                SimpleCaptureCallback listener = new SimpleCaptureCallback();
+                startCapture(request, false /*repeating*/, listener, mHandler);
+
+                // Validate images.
+                mListener.waitForAnyImageAvailable(CAPTURE_WAIT_TIMEOUT_MS);
+                Image img = mReader.acquireNextImage();
+                assertNotNull("Unable to acquire the latest image", img);
+                CameraTestUtils.validateImage(img, maxSize.getWidth(), maxSize.getHeight(), format,
+                        mDebugFileNameBase);
+                img.close();
+
+                // Validate capture result.
+                if (mStaticInfo.isActivePhysicalCameraIdSupported()) {
+                    CaptureResult result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
+                    String activePhysicalId = result.get(
+                            CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
+                    assertNotNull("Camera " + mCamera.getId() + " result metadata must contain " +
+                            "ACTIVE_PHYSICAL_ID", activePhysicalId);
+                    assertTrue("Camera " + mCamera.getId() + " must be logical " +
+                            "camera if activePhysicalId exists in capture result",
+                            physicalCameraIds != null && physicalCameraIds.size() != 0);
+                    mCollector.expectTrue("Camera " + mCamera.getId() + "  activePhysicalId " +
+                            activePhysicalId + "must be among valid physical Ids "  +
+                            physicalCameraIds.toString(),
+                            physicalCameraIds.contains(activePhysicalId));
+
+                    activePhysicalIdsSeen.add(activePhysicalId);
+                }
+            }
+            // stop capture.
+            stopCapture(/*fast*/false);
+
+            if (activePhysicalIdsSeen.size() > 0 && format == ImageFormat.RAW_SENSOR) {
+                mCollector.expectTrue("Logical camera's activePhysicalCamera should not " +
+                        " change at different zoom levels.", activePhysicalIdsSeen.size() == 1);
+            }
+        } finally {
+            closeDefaultImageReader();
+        }
+    }
+
+    private final class SimpleImageListener implements ImageReader.OnImageAvailableListener {
+        private final ConditionVariable imageAvailable = new ConditionVariable();
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            imageAvailable.open();
+        }
+
+        public void waitForAnyImageAvailable(long timeout) {
+            if (imageAvailable.block(timeout)) {
+                imageAvailable.close();
+            } else {
+                fail("wait for image available timed out after " + timeout + "ms");
+            }
+        }
+    }
+}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
index edd11bc..943d73f 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
@@ -70,12 +70,10 @@
 import com.android.bedstead.testapp.TestAppProvider;
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.eventlib.EventLogs;
-import com.android.eventlib.events.activities.ActivityCreatedEvent;
 import com.android.eventlib.events.activities.ActivityDestroyedEvent;
 import com.android.eventlib.events.activities.ActivityStartedEvent;
 
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -92,7 +90,7 @@
 
     private static final TestApis sTestApis = new TestApis();
 
-    private static final DevicePolicyManager mDevicePolicyManager =
+    private static final DevicePolicyManager sLocalDevicePolicyManager =
             sTestApis.context().instrumentedContext().getSystemService(DevicePolicyManager.class);
 
     private static final int[] INDIVIDUALLY_SETTABLE_FLAGS = new int[] {
@@ -238,7 +236,7 @@
         sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{PACKAGE_NAME});
 
         try {
-            assertThat(mDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isTrue();
+            assertThat(sLocalDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isTrue();
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
@@ -255,7 +253,7 @@
         sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{PACKAGE_NAME});
 
         try {
-            assertThat(mDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
+            assertThat(sLocalDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
@@ -271,7 +269,7 @@
         sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{});
 
         try {
-            assertThat(mDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
+            assertThat(sLocalDevicePolicyManager.isLockTaskPermitted(PACKAGE_NAME)).isFalse();
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
@@ -293,7 +291,7 @@
 
             for (String app : policyExemptApps) {
                 assertWithMessage("isLockTaskPermitted(%s)", app)
-                        .that(mDevicePolicyManager.isLockTaskPermitted(app)).isTrue();
+                        .that(sLocalDevicePolicyManager.isLockTaskPermitted(app)).isTrue();
             }
         } finally {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
@@ -966,6 +964,7 @@
         try {
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(
                     new String[]{dialerPackage});
+
             Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle();
             Intent intent = new Intent(ACTION_DIAL);
             intent.setPackage(dialerPackage);
diff --git a/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml b/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml
index b8926e5..bb10056 100644
--- a/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml
+++ b/tests/framework/base/windowmanager/app/res/layout/blur_activity.xml
@@ -16,6 +16,6 @@
   -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="50dp"
-    android:layout_height="50dp">
+    android:layout_width="100dp"
+    android:layout_height="100dp">
 </FrameLayout>
diff --git a/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java b/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
index 5cf68b5..6b30644 100644
--- a/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
+++ b/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
@@ -143,6 +143,14 @@
         dumpConfigInfo();
     }
 
+    @Override
+    public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+        super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+        dumpConfiguration(newConfig);
+        dumpAssetSeqNumber(newConfig);
+        dumpConfigInfo();
+    }
+
     private void dumpAssetSeqNumber(Configuration newConfig) {
         withTestJournalClient(client -> {
             final Bundle extras = new Bundle();
diff --git a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
index f6d4ab1..628fc4c 100644
--- a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
+++ b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
@@ -256,14 +256,16 @@
                 APP_A_FOREGROUND_ACTIVITY);
         assertTrue("Not able to launch background activity", result);
         assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY);
-        pressHomeAndResumeAppSwitch();
+        // We can't resume app switching after pressing home button, otherwise the grace period
+        // will allow the starts.
+        pressHomeAndWaitHomeResumed();
 
         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A_BACKGROUND_ACTIVITY));
 
         result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY);
-        assertFalse("Previously foreground Activity should not be able to relaunch itself", result);
+        assertFalse("Previously foreground Activity should not be able to make it focused", result);
         result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY);
-        assertFalse("Previously foreground Activity should not be able to relaunch itself", result);
+        assertFalse("Previously background Activity should not be able to make it focused", result);
         assertTaskStack(new ComponentName[] {APP_A_BACKGROUND_ACTIVITY, APP_A_FOREGROUND_ACTIVITY},
                 APP_A_FOREGROUND_ACTIVITY);
     }
@@ -283,7 +285,9 @@
         assertTrue("Not able to launch background activity", result);
         assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY);
 
-        pressHomeAndResumeAppSwitch();
+        // We can't resume app switching after pressing home button, otherwise the grace period
+        // will allow the starts.
+        pressHomeAndWaitHomeResumed();
 
         result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY);
         assertFalse("FG activity shouldn't be visible", result);
@@ -375,7 +379,9 @@
         boolean result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY);
         assertTrue("Not able to start foreground activity", result);
         assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY);
-        pressHomeAndResumeAppSwitch();
+        // We can't resume app switching after pressing home button, otherwise the grace period
+        // will allow the starts.
+        pressHomeAndWaitHomeResumed();
 
         // The activity, now in the background, will attempt to start 2 activities in quick
         // succession
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
index 4ef52d9..ec4903b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
@@ -89,7 +89,7 @@
         }
 
         launchHomeActivity();
-        launchActivity(TRANSLUCENT_ACTIVITY);
+        launchActivity(TRANSLUCENT_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
 
         mWmState.assertFrontStack("Fullscreen stack must be the front stack.",
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
index 7f6cd6c..900f250 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
@@ -406,10 +406,9 @@
 
         // Adjust the test to check a smaller part of the blurred area in order to accept various
         // blur algorithm approximations used in RenderEngine
-        final int kawaseOffset = (int) (blurRadius * 0.7f);
-        final int blurAreaStartX = width / 2 - blurRadius + kawaseOffset;
-        final int blurAreaEndX = width / 2 + blurRadius - kawaseOffset;
-        final int stepSize = kawaseOffset / 4;
+        final int stepSize = blurRadius / 4;
+        final int blurAreaStartX = width / 2 - blurRadius + stepSize;
+        final int blurAreaEndX = width / 2 + blurRadius;
 
         Color previousColor;
         Color currentColor;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index 66dcfa8..6fa58b6 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -69,7 +69,6 @@
  * atest CtsWindowManagerDeviceTestCases:CompatChangeTests
  */
 @Presubmit
-@FlakyTest(bugId = 190609681)
 public final class CompatChangeTests extends MultiDisplayTestBase {
     private static final ComponentName RESIZEABLE_PORTRAIT_ACTIVITY =
             component(ResizeablePortraitActivity.class);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
index ab2a53c..b03e453 100755
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
@@ -164,17 +164,21 @@
                         .setTargetActivity(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY));
 
         mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY, SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
-        mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, false);
         mWmState.assertVisibility(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY, true);
+        mWmState.assertFocusedActivity("Launching Activity must be focused",
+                SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
         lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
 
-        mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, false);
         mWmState.assertVisibility(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY, true);
+        mWmState.assertFocusedActivity("Top activity stay un-change",
+                SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
         mWmState.assertKeyguardShowingAndOccluded();
 
         showWhenLockedActivitySession.finish();
         mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
         mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
+        mWmState.assertFocusedActivity("ShowWhenLocked activity must occludes keyguard",
+                SHOW_WHEN_LOCKED_ACTIVITY);
         mWmState.assertKeyguardShowingAndOccluded();
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index 8dbc12c..63526cf 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -17,6 +17,9 @@
 package android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.server.wm.UiDeviceUtils.pressSleepButton;
+import static android.server.wm.UiDeviceUtils.pressUnlockButton;
+import static android.server.wm.UiDeviceUtils.pressWakeupButton;
 import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.app.Components.HOME_ACTIVITY;
 import static android.server.wm.app.Components.SECONDARY_HOME_ACTIVITY;
@@ -193,6 +196,10 @@
             if (mTestBitmap != null) {
                 mTestBitmap.recycle();
             }
+            // Turning screen off/on to flush deferred color events due to wallpaper changed.
+            pressSleepButton();
+            pressWakeupButton();
+            pressUnlockButton();
         }
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index 24846ef..94f0a68 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -453,6 +453,25 @@
         }
     }
 
+    private void waitAndAssertOverrideThemeColor(int expectedColor) {
+        final ComponentName activity = SPLASH_SCREEN_REPLACE_THEME_ACTIVITY;
+        final Bundle resultExtras = Condition.waitForResult(
+                new Condition<Bundle>("splash screen theme color of " + activity)
+                        .setResultSupplier(() -> TestJournalProvider.TestJournalContainer.get(
+                                OVERRIDE_THEME_COMPONENT).extras)
+                        .setResultValidator(extras -> extras.containsKey(OVERRIDE_THEME_COLOR)));
+        if (resultExtras == null) {
+            fail("No reported override theme color from " + activity);
+        }
+        if (expectedColor > 0) {
+            assertEquals("Override theme color must match",
+                    Integer.toHexString(expectedColor),
+                    Integer.toHexString(resultExtras.getInt(OVERRIDE_THEME_COLOR)));
+        }
+        mWmState.waitForActivityRemoved(activity);
+        separateTestJournal();
+    }
+
     @Test
     public void testOverrideSplashscreenTheme() {
         assumeFalse(isLeanBack());
@@ -461,36 +480,23 @@
         // Pre-launch the activity to ensure status is cleared on the device
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> {});
-        mWmState.waitAndAssertActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
+        waitAndAssertOverrideThemeColor(0 /* ignore */);
 
         // Launch the activity a first time, check that the splashscreen use the default theme,
         // and override the theme for the next launch
-        TestJournalProvider.TestJournal journal = TestJournalProvider.TestJournalContainer.get(
-                OVERRIDE_THEME_COMPONENT);
-
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> intent.putExtra(OVERRIDE_THEME_ENABLED, true));
-        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-        assertEquals(Integer.toHexString(Color.BLUE),
-                Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
+        waitAndAssertOverrideThemeColor(Color.BLUE);
 
         // Launch the activity a second time, check that the theme has been overridden and reset
         // to the default theme
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> {});
-        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-
-        journal = TestJournalProvider.TestJournalContainer.get(OVERRIDE_THEME_COMPONENT);
-        assertEquals(Integer.toHexString(Color.RED),
-                Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
+        waitAndAssertOverrideThemeColor(Color.RED);
 
         // Launch the activity a third time just to check that the theme has indeed been reset.
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
                 intent -> {});
-        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-
-        journal = TestJournalProvider.TestJournalContainer.get(OVERRIDE_THEME_COMPONENT);
-        assertEquals(Integer.toHexString(Color.BLUE),
-                Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
+        waitAndAssertOverrideThemeColor(Color.BLUE);
     }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
index e777034..6f388e3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
@@ -18,6 +18,7 @@
 
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_DESTROY;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_PAUSE;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_RESTART;
@@ -28,15 +29,12 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
 import static android.server.wm.lifecycle.LifecycleVerifier.transition;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
 import android.platform.test.annotations.Presubmit;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 
 import org.junit.Test;
@@ -69,10 +67,8 @@
         // Launch two activities - second one to cover the first one and make it invisible.
         final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
         final Activity secondActivity = launchActivityAndWait(SecondActivity.class);
-        waitAndAssertActivityStates(state(secondActivity, ON_RESUME),
-                state(firstActivity, ON_STOP));
         // Wait for activity to report saved state to the server.
-        getInstrumentation().waitForIdleSync();
+        mWmState.waitForActivityState(firstActivity.getComponentName(), STATE_STOPPED);
 
         // Release the instance of the non-visible activity below.
         getLifecycleLog().clear();
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
index b1d8554..ccd8659 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
@@ -20,7 +20,6 @@
 import android.graphics.Color;
 
 import androidx.annotation.AnyThread;
-import androidx.annotation.ColorInt;
 import androidx.annotation.NonNull;
 
 /**
@@ -91,33 +90,6 @@
         }
 
         /**
-         * Returns pixel color in A8R8G8B8 format.
-         *
-         * @param x X coordinate of the pixel.
-         * @param y Y coordinate of the pixel.
-         * @return Pixel color in A8R8G8B8 format.
-         */
-        @ColorInt
-        @AnyThread
-        int getPixel(int x, int y) {
-            return mPixels[y * mWidth + x];
-        }
-
-        /**
-         * Compares two given pixels to determine whether those two pixels are considered to be
-         * the same within {@link #TOLERANCE}.
-         *
-         * @param lhs a color integer to be compared.
-         * @param rhs another color integer to be compared.
-         * @return {@true} if two given pixels are the same within {@link #TOLERANCE}.
-         */
-        private static boolean robustMatchInternal(@ColorInt int lhs, @ColorInt int rhs) {
-            return lhs == rhs || (Math.abs(Color.red(lhs) - Color.red(rhs)) <= TOLERANCE
-                    && Math.abs(Color.green(lhs) - Color.green(rhs)) <= TOLERANCE
-                    && Math.abs(Color.blue(lhs) - Color.blue(rhs)) <= TOLERANCE);
-        }
-
-        /**
          * Checks if the same image can be found in the specified {@link BitmapImage} within
          * within {@link #TOLERANCE}.
          *
@@ -130,19 +102,25 @@
         boolean robustMatch(@NonNull BitmapImage targetImage, int offsetX, int offsetY) {
             final int targetWidth = targetImage.getWidth();
             final int targetHeight = targetImage.getHeight();
+            final int[] targetPixels = targetImage.mPixels;
+            final int[] sourcePixels = mPixels;
+
+            if (offsetX < 0 || targetWidth <= mWidth - 1 + offsetX) return false;
+            if (offsetY < 0 || targetHeight <= mHeight - 1 + offsetY) return false;
 
             for (int y = 0; y < mHeight; ++y) {
                 for (int x = 0; x < mWidth; ++x) {
                     final int targetX = x + offsetX;
-                    if (targetX < 0 || targetWidth <= targetX) {
-                        return false;
-                    }
                     final int targetY = y + offsetY;
-                    if (targetY < 0 || targetHeight <= targetY) {
-                        return false;
-                    }
-                    if (!robustMatchInternal(
-                            targetImage.getPixel(targetX, targetY), getPixel(x, y))) {
+                    final int targetPx = targetPixels[targetY * targetWidth + targetX];
+                    final int sourcePx = sourcePixels[y * mWidth + x];
+                    // Compares two given pixels (targetPx & sourcePx) to determine whether those
+                    // two pixels are considered to be the same within {@link #TOLERANCE}.
+                    boolean match = targetPx == sourcePx
+                            || (Math.abs(Color.red(targetPx) - Color.red(sourcePx)) <= TOLERANCE
+                            && Math.abs(Color.green(targetPx) - Color.green(sourcePx)) <= TOLERANCE
+                            && Math.abs(Color.blue(targetPx) - Color.blue(sourcePx)) <= TOLERANCE);
+                    if (!match) {
                         return false;
                     }
                 }
@@ -252,9 +230,12 @@
      */
     public static boolean detect(@NonNull Bitmap bitmap) {
         final BitmapImage targetImage = BitmapImage.createFromBitmap(bitmap);
+
         // Search from the bottom line with an assumption that the IME is shown at the bottom.
-        for (int offsetY = targetImage.getHeight() - 1; offsetY >= 0; --offsetY) {
-            for (int offsetX = 0; offsetX < targetImage.getWidth(); ++offsetX) {
+        final int targetImageHeight = targetImage.getHeight();
+        final int targetImageWidth = targetImage.getWidth();
+        for (int offsetY = targetImageHeight - 1; offsetY >= 0; --offsetY) {
+            for (int offsetX = 0; offsetX < targetImageWidth; ++offsetX) {
                 if (sImage.robustMatch(targetImage, offsetX, offsetY)) {
                     return true;
                 }
diff --git a/tests/media/jni/NativeCodecDecoderTest.cpp b/tests/media/jni/NativeCodecDecoderTest.cpp
index fabd6a5..d68a040 100644
--- a/tests/media/jni/NativeCodecDecoderTest.cpp
+++ b/tests/media/jni/NativeCodecDecoderTest.cpp
@@ -319,7 +319,7 @@
             mOutputBuff = loopCounter == 0 ? ref : test;
             mOutputBuff->reset();
             AMediaExtractor_seekTo(mExtractor, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
-            /* TODO(b/149981033) */
+            /* TODO(b/147348711) */
             /* Instead of create and delete codec at every iteration, we would like to create
              * once and use it for all iterations and delete before exiting */
             mCodec = AMediaCodec_createCodecByName(decoder);
@@ -437,7 +437,7 @@
         char log[1000];
         snprintf(log, sizeof(log), "codec: %s, file: %s, async mode: %s:: \n", decoder, testFile,
                  (isAsync ? "async" : "sync"));
-        /* TODO(b/149981033) */
+        /* TODO(b/147348711) */
         /* Instead of create and delete codec at every iteration, we would like to create
          * once and use it for all iterations and delete before exiting */
         mCodec = AMediaCodec_createCodecByName(decoder);
@@ -541,7 +541,7 @@
                  (isAsync ? "async" : "sync"));
         mOutputBuff = loopCounter == 0 ? ref : test;
         mOutputBuff->reset();
-        /* TODO(b/149981033) */
+        /* TODO(b/147348711) */
         /* Instead of create and delete codec at every iteration, we would like to create
          * once and use it for all iterations and delete before exiting */
         mCodec = AMediaCodec_createCodecByName(decoder);
@@ -605,7 +605,7 @@
                          (eosType ? "eos with last frame" : "eos separate"));
                 mOutputBuff = loopCounter == 0 ? ref : test;
                 mOutputBuff->reset();
-                /* TODO(b/149981033) */
+                /* TODO(b/147348711) */
                 /* Instead of create and delete codec at every iteration, we would like to create
                  * once and use it for all iterations and delete before exiting */
                 mCodec = AMediaCodec_createCodecByName(decoder);
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index a94bbe4..00f9131 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -170,7 +170,9 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -268,7 +270,9 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -341,7 +345,9 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -355,7 +361,9 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -374,7 +382,9 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index 32a6a91..16faa41 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -243,7 +243,9 @@
                     queueEOS();
                     waitForAllOutputs();
                     validateMetrics(mCodecName, format);
-                    mCodec.stop();
+                    /* TODO(b/147348711) */
+                    if (false) mCodec.stop();
+                    else mCodec.reset();
                     assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                     assertTrue(log + "no input sent", 0 != mInputCount);
                     assertTrue(log + "output received", 0 != mOutputCount);
@@ -369,7 +371,9 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -485,7 +489,9 @@
                 queueEOS();
                 waitForAllOutputs();
                 if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -509,7 +515,9 @@
                 queueEOS();
                 waitForAllOutputs();
                 if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -543,7 +551,9 @@
                 queueEOS();
                 waitForAllOutputs();
                 validateMetrics(mCodecName, newFormat);
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
@@ -672,7 +682,9 @@
                         queueEOS();
                         waitForAllOutputs();
                         validateMetrics(mCodecName);
-                        mCodec.stop();
+                        /* TODO(b/147348711) */
+                        if (false) mCodec.stop();
+                        else mCodec.reset();
                         assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                         assertTrue(log + "no input sent", 0 != mInputCount);
                         assertTrue(log + "output received", 0 != mOutputCount);
@@ -764,7 +776,9 @@
                 doWork(buffer, list);
                 queueEOS();
                 waitForAllOutputs();
-                mCodec.stop();
+                /* TODO(b/147348711) */
+                if (false) mCodec.stop();
+                else mCodec.reset();
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
                 assertTrue(log + "output received", 0 != mOutputCount);
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index ffa75f6..22d1083 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -496,7 +496,9 @@
                         mMuxer = null;
                     }
                 }
-                mDecoder.stop();
+                /* TODO(b/147348711) */
+                if (false) mDecoder.stop();
+                else mDecoder.reset();
                 /* TODO(b/147348711) */
                 if (false) mEncoder.stop();
                 else mEncoder.reset();
diff --git a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
index f81c30a..528b417 100644
--- a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
@@ -49,10 +49,14 @@
     // The bitrates are configured to large values. The content has zero motion, so in-time the
     // qp of the encoded clips shall drop down to < 10. Further the color bands are aligned to 2,
     // so from downsampling rgb24 to yuv420p, even if bilinear filters are used as opposed to
-    // skipping samples, we may not see large color loss. Hence allowable tolerance is kept to 5.
-    // until QP stabilizes, the tolerance is set at 7.
-    private final int TRANSIENT_STATE_COLOR_DELTA = 7;
-    private final int STEADY_STATE_COLOR_DELTA = 5;
+    // skipping samples, we may not see large color loss. Hence allowable tolerance is kept to 8.
+    // until QP stabilizes, the tolerance is set at 10.
+
+    // TODO (b/193192195) Initial delta values used in the tests were 7 and 5, but were increased
+    // to 10 and 8, as tests on emulator showed a higher delta. So the allowed delta values are
+    // increased for now
+    private final int TRANSIENT_STATE_COLOR_DELTA = 10;
+    private final int STEADY_STATE_COLOR_DELTA = 8;
     private final int[][] mColorBars = new int[][]{
             {66, 133, 244},
             {219, 68, 55},
diff --git a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
index 81e948e..7a9ce5e 100644
--- a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
@@ -19,10 +19,14 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
+import android.os.Build;
 import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -53,6 +57,8 @@
 
     private ArrayList<String> mCheckESList = new ArrayList<>();
 
+    private static boolean sIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
+
     public EncoderColorAspectsTest(String encoderName, String mime, int width, int height,
             int range, int standard, int transferCurve) {
         super(encoderName, mime, new int[]{64000}, new int[]{width}, new int[]{height});
@@ -132,6 +138,7 @@
     @SmallTest
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testColorAspects() throws IOException, InterruptedException {
+        Assume.assumeTrue("Test introduced with Android 11", sIsAtLeastR);
         setUpSource(mInputFile);
         mOutputBuff = new OutputManager();
         {
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index d99ff66..f24a4b1 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -32,6 +32,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
@@ -703,7 +704,6 @@
         setUpSource(mInputFile);
         mSaveToMem = true;
         String tempMuxedFile = File.createTempFile("tmp", ".out").getAbsolutePath();
-        int supportedCddCount = (cddSupportedMime ? profileCdd.length : 1);
         {
             mCodec = MediaCodec.createByCodecName(mCodecName);
             MediaCodecInfo.CodecCapabilities codecCapabilities =
@@ -722,12 +722,26 @@
                 if (!mIsAudio) format.setInteger(MediaFormat.KEY_LEVEL, level);
                 if (!codecCapabilities.isFormatSupported(format)) {
                     if (cddSupportedMime) {
+                        boolean shallSupportProfileLevel = false;
                         if (mIsAudio) {
                             for (int cddProfile : profileCdd) {
-                                if (profile == cddProfile) supportedCddCount--;
+                                if (profile == cddProfile) {
+                                    shallSupportProfileLevel = true;
+                                }
                             }
                         } else if (profile == profileCdd[0] && level == levelCdd) {
-                            supportedCddCount--;
+                            shallSupportProfileLevel = true;
+                        }
+
+                        // TODO (b/193173880) Check if there is at least one component that
+                        // supports this profile and level combination
+                        if (shallSupportProfileLevel) {
+                            ArrayList<MediaFormat> formats = new ArrayList<>();
+                            formats.add(format);
+                            assertFalse(
+                                    "No components support cdd requirement profile level with \n "
+                                            + "format :" + format + " for mime: " + mMime,
+                                    selectCodecs(mMime, formats, null, false).isEmpty());
                         }
                         Log.w(LOG_TAG,
                                 "Component: " + mCodecName + " doesn't support cdd format: " +
@@ -822,7 +836,5 @@
             mCodec.release();
         }
         new File(tempMuxedFile).delete();
-        assertFalse("No components support cdd requirement profile level for mime: " + mMime,
-                supportedCddCount == 0);
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/ExtractorTest.java b/tests/media/src/android/mediav2/cts/ExtractorTest.java
index 39f7a9d..b7840db 100644
--- a/tests/media/src/android/mediav2/cts/ExtractorTest.java
+++ b/tests/media/src/android/mediav2/cts/ExtractorTest.java
@@ -834,8 +834,6 @@
                     {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{
                             "bbb_cif_768kbps_30fps_mpeg4_stereo_48kHz_192kbps_flac.mp4",
                             "bbb_cif_768kbps_30fps_h263_stereo_48kHz_192kbps_flac.mkv",}},
-                    {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{
-                            "bbb_stereo_48kHz_192kbps_flac.flac",}},
                     {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"canon.mid",}},
                     {MediaFormat.MIMETYPE_AUDIO_AC3, new String[]{
                             "testac3mp4.mp4", "testac3ts.ts",}},
diff --git a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
index 9e26ef3..61fe054 100644
--- a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
@@ -42,6 +42,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
@@ -269,39 +270,43 @@
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testInitializationLatency() throws Exception {
         final int NUM_MEASUREMENTS = 5;
+        // Test gathers initialization latency for a number of iterations and
+        // percentile is a variable used to control how many of these iterations
+        // need to meet the pass criteria. For NUM_MEASUREMENTS at 5, sync and Async
+        // modes which is a total of 10 iterations, this translates to index 7.
+        final int percentile = 70;
         long expectedMaxCodecInitializationLatencyMs = mMime.startsWith("audio/") ?
                 MAX_AUDIOENC_INITIALIZATION_LATENCY_MS : MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
-        long minEncoderInitializationLatencyMs = Integer.MAX_VALUE;
-        long maxEncoderInitializationLatencyMs = 0;
         long sumOfEncoderInitializationLatencyMs = 0;
         int count = 0;
+        long[] encoderInitializationLatencyMs = new long[NUM_MEASUREMENTS * boolStates.length];
         for (int i = 0; i < NUM_MEASUREMENTS; i++) {
             for (boolean isAsync : boolStates) {
                 EncoderInitializationLatency encoderInitializationLatency =
                         new EncoderInitializationLatency(mMime, mEncoderName, isAsync);
-                long encoderInitializationLatencyMs = encoderInitializationLatency
-                        .calculateEncoderInitializationLatency();
-                String errorLog = String.format("CodecInitialization latency for mime: %s, " +
-                        "Encoder: %s, Iteration: %d, mode: %s, is not as expected. act/exp " +
-                        " in Ms :: %d/%d", mMime, mEncoderName, i, (isAsync ? "async" : "sync"),
-                        encoderInitializationLatencyMs, expectedMaxCodecInitializationLatencyMs);
-                assertTrue(errorLog,
-                        encoderInitializationLatencyMs <= expectedMaxCodecInitializationLatencyMs);
-                if (encoderInitializationLatencyMs < minEncoderInitializationLatencyMs) {
-                    minEncoderInitializationLatencyMs = encoderInitializationLatencyMs;
-                }
-                if (encoderInitializationLatencyMs > maxEncoderInitializationLatencyMs) {
-                    maxEncoderInitializationLatencyMs = encoderInitializationLatencyMs;
-                }
-                sumOfEncoderInitializationLatencyMs += encoderInitializationLatencyMs;
+                long latency = encoderInitializationLatency.calculateEncoderInitializationLatency();
+                encoderInitializationLatencyMs[count] = latency;
+                sumOfEncoderInitializationLatencyMs += latency;
                 count++;
             }
         }
+        Arrays.sort(encoderInitializationLatencyMs);
+
         String statsLog = String.format("CodecInitialization latency for mime: %s, " +
                 "Encoder: %s, in Ms :: ", mMime, mEncoderName);
-        Log.i(LOG_TAG, "Min " + statsLog + minEncoderInitializationLatencyMs);
-        Log.i(LOG_TAG, "Max " + statsLog + maxEncoderInitializationLatencyMs);
+        Log.i(LOG_TAG, "Min " + statsLog + encoderInitializationLatencyMs[0]);
+        Log.i(LOG_TAG, "Max " + statsLog + encoderInitializationLatencyMs[count - 1]);
         Log.i(LOG_TAG, "Avg " + statsLog + (sumOfEncoderInitializationLatencyMs / count));
+
+        String errorLog = String.format(
+                "CodecInitialization latency for mime: %s, Encoder: %s is not as expected. "
+                        + "act/exp in Ms :: %d/%d",
+                mMime, mEncoderName, encoderInitializationLatencyMs[percentile * count / 100],
+                expectedMaxCodecInitializationLatencyMs);
+        assertTrue(errorLog,
+                encoderInitializationLatencyMs[percentile * count / 100]
+                        <= expectedMaxCodecInitializationLatencyMs);
+
     }
 }
 
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index fbf1c19..80bdafe 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -39,6 +39,11 @@
     private static final String LOG_TAG = MultiCodecPerfTestBase.class.getSimpleName();
     static final boolean[] boolStates = {true, false};
     static final int REQUIRED_MIN_CONCURRENT_INSTANCES = 6;
+    static final int REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 = 2;
+    // allowed tolerance in measured fps vs expected fps in percentage, i.e. codecs achieving fps
+    // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as
+    // passing the test
+    static final double FPS_TOLERANCE_FACTOR = 0.95;
     static ArrayList<String> mMimeList = new ArrayList<String>();
     static Map<String, String> mTestFiles = new HashMap<>();
     static {
@@ -100,13 +105,21 @@
                     .getCapabilitiesForType(mimeCodecPair.first);
             List<PerformancePoint> pps = cap.getVideoCapabilities().getSupportedPerformancePoints();
             assertTrue(pps.size() > 0);
+
+            int requiredFrameRate = 180;
+            // VP9 requires 60 fps at 720p and minimum of 2 instances
+            if (mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+                requiredFrameRate = 60;
+            }
+
             maxInstances[loopCount] = cap.getMaxSupportedInstances();
-            PerformancePoint PP720p = new PerformancePoint(1280, 720, 180);
+            PerformancePoint PP720p = new PerformancePoint(1280, 720, requiredFrameRate);
+
             maxMacroBlockRates[loopCount] = 0;
-            boolean supports720p180Performance = false;
+            boolean supports720pPerformance = false;
             for (PerformancePoint pp : pps) {
-                if(pp.covers(PP720p)) {
-                    supports720p180Performance = true;
+                if (pp.covers(PP720p)) {
+                    supports720pPerformance = true;
                     if (pp.getMaxMacroBlockRate() > maxMacroBlockRates[loopCount]) {
                         maxMacroBlockRates[loopCount] = (int) pp.getMaxMacroBlockRate();
                         maxFrameRates[loopCount] = pp.getMaxFrameRate();
@@ -114,8 +127,8 @@
                 }
             }
             codec.release();
-            assertTrue("Codec " + mimeCodecPair.second + " doesn't support 720p 180 " +
-                    "performance point", supports720p180Performance);
+            assertTrue("Codec " + mimeCodecPair.second + " doesn't support 720p " +
+                    requiredFrameRate + " performance point", supports720pPerformance);
             loopCount++;
         }
         Arrays.sort(maxInstances);
@@ -124,7 +137,10 @@
         int minOfMaxInstances = maxInstances[0];
         int minOfMaxFrameRates = maxFrameRates[0];
         int minOfMaxMacroBlockRates = maxMacroBlockRates[0];
-        mMaxFrameRate = minOfMaxFrameRates;
+
+        // Allow a tolerance in expected frame rate
+        mMaxFrameRate = minOfMaxFrameRates * FPS_TOLERANCE_FACTOR;
+
         // Calculate how many 720p 30fps max instances it can support from it's mMaxFrameRate
         // amd maxMacroBlockRate. (720p is 3,600 macro blocks assuming 16x16 macroblocks)
         return Math.min(minOfMaxInstances, Math.min((int) (minOfMaxFrameRates / 30.0),
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index 938ae15..ddb7451 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -111,6 +111,7 @@
             achievedFrameRate += result.get();
         }
         assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate, achievedFrameRate >= mMaxFrameRate);
+                + "/" + mMaxFrameRate + " for " + maxInstances + " instances.",
+                achievedFrameRate >= mMaxFrameRate);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index ec329a8..4647719 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -15,7 +15,7 @@
  */
 
 package android.mediapc.cts;
-
+import android.media.MediaFormat;
 import android.util.Pair;
 
 import androidx.test.filters.LargeTest;
@@ -79,9 +79,13 @@
         ArrayList<Pair<String, String>> mimeDecoderPairs = new ArrayList<>();
         mimeDecoderPairs.add(Pair.create(mMime, mDecoderName));
         int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeDecoderPairs);
+        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
+        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
+        }
         assertTrue("Decoder " + mDecoderName + " unable to support minimum concurrent " +
-                "instances. act/exp: " + maxInstances + "/" + REQUIRED_MIN_CONCURRENT_INSTANCES,
-                maxInstances >= REQUIRED_MIN_CONCURRENT_INSTANCES);
+                "instances. act/exp: " + maxInstances + "/" + requiredMinInstances,
+                maxInstances >= requiredMinInstances);
         ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
         List<Decode> testList = new ArrayList<>();
         for (int i = 0; i < maxInstances; i++) {
@@ -93,6 +97,7 @@
             achievedFrameRate += result.get();
         }
         assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate, achievedFrameRate >= mMaxFrameRate);
+                + "/" + mMaxFrameRate + " for " + maxInstances + " instances.",
+                achievedFrameRate >= mMaxFrameRate);
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index a0c8421..969dc19 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -15,7 +15,7 @@
  */
 
 package android.mediapc.cts;
-
+import android.media.MediaFormat;
 import android.util.Pair;
 
 import androidx.test.filters.LargeTest;
@@ -78,9 +78,13 @@
         ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>();
         mimeEncoderPairs.add(Pair.create(mMime, mEncoderName));
         int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeEncoderPairs);
+        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
+        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
+        }
         assertTrue("Encoder " + mEncoderName + " unable to support minimum concurrent " +
-                "instances. act/exp: " + maxInstances + "/" + REQUIRED_MIN_CONCURRENT_INSTANCES,
-                maxInstances >= REQUIRED_MIN_CONCURRENT_INSTANCES);
+                "instances. act/exp: " + maxInstances + "/" + requiredMinInstances,
+                maxInstances >= requiredMinInstances);
         ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
         List<Encode> testList = new ArrayList<>();
         for (int i = 0; i < maxInstances; i++) {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index 1686ecd..4854853 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -15,7 +15,7 @@
  */
 
 package android.mediapc.cts;
-
+import android.media.MediaFormat;
 import android.util.Pair;
 import android.view.Surface;
 
@@ -103,11 +103,15 @@
         mimeCodecPairs.add(mDecoderPair);
         mimeCodecPairs.add(mEncoderPair);
         int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeCodecPairs);
+        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES / 2;
+        if (mDecoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)
+                || mEncoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 / 2;
+        }
         assertTrue("DecodeMime: " + mDecoderPair.first + ", Decoder " + mDecoderPair.second +
                 ", EncodeMime: " + mEncoderPair.first + ", Encoder: " + mEncoderPair.second +
-                ", unable to support minimum concurrent instances. act/exp: " + maxInstances + "/" +
-                (REQUIRED_MIN_CONCURRENT_INSTANCES / 2),
-                maxInstances >= (REQUIRED_MIN_CONCURRENT_INSTANCES / 2));
+                ", unable to support minimum concurrent instances. act/exp: " + maxInstances +
+                "/" + requiredMinInstances, maxInstances >= requiredMinInstances);
         ExecutorService pool = Executors.newFixedThreadPool(maxInstances / 2 + maxInstances % 2);
         List<Transcode> transcodeList = new ArrayList<>();
         for (int i = 0; i < maxInstances / 2 ; i++) {
@@ -137,6 +141,7 @@
             }
         }
         assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate
-                + "/" + mMaxFrameRate / 2, achievedFrameRate >= mMaxFrameRate / 2);
+                + "/" + mMaxFrameRate / 2 + " for " + maxInstances + " instances.",
+                achievedFrameRate >= mMaxFrameRate / 2);
     }
 }
diff --git a/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java b/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
index e00de5b..369bc31 100644
--- a/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
@@ -30,6 +30,7 @@
 import android.car.Car;
 import android.car.media.CarAudioManager;
 import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Pair;
 import android.view.KeyEvent;
 
@@ -49,6 +50,7 @@
 import java.util.regex.Pattern;
 
 @RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant Apps cannot get car related permissions")
 public final class CarAudioManagerTest extends CarApiTestBase {
 
     private static long WAIT_TIMEOUT_SECS = 5;
diff --git a/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java b/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
index cb0ac55..4cb1019 100644
--- a/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
@@ -23,6 +23,7 @@
 import android.car.hardware.power.CarPowerPolicy;
 import android.car.hardware.power.CarPowerPolicyFilter;
 import android.car.hardware.power.PowerComponent;
+import android.platform.test.annotations.AppModeFull;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.annotation.Nullable;
@@ -40,12 +41,14 @@
 import java.util.concurrent.TimeUnit;
 
 @SmallTest
+@AppModeFull(reason = "Instant Apps cannot get car related permissions")
 public final class CarPowerManagerTest extends CarApiTestBase {
     private static String TAG = CarPowerManagerTest.class.getSimpleName();
     private static final int LISTENER_WAIT_TIME_MS = 1000;
     private static final int NO_WAIT = 0;
 
     private CarPowerManager mCarPowerManager;
+    private String mInitialPowerPolicyId;
     private final Executor mExecutor = mContext.getMainExecutor();
 
     @Override
@@ -53,6 +56,15 @@
     public void setUp() throws Exception {
         super.setUp();
         mCarPowerManager = (CarPowerManager) getCar().getCarManager(Car.POWER_SERVICE);
+        mInitialPowerPolicyId = mCarPowerManager.getCurrentPowerPolicy().getPolicyId();
+    }
+
+    @After
+    public void teardown() throws Exception {
+        CarPowerPolicy policy = mCarPowerManager.getCurrentPowerPolicy();
+        if (!mInitialPowerPolicyId.equals(policy.getPolicyId())) {
+            applyPowerPolicy(mInitialPowerPolicyId);
+        }
     }
 
     /**
@@ -96,6 +108,8 @@
         makeSureExecutorReady();
         assertWithMessage("Added location listener's current policy")
                 .that(listenerLocation.getCurrentPolicyId(NO_WAIT)).isNull();
+
+        applyPowerPolicy(mInitialPowerPolicyId);
     }
 
     private void makeSureExecutorReady() throws Exception {
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index a68e0ec..bfa2304 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.junit.Assume.assumeNotNull;
 import static org.testng.Assert.assertThrows;
 
 import android.car.Car;
@@ -27,11 +26,11 @@
 import android.car.VehicleAreaType;
 import android.car.VehicleAreaWheel;
 import android.car.VehiclePropertyIds;
+import android.car.cts.utils.VehiclePropertyVerifier;
 import android.car.hardware.CarPropertyConfig;
 import android.car.hardware.CarPropertyValue;
 import android.car.hardware.property.CarPropertyManager;
 import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
-import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -68,6 +67,52 @@
     private final ArraySet<Integer> mPropertyIds = new ArraySet<>();
     private CarPropertyManager mCarPropertyManager;
 
+    private static void verifyWheelTickConfigArray(int supportedWheels, int wheelToVerify,
+            int configArrayIndex, int wheelTicksToUm) {
+        if ((supportedWheels & wheelToVerify) != 0) {
+            assertWithMessage(
+                    "WHEEL_TICK configArray[" + configArrayIndex
+                            + "] must specify the ticks to micrometers for " + wheelToString(
+                            wheelToVerify))
+                    .that(wheelTicksToUm)
+                    .isGreaterThan(0);
+        } else {
+            assertWithMessage(
+                    "WHEEL_TICK configArray[" + configArrayIndex + "] should be zero since "
+                            + wheelToString(wheelToVerify)
+                            + "is not supported")
+                    .that(wheelTicksToUm)
+                    .isEqualTo(0);
+        }
+    }
+
+    private static void verifyWheelTickValue(int supportedWheels, int wheelToVerify,
+            int valueIndex, Long ticks) {
+        if ((supportedWheels & wheelToVerify) == 0) {
+            assertWithMessage(
+                    "WHEEL_TICK value[" + valueIndex + "] should be zero since "
+                            + wheelToString(wheelToVerify)
+                            + "is not supported")
+                    .that(ticks)
+                    .isEqualTo(0);
+        }
+    }
+
+    private static String wheelToString(int wheel) {
+        switch (wheel) {
+            case VehicleAreaWheel.WHEEL_LEFT_FRONT:
+                return "WHEEL_LEFT_FRONT";
+            case VehicleAreaWheel.WHEEL_RIGHT_FRONT:
+                return "WHEEL_RIGHT_FRONT";
+            case VehicleAreaWheel.WHEEL_RIGHT_REAR:
+                return "WHEEL_RIGHT_REAR";
+            case VehicleAreaWheel.WHEEL_LEFT_REAR:
+                return "WHEEL_LEFT_REAR";
+            default:
+                return Integer.toString(wheel);
+        }
+    }
+
     @Before
     public void setUp() throws Exception {
         super.setUp();
@@ -136,173 +181,108 @@
     @CddTest(requirement = "2.5.1")
     @Test
     public void testMustSupportGearSelection() {
-        verifyOnchangeCarPropertyConfig(/*requiredProperty=*/true,
-                VehiclePropertyIds.GEAR_SELECTION,
-                Integer.class);
-        CarPropertyConfig gearSelectionConfig =
-                mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.GEAR_SELECTION);
-        List<Integer> gearSelectionArray = gearSelectionConfig.getConfigArray();
-        assertWithMessage("GEAR_SELECTION config array must specify supported gears")
-                .that(gearSelectionArray.size())
-                .isGreaterThan(0);
-
-        verifyCarPropertyValue(VehiclePropertyIds.GEAR_SELECTION, Integer.class);
-        CarPropertyValue<Integer> gearSelectionValue =
-                mCarPropertyManager.getProperty(
-                        VehiclePropertyIds.GEAR_SELECTION,
-                        VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
-        assertWithMessage("GEAR_SELECTION Integer value must be in configArray")
-                .that(gearSelectionArray.contains(gearSelectionValue.getValue())).isTrue();
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.GEAR_SELECTION,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Integer.class).requireProperty().setConfigArrayVerifier(
+                configArray -> assertWithMessage(
+                        "GEAR_SELECTION config array must specify supported gears")
+                        .that(configArray.size())
+                        .isGreaterThan(0)).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> assertWithMessage(
+                        "GEAR_SELECTION Integer value must be listed as supported gear in "
+                                + "configArray")
+                        .that(carPropertyConfig.getConfigArray().contains(
+                                carPropertyValue.getValue())).isTrue())
+                .build().verify(mCarPropertyManager);
     }
 
     @CddTest(requirement = "2.5.1")
     @Test
     public void testMustSupportNightMode() {
-        verifyOnchangeCarPropertyConfig(/*requiredProperty=*/true,
-                VehiclePropertyIds.NIGHT_MODE,
-                Boolean.class);
-
-        verifyCarPropertyValue(VehiclePropertyIds.NIGHT_MODE, Boolean.class);
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.NIGHT_MODE,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).requireProperty().build().verify(mCarPropertyManager);
     }
 
     @CddTest(requirement = "2.5.1")
     @Test
     public void testMustSupportPerfVehicleSpeed() {
-        verifyContinuousCarPropertyConfig(/*requiredProperty=*/true,
-                VehiclePropertyIds.PERF_VEHICLE_SPEED,
-                Float.class);
-
-        verifyCarPropertyValue(VehiclePropertyIds.PERF_VEHICLE_SPEED, Float.class);
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PERF_VEHICLE_SPEED,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Float.class).requireProperty().build().verify(mCarPropertyManager);
     }
 
     @CddTest(requirement = "2.5.1")
     @Test
     public void testMustSupportParkingBrakeOn() {
-        verifyOnchangeCarPropertyConfig(/*requiredProperty=*/true,
-                VehiclePropertyIds.PARKING_BRAKE_ON,
-                Boolean.class);
-
-        verifyCarPropertyValue(VehiclePropertyIds.PARKING_BRAKE_ON, Boolean.class);
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.PARKING_BRAKE_ON,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                Boolean.class).requireProperty().build().verify(mCarPropertyManager);
     }
 
     @Test
     public void testWheelTickIfSupported() {
-        verifyContinuousCarPropertyConfig(/*requiredProperty=*/false,
-                VehiclePropertyIds.WHEEL_TICK,
-                Long[].class);
+        VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.WHEEL_TICK,
+                CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
+                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+                CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS,
+                Long[].class).setConfigArrayVerifier(
+                configArray -> {
+                    assertWithMessage("WHEEL_TICK config array must be size 5")
+                            .that(configArray.size())
+                            .isEqualTo(5);
 
-        CarPropertyConfig wheelTickConfig =
-                mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.WHEEL_TICK);
-        List<Integer> wheelTickConfigArray = wheelTickConfig.getConfigArray();
-        assertWithMessage("WHEEL_TICK config array must be size 5")
-                .that(wheelTickConfigArray.size())
-                .isEqualTo(5);
+                    int supportedWheels = configArray.get(0);
+                    assertWithMessage(
+                            "WHEEL_TICK config array first element specifies which wheels are"
+                                    + " supported")
+                            .that(supportedWheels).isGreaterThan(
+                            VehicleAreaWheel.WHEEL_UNKNOWN);
+                    assertWithMessage(
+                            "WHEEL_TICK config array first element specifies which wheels are"
+                                    + " supported")
+                            .that(supportedWheels)
+                            .isAtMost(VehicleAreaWheel.WHEEL_LEFT_FRONT
+                                    | VehicleAreaWheel.WHEEL_RIGHT_FRONT |
+                                    VehicleAreaWheel.WHEEL_LEFT_REAR
+                                    | VehicleAreaWheel.WHEEL_RIGHT_REAR);
 
-        int supportedWheels = wheelTickConfigArray.get(0);
-        assertWithMessage(
-                "WHEEL_TICK config array first element specifies which wheels are supported")
-                .that(supportedWheels).isGreaterThan(VehicleAreaWheel.WHEEL_UNKNOWN);
-        assertWithMessage(
-                "WHEEL_TICK config array first element specifies which wheels are supported")
-                .that(supportedWheels)
-                .isAtMost(VehicleAreaWheel.WHEEL_LEFT_FRONT | VehicleAreaWheel.WHEEL_RIGHT_FRONT |
-                        VehicleAreaWheel.WHEEL_LEFT_REAR | VehicleAreaWheel.WHEEL_RIGHT_REAR);
+                    verifyWheelTickConfigArray(supportedWheels,
+                            VehicleAreaWheel.WHEEL_LEFT_FRONT, 1, configArray.get(1));
+                    verifyWheelTickConfigArray(supportedWheels,
+                            VehicleAreaWheel.WHEEL_RIGHT_FRONT, 2, configArray.get(2));
+                    verifyWheelTickConfigArray(supportedWheels,
+                            VehicleAreaWheel.WHEEL_RIGHT_REAR, 3, configArray.get(3));
+                    verifyWheelTickConfigArray(supportedWheels,
+                            VehicleAreaWheel.WHEEL_LEFT_REAR, 4, configArray.get(4));
+                }).setCarPropertyValueVerifier(
+                (carPropertyConfig, carPropertyValue) -> {
+                    List<Integer> wheelTickConfigArray = carPropertyConfig.getConfigArray();
+                    int supportedWheels = wheelTickConfigArray.get(0);
 
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_LEFT_FRONT) != 0) {
-            assertWithMessage(
-                    "WHEEL_TICK config array second element specifies ticks to micrometers for "
-                            + "front left wheel")
-                    .that(wheelTickConfigArray.get(1))
-                    .isGreaterThan(0);
-        } else {
-            assertWithMessage(
-                    "WHEEL_TICK config array second element should be zero since front left wheel"
-                            + " is not supported")
-                    .that(wheelTickConfigArray.get(1))
-                    .isEqualTo(0);
-        }
+                    Long[] wheelTicks = (Long[]) carPropertyValue.getValue();
+                    assertWithMessage("WHEEL_TICK Long[] value must be size 5").that(
+                            wheelTicks.length)
+                            .isEqualTo(5);
 
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_RIGHT_FRONT) != 0) {
-            assertWithMessage(
-                    "WHEEL_TICK config array third element specifies ticks to micrometers for "
-                            + "front right wheel")
-                    .that(wheelTickConfigArray.get(2))
-                    .isGreaterThan(0);
-        } else {
-            assertWithMessage(
-                    "WHEEL_TICK config array third element should be zero since front right wheel"
-                            + " is not supported")
-                    .that(wheelTickConfigArray.get(2))
-                    .isEqualTo(0);
-        }
+                    verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_LEFT_FRONT, 1,
+                            wheelTicks[1]);
+                    verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_RIGHT_FRONT, 2,
+                            wheelTicks[2]);
+                    verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_RIGHT_REAR, 3,
+                            wheelTicks[3]);
+                    verifyWheelTickValue(supportedWheels, VehicleAreaWheel.WHEEL_LEFT_REAR, 4,
+                            wheelTicks[4]);
+                }).build().verify(mCarPropertyManager);
 
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_RIGHT_REAR) != 0) {
-            assertWithMessage(
-                    "WHEEL_TICK config array fourth element specifies ticks to micrometers for "
-                            + "rear right wheel")
-                    .that(wheelTickConfigArray.get(3))
-                    .isGreaterThan(0);
-        } else {
-            assertWithMessage(
-                    "WHEEL_TICK config array fourth element should be zero since rear right wheel"
-                            + " is not supported")
-                    .that(wheelTickConfigArray.get(3))
-                    .isEqualTo(0);
-        }
-
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_LEFT_REAR) != 0) {
-            assertWithMessage(
-                    "WHEEL_TICK config array fifth element specifies ticks to micrometers for "
-                            + "rear left wheel")
-                    .that(wheelTickConfigArray.get(4))
-                    .isGreaterThan(0);
-        } else {
-            assertWithMessage(
-                    "WHEEL_TICK config array fifth element should be zero since rear left wheel "
-                            + "is not supported")
-                    .that(wheelTickConfigArray.get(4))
-                    .isEqualTo(0);
-        }
-
-        verifyCarPropertyValue(VehiclePropertyIds.WHEEL_TICK, Long[].class);
-        CarPropertyValue<Long[]> wheelTickValue =
-                mCarPropertyManager.getProperty(
-                        VehiclePropertyIds.WHEEL_TICK, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
-        Long[] wheelTicks = wheelTickValue.getValue();
-        assertWithMessage("WHEEL_TICK Long[] value must be size 5").that(wheelTicks.length)
-                .isEqualTo(5);
-
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_LEFT_FRONT) == 0) {
-            assertWithMessage(
-                    "WHEEL_TICK value array second element should be zero since front left wheel "
-                            + "is not supported")
-                    .that(wheelTicks[1])
-                    .isEqualTo(0);
-        }
-
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_RIGHT_FRONT) == 0) {
-            assertWithMessage(
-                    "WHEEL_TICK value array third element should be zero since front right wheel "
-                            + "is not supported")
-                    .that(wheelTicks[2])
-                    .isEqualTo(0);
-        }
-
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_RIGHT_REAR) == 0) {
-            assertWithMessage(
-                    "WHEEL_TICK value array fourth element should be zero since rear right wheel "
-                            + "is not supported")
-                    .that(wheelTicks[3])
-                    .isEqualTo(0);
-        }
-
-        if ((supportedWheels & VehicleAreaWheel.WHEEL_LEFT_REAR) == 0) {
-            assertWithMessage(
-                    "WHEEL_TICK value array fifth element should be zero since rear left wheel is"
-                            + " not supported")
-                    .that(wheelTicks[4])
-                    .isEqualTo(0);
-        }
     }
 
     @SuppressWarnings("unchecked")
@@ -548,89 +528,6 @@
         }
     }
 
-    private <T> void verifyCarPropertyConfig(boolean requiredProperty,
-            int propertyId,
-            Class<T> propertyType) {
-        String propertyName = VehiclePropertyIds.toString(propertyId);
-        CarPropertyConfig carPropertyConfig = mCarPropertyManager.getCarPropertyConfig(propertyId);
-        if (requiredProperty) {
-            assertWithMessage("Must support " + propertyName).that(carPropertyConfig)
-                    .isNotNull();
-        } else {
-            assumeNotNull(carPropertyConfig);
-        }
-        assertWithMessage(propertyName + " CarPropertyConfig must have correct property ID")
-                .that(carPropertyConfig.getPropertyId())
-                .isEqualTo(propertyId);
-        assertWithMessage(propertyName + " must be READ access")
-                .that(carPropertyConfig.getAccess())
-                .isEqualTo(CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ);
-        assertWithMessage(propertyName + " must be GLOBAL area type")
-                .that(carPropertyConfig.getAreaType())
-                .isEqualTo(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
-        assertWithMessage(propertyName + " must be " + propertyType + " type property")
-                .that(carPropertyConfig.getPropertyType()).isEqualTo(propertyType);
-    }
-
-    private <T> void verifyContinuousCarPropertyConfig(boolean requiredProperty,
-            int propertyId,
-            Class<T> propertyType) {
-        verifyCarPropertyConfig(requiredProperty, propertyId, propertyType);
-        String propertyName = VehiclePropertyIds.toString(propertyId);
-        CarPropertyConfig carPropertyConfig = mCarPropertyManager.getCarPropertyConfig(propertyId);
-        assertWithMessage(propertyName + " must be CONTINUOUS change mode type")
-                .that(carPropertyConfig.getChangeMode())
-                .isEqualTo(CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS);
-        assertWithMessage(propertyName + " must define max sample rate since it is CONTINUOUS")
-                .that(carPropertyConfig.getMaxSampleRate()).isGreaterThan(0);
-        assertWithMessage(propertyName + " must define min sample rate since it is CONTINUOUS")
-                .that(carPropertyConfig.getMinSampleRate()).isGreaterThan(0);
-        assertWithMessage("PERF_VEHICLE_SPEED max sample rate must be >= min sample rate")
-                .that(carPropertyConfig.getMaxSampleRate() >=
-                        carPropertyConfig.getMinSampleRate())
-                .isTrue();
-    }
-
-    private <T> void verifyOnchangeCarPropertyConfig(boolean requiredProperty,
-            int propertyId,
-            Class<T> propertyType) {
-        verifyCarPropertyConfig(requiredProperty, propertyId, propertyType);
-        String propertyName = VehiclePropertyIds.toString(propertyId);
-        CarPropertyConfig carPropertyConfig = mCarPropertyManager.getCarPropertyConfig(propertyId);
-        assertWithMessage(propertyName + " must be ONCHANGE change mode type")
-                .that(carPropertyConfig.getChangeMode())
-                .isEqualTo(CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE);
-        assertWithMessage(propertyName + " must define max sample rate as 0 since it is ONCHANGE")
-                .that(carPropertyConfig.getMaxSampleRate()).isEqualTo(0);
-        assertWithMessage(propertyName + " must define min sample rate as 0 since it is ONCHANGE")
-                .that(carPropertyConfig.getMinSampleRate()).isEqualTo(0);
-    }
-
-    private <T> void verifyCarPropertyValue(int propertyId, Class<?> propertyClass) {
-        String propertyName = VehiclePropertyIds.toString(propertyId);
-        long beforeElapsedTimestampNanos = SystemClock.elapsedRealtimeNanos();
-        CarPropertyValue<T> carPropertyValue =
-                mCarPropertyManager.getProperty(
-                        propertyId, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
-        long afterElapsedTimestampNanos = SystemClock.elapsedRealtimeNanos();
-        assertWithMessage(propertyName + " value must have correct property ID")
-                .that(carPropertyValue.getPropertyId()).isEqualTo(propertyId);
-        assertWithMessage(propertyName + " value must have correct area type")
-                .that(carPropertyValue.getAreaId())
-                .isEqualTo(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
-        assertWithMessage(propertyName + " value must be available")
-                .that(carPropertyValue.getStatus()).isEqualTo(CarPropertyValue.STATUS_AVAILABLE);
-        assertWithMessage(propertyName +
-                " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
-                .that(carPropertyValue.getTimestamp())
-                .isGreaterThan(beforeElapsedTimestampNanos);
-        assertWithMessage(propertyName +
-                " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
-                .that(carPropertyValue.getTimestamp()).isLessThan(afterElapsedTimestampNanos);
-        assertWithMessage(propertyName + " must return " + propertyClass + " type value")
-                .that(carPropertyValue.getValue().getClass()).isEqualTo(propertyClass);
-    }
-
     private static class CarPropertyEventCounter implements CarPropertyEventCallback {
         private final Object mLock = new Object();
         @GuardedBy("mLock")
diff --git a/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java b/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java
index 5b03606..3cc15ed 100644
--- a/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarWatchdogManagerTest.java
@@ -30,6 +30,7 @@
 import android.content.Context;
 import android.os.Process;
 import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -45,7 +46,7 @@
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.util.concurrent.atomic.AtomicReference;
-
+@AppModeFull(reason = "Instant Apps cannot get car related permissions")
 public class CarWatchdogManagerTest extends CarApiTestBase {
     private static final String TAG = CarWatchdogManagerTest.class.getSimpleName();
     private static final String CAR_WATCHDOG_SERVICE_NAME
diff --git a/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java b/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java
index 49fa9dd..4d00ea9 100644
--- a/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java
+++ b/tests/tests/car/src/android/car/cts/VehiclePropertyIdsTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.car.VehicleGear;
 import android.car.VehiclePropertyIds;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -39,6 +38,22 @@
 public class VehiclePropertyIdsTest {
     private static final String TAG = "VehiclePropertyIdsTest";
 
+    // Get all enums from the class.
+    private static List<Integer> getIntegersFromDataEnums() {
+        Field[] fields = VehiclePropertyIds.class.getDeclaredFields();
+        List<Integer> integerList = new ArrayList<>(5);
+        for (Field f : fields) {
+            if (f.getType() == int.class) {
+                try {
+                    integerList.add(f.getInt(VehiclePropertyIds.class));
+                } catch (IllegalAccessException | RuntimeException e) {
+                    Log.w(TAG, "Failed to get value");
+                }
+            }
+        }
+        return integerList;
+    }
+
     /**
      * Test for {@link VehiclePropertyIds#toString()}
      */
@@ -316,26 +331,10 @@
      */
     @Test
     public void testAllPropertiesAreMappedInToString() {
-        List<Integer> systemProperties = getIntegersFromDataEnums(
-                new VehiclePropertyIds().getClass());
+        List<Integer> systemProperties = getIntegersFromDataEnums();
         for (int propertyId : systemProperties) {
             String propertyString = VehiclePropertyIds.toString(propertyId);
             assertThat(propertyString.startsWith("0x")).isFalse();
         }
     }
-    // Get all enums from the class.
-    private static List<Integer> getIntegersFromDataEnums(Class clazz) {
-        Field[] fields = clazz.getDeclaredFields();
-        List<Integer> integerList = new ArrayList<>(5);
-        for (Field f : fields) {
-            if (f.getType() == int.class) {
-                try {
-                    integerList.add(f.getInt(clazz));
-                } catch (IllegalAccessException | RuntimeException e) {
-                    Log.w(TAG, "Failed to get value");
-                }
-            }
-        }
-        return integerList;
-    }
 }
diff --git a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
new file mode 100644
index 0000000..cb713d4
--- /dev/null
+++ b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2021 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.car.cts.utils;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeNotNull;
+
+import android.car.VehicleAreaType;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyManager;
+import android.os.SystemClock;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.util.List;
+import java.util.Optional;
+
+public class VehiclePropertyVerifier<T> {
+    private final int mPropertyId;
+    private final String mPropertyName;
+    private final int mAccess;
+    private final int mAreaType;
+    private final int mChangeMode;
+    private final Class<T> mPropertyType;
+    private final boolean mRequiredProperty;
+    private final Optional<ConfigArrayVerifier> mConfigArrayVerifier;
+    private final Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier;
+
+    private VehiclePropertyVerifier(int propertyId, int access, int areaType, int changeMode,
+            Class<T> propertyType, boolean requiredProperty,
+            Optional<ConfigArrayVerifier> configArrayVerifier,
+            Optional<CarPropertyValueVerifier> carPropertyValueVerifier) {
+        mPropertyId = propertyId;
+        mPropertyName = VehiclePropertyIds.toString(propertyId);
+        mAccess = access;
+        mAreaType = areaType;
+        mChangeMode = changeMode;
+        mPropertyType = propertyType;
+        mRequiredProperty = requiredProperty;
+        mConfigArrayVerifier = configArrayVerifier;
+        mCarPropertyValueVerifier = carPropertyValueVerifier;
+    }
+
+    public static <T> Builder<T> newBuilder(int propertyId, int access, int areaType,
+            int changeMode,
+            Class<T> propertyType) {
+        return new Builder<>(propertyId, access, areaType, changeMode, propertyType);
+    }
+
+    private static String accessToString(int access) {
+        switch (access) {
+            case CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_NONE:
+                return "VEHICLE_PROPERTY_ACCESS_NONE";
+            case CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ:
+                return "VEHICLE_PROPERTY_ACCESS_READ";
+            case CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE:
+                return "VEHICLE_PROPERTY_ACCESS_WRITE";
+            case CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE:
+                return "VEHICLE_PROPERTY_ACCESS_READ_WRITE";
+            default:
+                return Integer.toString(access);
+        }
+    }
+
+    private static String areaTypeToString(int areaType) {
+        switch (areaType) {
+            case VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL:
+                return "VEHICLE_AREA_TYPE_GLOBAL";
+            case VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW:
+                return "VEHICLE_AREA_TYPE_WINDOW";
+            case VehicleAreaType.VEHICLE_AREA_TYPE_DOOR:
+                return "VEHICLE_AREA_TYPE_DOOR";
+            case VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR:
+                return "VEHICLE_AREA_TYPE_MIRROR";
+            case VehicleAreaType.VEHICLE_AREA_TYPE_SEAT:
+                return "VEHICLE_AREA_TYPE_SEAT";
+            case VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL:
+                return "VEHICLE_AREA_TYPE_WHEEL";
+            default:
+                return Integer.toString(areaType);
+        }
+    }
+
+    private static String changeModeToString(int changeMode) {
+        switch (changeMode) {
+            case CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC:
+                return "VEHICLE_PROPERTY_CHANGE_MODE_STATIC";
+            case CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE:
+                return "VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE";
+            case CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS:
+                return "VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS";
+            default:
+                return Integer.toString(changeMode);
+        }
+    }
+
+    public void verify(CarPropertyManager carPropertyManager) {
+        CarPropertyConfig<?> carPropertyConfig = carPropertyManager.getCarPropertyConfig(
+                mPropertyId);
+        if (mRequiredProperty) {
+            assertWithMessage("Must support " + mPropertyName).that(carPropertyConfig)
+                    .isNotNull();
+        } else {
+            assumeNotNull(carPropertyConfig);
+        }
+
+        verifyCarPropertyConfig(carPropertyConfig);
+        verifyCarPropertyValue(carPropertyConfig, carPropertyManager);
+    }
+
+    private void verifyCarPropertyConfig(CarPropertyConfig<?> carPropertyConfig) {
+        assertWithMessage(mPropertyName + " CarPropertyConfig must have correct property ID")
+                .that(carPropertyConfig.getPropertyId())
+                .isEqualTo(mPropertyId);
+        assertWithMessage(mPropertyName + " must be " + accessToString(mAccess))
+                .that(carPropertyConfig.getAccess())
+                .isEqualTo(mAccess);
+        assertWithMessage(mPropertyName + " must be " + areaTypeToString(mAreaType))
+                .that(carPropertyConfig.getAreaType())
+                .isEqualTo(mAreaType);
+        assertWithMessage(mPropertyName + " must be " + changeModeToString(mChangeMode))
+                .that(carPropertyConfig.getChangeMode())
+                .isEqualTo(mChangeMode);
+        assertWithMessage(mPropertyName + " must be " + mPropertyType + " type property")
+                .that(carPropertyConfig.getPropertyType()).isEqualTo(mPropertyType);
+
+        if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) {
+            assertWithMessage(
+                    mPropertyName + "'s AreaIds must contain a single 0 since it is "
+                            + areaTypeToString(mAreaType))
+                    .that(carPropertyConfig.getAreaIds()).isEqualTo(new int[]{0});
+        }
+
+        if (mChangeMode == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) {
+            verifyContinuousCarPropertyConfig(carPropertyConfig);
+        } else {
+            verifyNonContinuousCarPropertyConfig(carPropertyConfig);
+        }
+
+        if (mConfigArrayVerifier.isPresent()) {
+            mConfigArrayVerifier.get().verify(carPropertyConfig.getConfigArray());
+        } else {
+            assertWithMessage(mPropertyName + " configArray is undefined, so it must be empty")
+                    .that(carPropertyConfig.getConfigArray().size()).isEqualTo(0);
+        }
+    }
+
+    private void verifyContinuousCarPropertyConfig(CarPropertyConfig<?> carPropertyConfig) {
+        assertWithMessage(
+                mPropertyName + " must define max sample rate since change mode is "
+                        + changeModeToString(mChangeMode))
+                .that(carPropertyConfig.getMaxSampleRate()).isGreaterThan(0);
+        assertWithMessage(
+                mPropertyName + " must define min sample rate since change mode is "
+                        + changeModeToString(mChangeMode))
+                .that(carPropertyConfig.getMinSampleRate()).isGreaterThan(0);
+        assertWithMessage(mPropertyName + " max sample rate must be >= min sample rate")
+                .that(carPropertyConfig.getMaxSampleRate() >=
+                        carPropertyConfig.getMinSampleRate())
+                .isTrue();
+    }
+
+    private void verifyNonContinuousCarPropertyConfig(CarPropertyConfig<?> carPropertyConfig) {
+        assertWithMessage(mPropertyName + " must define max sample rate as 0 since change mode is "
+                + changeModeToString(mChangeMode))
+                .that(carPropertyConfig.getMaxSampleRate()).isEqualTo(0);
+        assertWithMessage(mPropertyName + " must define min sample rate as 0 since change mode is "
+                + changeModeToString(mChangeMode))
+                .that(carPropertyConfig.getMinSampleRate()).isEqualTo(0);
+    }
+
+    private void verifyCarPropertyValue(CarPropertyConfig<?> carPropertyConfig,
+            CarPropertyManager carPropertyManager) {
+        for (int areaId : carPropertyConfig.getAreaIds()) {
+            CarPropertyValue<?> carPropertyValue =
+                    carPropertyManager.getProperty(
+                            mPropertyId, areaId);
+            long afterElapsedTimestampNanos = SystemClock.elapsedRealtimeNanos();
+            assertWithMessage(
+                    mPropertyName + " - areaId: " + areaId + " value must have correct property ID")
+                    .that(carPropertyValue.getPropertyId()).isEqualTo(mPropertyId);
+            assertWithMessage(
+                    mPropertyName + " - areaId: " + areaId + " value must have correct area id: "
+                            + areaId)
+                    .that(carPropertyValue.getAreaId())
+                    .isEqualTo(areaId);
+            assertWithMessage(
+                    mPropertyName + " - areaId: " + areaId + " value's status must be valid")
+                    .that(carPropertyValue.getStatus()).isIn(
+                    ImmutableSet.of(CarPropertyValue.STATUS_AVAILABLE,
+                            CarPropertyValue.STATUS_UNAVAILABLE, CarPropertyValue.STATUS_ERROR));
+            assertWithMessage(mPropertyName + " - areaId: " + areaId +
+                    " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
+                    .that(carPropertyValue.getTimestamp()).isAtLeast(0);
+            assertWithMessage(mPropertyName + " - areaId: " + areaId +
+                    " timestamp must use the SystemClock.elapsedRealtimeNanos() time base")
+                    .that(carPropertyValue.getTimestamp()).isLessThan(afterElapsedTimestampNanos);
+            assertWithMessage(
+                    mPropertyName + " - areaId: " + areaId + " must return " + mPropertyType
+                            + " type value")
+                    .that(carPropertyValue.getValue().getClass()).isEqualTo(mPropertyType);
+
+            mCarPropertyValueVerifier.ifPresent(
+                    propertyValueVerifier -> propertyValueVerifier.verify(carPropertyConfig,
+                            carPropertyValue));
+        }
+    }
+
+    public interface ConfigArrayVerifier {
+        void verify(List<Integer> configArray);
+    }
+
+    public interface CarPropertyValueVerifier {
+        void verify(CarPropertyConfig<?> carPropertyConfig, CarPropertyValue<?> carPropertyValue);
+    }
+
+    public static class Builder<T> {
+        private final int mPropertyId;
+        private final int mAccess;
+        private final int mAreaType;
+        private final int mChangeMode;
+        private final Class<T> mPropertyType;
+        private boolean mRequiredProperty = false;
+        private Optional<ConfigArrayVerifier> mConfigArrayVerifier = Optional.empty();
+        private Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier = Optional.empty();
+
+        private Builder(int propertyId, int access, int areaType, int changeMode,
+                Class<T> propertyType) {
+            mPropertyId = propertyId;
+            mAccess = access;
+            mAreaType = areaType;
+            mChangeMode = changeMode;
+            mPropertyType = propertyType;
+        }
+
+        public Builder<T> requireProperty() {
+            mRequiredProperty = true;
+            return this;
+        }
+
+        public Builder<T> setConfigArrayVerifier(ConfigArrayVerifier configArrayVerifier) {
+            mConfigArrayVerifier = Optional.of(configArrayVerifier);
+            return this;
+        }
+
+        public Builder<T> setCarPropertyValueVerifier(
+                CarPropertyValueVerifier carPropertyValueVerifier) {
+            mCarPropertyValueVerifier = Optional.of(carPropertyValueVerifier);
+            return this;
+        }
+
+        public VehiclePropertyVerifier<T> build() {
+            return new VehiclePropertyVerifier<>(mPropertyId, mAccess, mAreaType, mChangeMode,
+                    mPropertyType,
+                    mRequiredProperty, mConfigArrayVerifier, mCarPropertyValueVerifier);
+        }
+    }
+}
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
index d334b05..49b7254 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
@@ -70,7 +70,7 @@
             CtsSyncAccountAccessOtherCertTestCases.class.getSimpleName();
 
     private static final Pattern PERMISSION_REQUESTED = Pattern.compile(
-            "Permission Requested|Permission requested");
+            "Permission Requested.*|Permission requested.*");
     private static final Pattern ALLOW_SYNC = Pattern.compile("ALLOW|Allow");
     private static final String OPEN_NOTIFICATION_WATCH = "Open";
 
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
index 35f2d3e..8470a12 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
@@ -29,7 +29,6 @@
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.platform.test.annotations.AppModeFull;
 import android.provider.DeviceConfig;
 import android.service.dataloader.DataLoaderService;
@@ -41,6 +40,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PropertyUtil;
 import com.android.incfs.install.IBlockFilter;
 import com.android.incfs.install.IBlockTransformer;
 import com.android.incfs.install.IncrementalInstallSession;
@@ -55,7 +55,6 @@
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -153,7 +152,9 @@
 
     @Test
     public void testAndroid12RequiresIncFsV2() throws Exception {
-        final boolean v2Required = (SystemProperties.getInt("ro.product.first_api_level", 0) > 30);
+        // IncFS is a kernel feature, which is a subject to vendor freeze. That's why
+        // the test verifies the vendor API level here, not the system's one.
+        final boolean v2Required = PropertyUtil.isVendorApiLevelNewerThan(30);
         if (v2Required) {
             Assert.assertTrue(getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_INCREMENTAL_DELIVERY, 2));
@@ -167,7 +168,6 @@
     }
 
     @Test
-    @Ignore("Wait until the kernel change lands in RVC branch for the mixed vendor image tests")
     public void testBug183952694Fixed() throws Exception {
         // first ensure the IncFS is up and running, e.g. if it's a module
         installPackage(TEST_APK);
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index dc44bf4..a495285 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -19,6 +19,8 @@
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
 import static org.junit.Assert.*;
 import static org.junit.Assume.*;
 
@@ -62,6 +64,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.DisplayUtil;
 import com.android.compatibility.common.util.PropertyUtil;
 
 import org.junit.After;
@@ -189,12 +192,15 @@
             InstrumentationRegistry.getInstrumentation().getUiAutomation(),
             Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
             Manifest.permission.ACCESS_SURFACE_FLINGER,
-            Manifest.permission.WRITE_SECURE_SETTINGS);
+            Manifest.permission.WRITE_SECURE_SETTINGS,
+            Manifest.permission.HDMI_CEC);
 
     @Before
     public void setUp() throws Exception {
         mScreenOnActivity = launchScreenOnActivity();
-        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mContext = getInstrumentation().getTargetContext();
+        assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(mContext));
+
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
@@ -429,10 +435,12 @@
     private void restoreOriginalHdrSettings() {
         final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
         SurfaceControl.overrideHdrTypes(displayToken, new int[]{});
-        mDisplayManager.setUserDisabledHdrTypes(
-                mOriginalHdrSettings.userDisabledHdrTypes);
-        mDisplayManager.setAreUserDisabledHdrTypesAllowed(
-                mOriginalHdrSettings.areUserDisabledHdrTypesAllowed);
+        if (mDisplayManager != null) {
+            mDisplayManager.setUserDisabledHdrTypes(
+                    mOriginalHdrSettings.userDisabledHdrTypes);
+            mDisplayManager.setAreUserDisabledHdrTypesAllowed(
+                    mOriginalHdrSettings.areUserDisabledHdrTypesAllowed);
+        }
     }
 
     private void waitUntil(Display display, Predicate<Display> pred, Duration maxWait)
diff --git a/tests/tests/graphics/TEST_MAPPING b/tests/tests/graphics/TEST_MAPPING
index f8fa289..edd5f5f 100644
--- a/tests/tests/graphics/TEST_MAPPING
+++ b/tests/tests/graphics/TEST_MAPPING
@@ -1,7 +1,12 @@
 {
   "presubmit": [
     {
-      "name": "CtsGraphicsTestCases"
+      "name": "CtsGraphicsTestCases",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
     }
   ]
 }
\ No newline at end of file
diff --git a/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java b/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
index c87794e..ff0ce79 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
@@ -16,11 +16,13 @@
 
 package android.graphics.cts;
 
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import android.Manifest;
+import android.content.Context;
 import android.hardware.display.DisplayManager;
 
 import androidx.test.filters.MediumTest;
@@ -28,6 +30,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.DisplayUtil;
 
 import org.junit.After;
 import org.junit.Before;
@@ -38,7 +41,6 @@
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class MatchContentFrameRateTest {
-    private static final int SETTING_PROPAGATION_TIMEOUT_MILLIS = 50;
 
     @Rule
     public ActivityTestRule<FrameRateCtsActivity> mActivityRule =
@@ -48,13 +50,17 @@
     public final AdoptShellPermissionsRule mShellPermissionsRule =
             new AdoptShellPermissionsRule(getInstrumentation().getUiAutomation(),
                     Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
-                    Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE);
+                    Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
+                    Manifest.permission.HDMI_CEC);
 
     private int mInitialMatchContentFrameRate;
     private DisplayManager mDisplayManager;
 
     @Before
     public void setUp() throws Exception {
+        Context context = getInstrumentation().getTargetContext();
+        assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(context));
+
         FrameRateCtsActivity activity = mActivityRule.getActivity();
 
         // Prevent DisplayManager from limiting the allowed refresh rate range based on
@@ -68,8 +74,10 @@
 
     @After
     public void tearDown() {
-        mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
-        mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+        if (mDisplayManager != null) {
+            mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
+            mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+        }
     }
 
     @Test
diff --git a/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java b/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
index bd3bb27..1b41d09 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
@@ -16,9 +16,12 @@
 
 package android.graphics.cts;
 
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
 
 import android.app.UiAutomation;
+import android.content.Context;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -27,6 +30,8 @@
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.DisplayUtil;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -50,6 +55,10 @@
         // necessary permission when surface flinger checks.
         UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
         uiAutomation.adoptShellPermissionIdentity();
+
+        Context context = getInstrumentation().getTargetContext();
+        assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(context));
+
         try {
             // Take ownership of the frame rate flexibility token, if we were able
             // to get one - we'll release it in tearDown().
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java
index 79c8342..04a8e1b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanPreTransformTest.java
@@ -30,6 +30,7 @@
 import android.view.PixelCopy;
 import android.view.SurfaceView;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
@@ -109,6 +110,7 @@
     }
 
     @Test
+    @FlakyTest (bugId = 184584284)
     public void testVulkanPreTransformSetToMatchCurrentTransform() throws Throwable {
         Log.d(TAG, "testVulkanPreTransformSetToMatchCurrentTransform start");
         if (!hasDeviceFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
@@ -123,6 +125,7 @@
     }
 
     @Test
+    @FlakyTest (bugId = 184584284)
     public void testVulkanPreTransformNotSetToMatchCurrentTransform() throws Throwable {
         Log.d(TAG, "testVulkanPreTransformNotSetToMatchCurrentTransform start");
         if (!hasDeviceFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
diff --git a/tests/tests/libcoreapievolution/Android.bp b/tests/tests/libcoreapievolution/Android.bp
index 1e41643..891ebc3 100644
--- a/tests/tests/libcoreapievolution/Android.bp
+++ b/tests/tests/libcoreapievolution/Android.bp
@@ -30,5 +30,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/tests/libcoreapievolution/AndroidTest.xml b/tests/tests/libcoreapievolution/AndroidTest.xml
index bfa6cdf..08f47fd 100644
--- a/tests/tests/libcoreapievolution/AndroidTest.xml
+++ b/tests/tests/libcoreapievolution/AndroidTest.xml
@@ -33,4 +33,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/tests/libcorefileio/Android.bp b/tests/tests/libcorefileio/Android.bp
index 7d1e7f4..58c388c 100644
--- a/tests/tests/libcorefileio/Android.bp
+++ b/tests/tests/libcorefileio/Android.bp
@@ -30,5 +30,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/tests/libcorefileio/AndroidTest.xml b/tests/tests/libcorefileio/AndroidTest.xml
index f563afe..c90b702 100644
--- a/tests/tests/libcorefileio/AndroidTest.xml
+++ b/tests/tests/libcorefileio/AndroidTest.xml
@@ -31,4 +31,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/tests/libcorelegacy22/Android.bp b/tests/tests/libcorelegacy22/Android.bp
index 351206e..44a997a 100644
--- a/tests/tests/libcorelegacy22/Android.bp
+++ b/tests/tests/libcorelegacy22/Android.bp
@@ -26,5 +26,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/tests/libcorelegacy22/AndroidTest.xml b/tests/tests/libcorelegacy22/AndroidTest.xml
index 33e08c0..94c1134 100644
--- a/tests/tests/libcorelegacy22/AndroidTest.xml
+++ b/tests/tests/libcorelegacy22/AndroidTest.xml
@@ -33,4 +33,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java b/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
index ec46782..f5cad49 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
@@ -166,12 +166,6 @@
                             -1 /* startFromMillis */);
                 });
 
-        assertThrows(IllegalArgumentException.class, () -> {
-                    record.shareAudioHistory(
-                            InstrumentationRegistry.getTargetContext().getPackageName(),
-                            10000 /* startFromMillis */);
-                });
-
         record.stop();
         record.release();
     }
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index e712615..3eecb04 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -46,9 +46,13 @@
         CamcorderProfile.QUALITY_720P,
         CamcorderProfile.QUALITY_1080P,
         CamcorderProfile.QUALITY_QVGA,
-        CamcorderProfile.QUALITY_2K,
-        CamcorderProfile.QUALITY_QHD,
         CamcorderProfile.QUALITY_2160P,
+        CamcorderProfile.QUALITY_VGA,
+        CamcorderProfile.QUALITY_4KDCI,
+        CamcorderProfile.QUALITY_QHD,
+        CamcorderProfile.QUALITY_2K,
+        CamcorderProfile.QUALITY_8KUHD,
+
         CamcorderProfile.QUALITY_TIME_LAPSE_LOW,
         CamcorderProfile.QUALITY_TIME_LAPSE_HIGH,
         CamcorderProfile.QUALITY_TIME_LAPSE_QCIF,
@@ -57,18 +61,25 @@
         CamcorderProfile.QUALITY_TIME_LAPSE_720P,
         CamcorderProfile.QUALITY_TIME_LAPSE_1080P,
         CamcorderProfile.QUALITY_TIME_LAPSE_QVGA,
-        CamcorderProfile.QUALITY_TIME_LAPSE_2K,
-        CamcorderProfile.QUALITY_TIME_LAPSE_QHD,
         CamcorderProfile.QUALITY_TIME_LAPSE_2160P,
+        CamcorderProfile.QUALITY_TIME_LAPSE_VGA,
+        CamcorderProfile.QUALITY_TIME_LAPSE_4KDCI,
+        CamcorderProfile.QUALITY_TIME_LAPSE_QHD,
+        CamcorderProfile.QUALITY_TIME_LAPSE_2K,
+        CamcorderProfile.QUALITY_TIME_LAPSE_8KUHD,
+
         CamcorderProfile.QUALITY_HIGH_SPEED_LOW,
         CamcorderProfile.QUALITY_HIGH_SPEED_HIGH,
         CamcorderProfile.QUALITY_HIGH_SPEED_480P,
         CamcorderProfile.QUALITY_HIGH_SPEED_720P,
         CamcorderProfile.QUALITY_HIGH_SPEED_1080P,
-        CamcorderProfile.QUALITY_HIGH_SPEED_2160P
+        CamcorderProfile.QUALITY_HIGH_SPEED_2160P,
+        CamcorderProfile.QUALITY_HIGH_SPEED_CIF,
+        CamcorderProfile.QUALITY_HIGH_SPEED_VGA,
+        CamcorderProfile.QUALITY_HIGH_SPEED_4KDCI,
     };
-    private static final int LAST_QUALITY = CamcorderProfile.QUALITY_2K;
-    private static final int LAST_TIMELAPSE_QUALITY = CamcorderProfile.QUALITY_TIME_LAPSE_2K;
+    private static final int LAST_QUALITY = CamcorderProfile.QUALITY_8KUHD;
+    private static final int LAST_TIMELAPSE_QUALITY = CamcorderProfile.QUALITY_TIME_LAPSE_8KUHD;
     private static final int LAST_HIGH_SPEED_QUALITY = CamcorderProfile.QUALITY_HIGH_SPEED_4KDCI;
     private static final Integer[] UNKNOWN_QUALITIES = {
         LAST_QUALITY + 1, // Unknown normal profile quality
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
index 0f404d1..80aefa7 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
@@ -25,12 +25,15 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.media.MediaFormat;
+import android.os.Environment;
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 import android.view.View;
 
 import com.android.compatibility.common.util.MediaUtils;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -139,6 +142,8 @@
     private View videoView;
     private VideoViewFactory videoViewFactory;
     private String fileName;
+    private String testName;
+    private String methodName;
     private SimplePlayer player;
 
     @After
@@ -161,48 +166,55 @@
         final List<Object[]> testParams = new ArrayList<>();
         for (int i = 0; i < VIDEO_FILES.length; i++) {
             final String file = VIDEO_FILES[i];
-            Pattern regex = Pattern.compile("^\\w+-(\\w+)_\\d+fps.\\w+");
+            Pattern regex = Pattern.compile("^\\w+-(\\w+)_\\d+fps\\.\\w+");
             Matcher matcher = regex.matcher(file);
             String testName = "";
             if (matcher.matches()) {
                 testName = matcher.group(1);
             }
-            testParams.add(new Object[] { testName.replace("_", " ").toUpperCase(), file });
+            testParams.add(new Object[] { testName, file });
         }
         return testParams;
     }
 
-    public DecodeAccuracyTest(String testname, String fileName) {
+    public DecodeAccuracyTest(String testName, String fileName) {
         this.fileName = fileName;
+        this.testName = testName;
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewDecodeAccuracy() throws Exception {
+        this.methodName = "testGLViewDecodeAccuracy";
         runTest(new GLSurfaceViewFactory(), new VideoFormat(fileName));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewLargerHeightDecodeAccuracy() throws Exception {
+        this.methodName = "testGLViewLargerHeightDecodeAccuracy";
         runTest(new GLSurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewLargerWidthDecodeAccuracy() throws Exception {
+        this.methodName = "testGLViewLargerWidthDecodeAccuracy";
         runTest(new GLSurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewVideoDecodeAccuracy() throws Exception {
+        this.methodName = "testSurfaceViewVideoDecodeAccuracy";
         runTest(new SurfaceViewFactory(), new VideoFormat(fileName));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewLargerHeightDecodeAccuracy() throws Exception {
+        this.methodName = "testSurfaceViewLargerHeightDecodeAccuracy";
         runTest(new SurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)));
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewLargerWidthDecodeAccuracy() throws Exception {
+        this.methodName = "testSurfaceViewLargerWidthDecodeAccuracy";
         runTest(new SurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)));
     }
 
@@ -253,6 +265,20 @@
         final Bitmap golden = getHelper().generateBitmapFromImageResourceId(goldenId);
         final BitmapCompare.Difference difference = BitmapCompare.computeMinimumDifference(
                 result, golden, videoFormat.getOriginalWidth(), videoFormat.getOriginalHeight());
+
+        if (difference.greatestPixelDifference > ALLOWED_GREATEST_PIXEL_DIFFERENCE) {
+            /* save failing file */
+            File failed = new File(Environment.getExternalStorageDirectory(),
+                                   "failed_" + methodName + "_" + testName + ".png");
+            try (FileOutputStream fileStream = new FileOutputStream(failed)) {
+                result.compress(Bitmap.CompressFormat.PNG, 0 /* ignored for PNG */, fileStream);
+                fileStream.flush();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            Log.d(TAG, testName + " saved " + failed.getAbsolutePath());
+        }
+
         assertTrue("With the best matched border crop ("
                 + difference.bestMatchBorderCrop.first + ", "
                 + difference.bestMatchBorderCrop.second + "), "
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
index 4579567..33580ce 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
@@ -1797,7 +1797,7 @@
         }
         return new Difference(greatestDifference, Pair.create(
             greatestDifferenceIndex % bitmap1.getWidth(),
-            greatestDifferenceIndex / bitmap1.getHeight()));
+            greatestDifferenceIndex / bitmap1.getWidth()));
     }
 
     @SuppressLint("UseSparseArrays")
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
index 9918545..96ae72a 100755
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -27,6 +27,7 @@
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
 import android.opengl.GLES20;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -43,6 +44,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.MediaUtils;
+
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -121,6 +125,9 @@
         return 0xff << 24 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff);
     }
 
+    private static boolean sIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
+    private static boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -136,6 +143,9 @@
      * @throws Exception
      */
     public void testEncodeVirtualDisplay() throws Throwable {
+
+        if (!MediaUtils.check(sIsAtLeastR, "test needs Android 11")) return;
+
         EncodeVirtualWrapper.runTest(this);
     }
 
diff --git a/tests/tests/nativemedia/aaudio/jni/Android.mk b/tests/tests/nativemedia/aaudio/jni/Android.mk
index 2f11b9e..09f730f 100644
--- a/tests/tests/nativemedia/aaudio/jni/Android.mk
+++ b/tests/tests/nativemedia/aaudio/jni/Android.mk
@@ -32,6 +32,9 @@
     test_session_id.cpp \
     utils.cpp \
 
+LOCAL_C_INCLUDES := \
+    system/media/audio/include
+
 LOCAL_SHARED_LIBRARIES := \
     libaaudio \
     liblog
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
index 4a89d69..1b8cf44 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
@@ -27,6 +27,9 @@
 #include "test_aaudio.h"
 #include "utils.h"
 
+constexpr int kExtremelyHighCallbackPeriodMillis = 200;
+constexpr int kMinCallbacksPerSecond = MILLIS_PER_SECOND / kExtremelyHighCallbackPeriodMillis;
+
 static int32_t measureLatency(AAudioStream *stream) {
     int64_t presentationTime = 0;
     int64_t presentationPosition = 0;
@@ -109,6 +112,7 @@
         int32_t maxLatency;
         std::atomic<aaudio_result_t> callbackError;
         std::atomic<int32_t> callbackCount;
+        std::atomic<bool> returnStop;
 
         AAudioCallbackTestData() {
             reset(0);
@@ -120,6 +124,7 @@
             maxLatency = 0;
             callbackError = AAUDIO_OK;
             callbackCount = 0;
+            returnStop = false;
         }
         void updateFrameCount(int32_t numFrames) {
             if (numFrames != expectedFramesPerCallback) {
@@ -170,7 +175,7 @@
     myData->updateFrameCount(numFrames);
     // No latency measurement as there is no API for querying capture position.
     myData->callbackCount++;
-    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    return myData->returnStop ? AAUDIO_CALLBACK_RESULT_STOP : AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
 
 void AAudioInputStreamCallbackTest::SetUp() {
@@ -212,7 +217,7 @@
 
 }
 
-// Test Reading from an AAudioStream using a Callback
+// Test starting and stopping an INPUT AAudioStream that uses a Callback
 TEST_P(AAudioInputStreamCallbackTest, testRecording) {
     if (!mSetupSuccesful) return;
 
@@ -222,29 +227,47 @@
         ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
     }
 
-    mCbData->reset(streamFramesPerDataCallback);
+    constexpr int kSleepSeconds = 2;
+    constexpr int kMinExpectedCallbacks = kMinCallbacksPerSecond * kSleepSeconds;
 
-    mHelper->startStream();
-    // See b/62090113. For legacy path, the device is only known after
-    // the stream has been started.
-    EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
-    sleep(2); // let the stream run
+    // Try both methods of stopping a stream.
+    const int kNumMethods = 2;
 
-    ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
-    ASSERT_GT(mCbData->callbackCount, 10);
+    // Start/stop more than once to see if it fails after the first time.
+    // Also check to make sure we do not get callbacks after the stop.
+    for (int loopIndex = 0; loopIndex < kNumMethods; loopIndex++) {
+        mCbData->reset(streamFramesPerDataCallback);
 
-    mHelper->stopStream();
+        mHelper->startStream();
+        // See b/62090113. For legacy path, the device is only known after
+        // the stream has been started.
+        EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
+        sleep(kSleepSeconds); // let the stream run
 
-    int32_t oldCallbackCount = mCbData->callbackCount;
-    EXPECT_GT(oldCallbackCount, 10);
-    sleep(1);
-    EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
+        ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
+        ASSERT_GT(mCbData->callbackCount, kMinExpectedCallbacks);
 
-    if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
-        ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
+        switch (loopIndex % kNumMethods) {
+            case 0:
+                mCbData->returnStop = true; // callback return
+                mHelper->waitForState(AAUDIO_STREAM_STATE_STOPPED);
+                break;
+            case 1:
+                mHelper->stopStream();
+                break;
+        }
+
+        int32_t oldCallbackCount = mCbData->callbackCount;
+        EXPECT_GT(oldCallbackCount, kMinExpectedCallbacks);
+        sleep(1);
+        EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
+
+        if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
+            ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
+        }
+
+        ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
     }
-
-    ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
 }
 
 INSTANTIATE_TEST_CASE_P(SPM, AAudioInputStreamCallbackTest,
@@ -319,7 +342,7 @@
     myData->updateFrameCount(numFrames);
     myData->updateLatency(measureLatency(stream));
     myData->callbackCount++;
-    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    return myData->returnStop ? AAUDIO_CALLBACK_RESULT_STOP : AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
 
 void AAudioOutputStreamCallbackTest::SetUp() {
@@ -344,7 +367,7 @@
 
 }
 
-// Test Writing to an AAudioStream using a Callback
+// Test starting and stopping an OUTPUT AAudioStream that uses a Callback
 TEST_P(AAudioOutputStreamCallbackTest, testPlayback) {
     if (!mSetupSuccesful) return;
 
@@ -354,29 +377,41 @@
         ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
     }
 
+    constexpr int kSleepSeconds = 2;
+    constexpr int kMinExpectedCallbacks = kMinCallbacksPerSecond * kSleepSeconds;
+
+    // Try all 3 methods of stopping/pausing a stream.
+    constexpr int kNumMethods = 3;
+
     // Start/stop more than once to see if it fails after the first time.
-    // Write some data and measure the rate to see if the timing is OK.
-    for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+    // Also check to make sure we do not get callbacks after the stop.
+    for (int loopIndex = 0; loopIndex < kNumMethods; loopIndex++) {
         mCbData->reset(streamFramesPerDataCallback);
 
         mHelper->startStream();
         // See b/62090113. For legacy path, the device is only known after
         // the stream has been started.
         EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
-        sleep(2); // let the stream run
+        sleep(kSleepSeconds); // let the stream run
 
         ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
-        ASSERT_GT(mCbData->callbackCount, 10);
+        ASSERT_GT(mCbData->callbackCount, kMinExpectedCallbacks);
 
-        // For more coverage, alternate pausing and stopping.
-        if ((loopIndex & 1) == 0) {
-            mHelper->pauseStream();
-        } else {
-            mHelper->stopStream();
+        switch (loopIndex % kNumMethods) {
+            case 0:
+                mCbData->returnStop = true; // callback return
+                mHelper->waitForState(AAUDIO_STREAM_STATE_STOPPED);
+                break;
+            case 1:
+                mHelper->pauseStream();
+                break;
+            case 2:
+                mHelper->stopStream();
+                break;
         }
 
         int32_t oldCallbackCount = mCbData->callbackCount;
-        EXPECT_GT(oldCallbackCount, 10);
+        EXPECT_GT(oldCallbackCount, kMinExpectedCallbacks);
         sleep(1);
         EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
 
@@ -391,9 +426,9 @@
                     "Suspiciously high callback latency: %d", mCbData->maxLatency);
         }
         //printf("latency: %d, %d\n", mCbData->minLatency, mCbData->maxLatency);
-    }
 
-    ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
+        ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
+    }
 }
 
 INSTANTIATE_TEST_CASE_P(SPM, AAudioOutputStreamCallbackTest,
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
index 0c55a3f..57d36ae 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
@@ -23,6 +23,7 @@
 #include <android/log.h>
 #include <gtest/gtest.h>
 #include <sys/system_properties.h>
+#include <system/audio.h> /* FCC_LIMIT */
 
 #include "utils.h"
 
@@ -186,7 +187,7 @@
     }
   protected:
     static bool isValidChannelCount(int32_t cc) {
-        return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= 8);
+        return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= FCC_LIMIT);
     }
 };
 
@@ -201,10 +202,10 @@
 
 INSTANTIATE_TEST_CASE_P(CC, AAudioStreamBuilderChannelCountTest,
         ::testing::Values(
-                // Reasonable values
-                AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8,
-                // Odd values
-                AAUDIO_UNSPECIFIED - 1, 9, 100, 1000000, 10000000),
+                // Reasonable values that should work OK.
+                AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8, FCC_LIMIT,
+                // These values should fail.
+                AAUDIO_UNSPECIFIED - 1, (FCC_LIMIT + 1), 1000, 1000000),
         &AAudioStreamBuilderChannelCountTest::getTestName);
 
 class AAudioStreamBuilderFormatTest : public ::testing::TestWithParam<aaudio_format_t> {
diff --git a/tests/tests/nativemedia/aaudio/jni/utils.h b/tests/tests/nativemedia/aaudio/jni/utils.h
index f14e04d..8294eca 100644
--- a/tests/tests/nativemedia/aaudio/jni/utils.h
+++ b/tests/tests/nativemedia/aaudio/jni/utils.h
@@ -22,6 +22,8 @@
 
 #include <aaudio/AAudio.h>
 
+#include "test_aaudio.h"    // NANOS_PER_MILLISECOND
+
 int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
 const char* performanceModeToString(aaudio_performance_mode_t mode);
 const char* sharingModeToString(aaudio_sharing_mode_t mode);
@@ -57,6 +59,18 @@
         streamCommand(&AAudioStream_requestStop,
                 AAUDIO_STREAM_STATE_STOPPING, AAUDIO_STREAM_STATE_STOPPED);
     }
+
+    void waitForState(aaudio_stream_state_t targetState) {
+        aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+        const int kNumTries = 4; // max number of states we expect to transition through
+        for (int i = 0; ((i < kNumTries) && (state != targetState)); i++) {
+            EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream(),
+                                                                 state,
+                                                                 &state,
+                                                                 500 * NANOS_PER_MILLISECOND));
+        }
+    }
+
     void flushStream() {
         streamCommand(&AAudioStream_requestFlush,
                 AAUDIO_STREAM_STATE_FLUSHING, AAUDIO_STREAM_STATE_FLUSHED);
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index ea9d85b..bfb82c5 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -17,6 +17,7 @@
 package android.os.cts
 
 import android.companion.CompanionDeviceManager
+import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
 import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
 import android.content.pm.PackageManager.PERMISSION_GRANTED
 import android.net.MacAddress
@@ -54,8 +55,10 @@
 import org.hamcrest.Matchers.empty
 import org.hamcrest.Matchers.not
 import org.junit.Assert.assertThat
+import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Before
+import org.junit.After
 import org.junit.Test
 import org.junit.runner.RunWith
 import java.io.Serializable
@@ -100,6 +103,19 @@
     @Before
     fun assumeHasFeature() {
         assumeTrue(context.packageManager.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP))
+        // TODO(b/191699828) test does not work in automotive due to accessibility issue
+        assumeFalse(context.packageManager.hasSystemFeature(FEATURE_AUTOMOTIVE))
+    }
+
+    @After
+    fun removeAllAssociations() {
+        val packageName = "android.os.cts.companiontestapp"
+        val userId = context.userId
+        val associations = getAssociatedDevices(packageName)
+
+        for (address in associations) {
+            runShellCommandOrThrow("cmd companiondevice disassociate $userId $packageName $address")
+        }
     }
 
     @AppModeFull(reason = "Companion API for non-instant apps only")
@@ -153,7 +169,8 @@
     @Test
     fun testProfiles() {
         val packageName = "android.os.cts.companiontestapp"
-        installApk("/data/local/tmp/cts/os/CtsCompanionTestApp.apk")
+        installApk(
+                "--user ${UserHandle.myUserId()} /data/local/tmp/cts/os/CtsCompanionTestApp.apk")
         startApp(packageName)
 
         waitFindNode(hasClassThat(`is`(equalTo(EditText::class.java.name))))
@@ -166,11 +183,11 @@
             click("Associate")
             waitFindNode(hasIdThat(containsString("device_list")),
                     failMsg = "Test requires a discoverable bluetooth device nearby",
-                    timeoutMs = 5_000)
+                    timeoutMs = 9_000)
                     .children
                     .find { it.className == TextView::class.java.name }
                     .assertNotNull { "Empty device list" }
-        }, 60_000)
+        }, 90_000)
         device!!.click()
 
         eventually {
@@ -189,7 +206,8 @@
     @Test
     fun testRequestNotifications() {
         val packageName = "android.os.cts.companiontestapp"
-        installApk("/data/local/tmp/cts/os/CtsCompanionTestApp.apk")
+        installApk(
+                "--user ${UserHandle.myUserId()} /data/local/tmp/cts/os/CtsCompanionTestApp.apk")
         startApp(packageName)
 
         waitFindNode(hasClassThat(`is`(equalTo(EditText::class.java.name))))
@@ -208,6 +226,7 @@
         }, 60_000)
 
         deviceForAssociation!!.click()
+
         waitForIdle()
 
         val deviceForNotifications = getEventually({
@@ -219,6 +238,8 @@
         }, 60_000)
 
         deviceForNotifications!!.click()
+
+        waitForIdle()
     }
 
     private fun getAssociatedDevices(
diff --git a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
index 140ffc8..6545c0c 100644
--- a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
@@ -121,7 +121,7 @@
             "location_access_check_enabled";
 
     private static final long UNEXPECTED_TIMEOUT_MILLIS = 10000;
-    private static final long EXPECTED_TIMEOUT_MILLIS = 1000;
+    private static final long EXPECTED_TIMEOUT_MILLIS = 15000;
     private static final long LOCATION_ACCESS_TIMEOUT_MILLIS = 15000;
 
     private static final Context sContext = InstrumentationRegistry.getTargetContext();
@@ -165,7 +165,7 @@
 
         long beforeAccess = System.currentTimeMillis();
         // Wait a little to avoid raciness in timing between threads
-        Thread.sleep(10);
+        Thread.sleep(1000);
 
         // Try again until binder call goes though. It might not go through if the sLocationAccessor
         // is not bound yet
@@ -295,24 +295,28 @@
      * Force a run of the location check.
      */
     private static void runLocationCheck() throws Throwable {
+        // Sleep a little bit to make sure we don't have overlap in timing
+        Thread.sleep(1000);
+
         long beforeJob = System.currentTimeMillis();
 
         // Sleep a little bit to avoid raciness in time keeping
-        Thread.sleep(100);
+        Thread.sleep(1000);
 
         runShellCommand(
                 "cmd jobscheduler run -u " + android.os.Process.myUserHandle().getIdentifier()
                         + " -f " + PERMISSION_CONTROLLER_PKG + " 0");
 
-        long[] startTime = new long[] {-1};
         eventually(() -> {
-            startTime[0] = getLastJobTime(START_PERIODIC_JOB);
-            assertTrue(startTime[0] + "!>" + beforeJob, startTime[0] > beforeJob);
+            long startTime = getLastJobTime(START_PERIODIC_JOB);
+            assertTrue(startTime + " !> " + beforeJob, startTime > beforeJob);
         }, EXPECTED_TIMEOUT_MILLIS);
 
+        // We can't simply require startTime <= endTime because the time being reported isn't
+        // accurate, and sometimes the end time may come before the start time by around 100 ms.
         eventually(() -> {
             long stopTime = getLastJobTime(STOP_JOB);
-            assertTrue(startTime[0] <= stopTime);
+            assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob);
         }, EXPECTED_TIMEOUT_MILLIS);
     }
 
@@ -404,17 +408,19 @@
     }
 
     @BeforeClass
-    public static void installBackgroundAccessApp() {
+    public static void installBackgroundAccessApp() throws Exception {
         installBackgroundAccessApp(false);
     }
 
-    private static void installBackgroundAccessApp(boolean isDowngrade) {
+    private static void installBackgroundAccessApp(boolean isDowngrade) throws Exception {
         String command = "pm install -r -g ";
         if (isDowngrade) {
             command = command + "-d ";
         }
         String output = runShellCommand(command + TEST_APP_LOCATION_BG_ACCESS_APK);
         assertTrue(output.contains("Success"));
+        // Wait for user sensitive to be updated, which is checked by LocationAccessCheck.
+        Thread.sleep(5000);
     }
 
     @AfterClass
@@ -432,9 +438,11 @@
     }
 
 
-    private static void installForegroundAccessApp() {
+    private static void installForegroundAccessApp() throws Exception {
         unbindService();
         runShellCommand("pm install -r -g " + TEST_APP_LOCATION_FG_ACCESS_APK);
+        // Wait for user sensitive to be updated, which is checked by LocationAccessCheck.
+        Thread.sleep(5000);
     }
 
     private static void uninstallForegroundAccessApp() {
@@ -450,6 +458,12 @@
     }
 
     @Before
+    public void wakeUpAndDismissKeyguard() {
+        runShellCommand("input keyevent KEYCODE_WAKEUP");
+        runShellCommand("wm dismiss-keyguard");
+    }
+
+    @Before
     public void bindService() {
         sConnection = new ServiceConnection() {
             @Override
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index ff9bbcf..27b7c3b 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -476,7 +476,7 @@
         android:description="@string/car_permission_desc_template_renderer"/>
 
     <permission android:name="android.car.permission.CAR_MONITOR_INPUT"
-        android:protectionLevel="signature"
+        android:protectionLevel="signature|privileged"
         android:label="@string/car_permission_label_monitor_input"
         android:description="@string/car_permission_desc_monitor_input"/>
 
diff --git a/tests/tests/permission3/UsePermissionApp30WithBluetooth/src/android/permission3/cts/usepermission/AccessBluetoothOnCommand.kt b/tests/tests/permission3/UsePermissionApp30WithBluetooth/src/android/permission3/cts/usepermission/AccessBluetoothOnCommand.kt
index abfaa7b..9a09f18 100644
--- a/tests/tests/permission3/UsePermissionApp30WithBluetooth/src/android/permission3/cts/usepermission/AccessBluetoothOnCommand.kt
+++ b/tests/tests/permission3/UsePermissionApp30WithBluetooth/src/android/permission3/cts/usepermission/AccessBluetoothOnCommand.kt
@@ -36,7 +36,7 @@
 class AccessBluetoothOnCommand : ContentProvider() {
 
     private enum class Result {
-        UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
+        UNKNOWN, ERROR, EXCEPTION, EMPTY, FILTERED, FULL
     }
 
     override fun call(authority: String, method: String, arg: String?, extras: Bundle?): Bundle? {
@@ -77,7 +77,8 @@
             SystemClock.sleep(3000)
 
             if (observedErrorCode.get() > 0) {
-                throw RuntimeException("Scan returned error code: " + observedErrorCode.get())
+                res.putInt(Intent.EXTRA_INDEX, Result.ERROR.ordinal)
+                return res
             }
 
             when (observedScans.size) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
index d1fd37d..124cbec 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
@@ -16,21 +16,30 @@
 
 package android.permission3.cts
 
+import android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.BLUETOOTH_SCAN
+import android.app.AppOpsManager
 import android.bluetooth.BluetoothAdapter
 import android.bluetooth.BluetoothManager
 import android.bluetooth.cts.BTAdapterUtils
 import android.content.Intent
 import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
 import android.os.Build
+import android.os.Process
 import androidx.test.InstrumentationRegistry
 import androidx.test.filters.SdkSuppress
 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertTrue
+import junit.framework.AssertionFailedError
 import org.junit.After
+import org.junit.Assert.assertNotEquals
 import org.junit.Assume.assumeTrue
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 
 /**
@@ -41,11 +50,13 @@
 
     private val TEST_APP_AUTHORITY =
         "android.permission3.cts.usepermission.AccessBluetoothOnCommand"
+    private val TEST_APP_PKG =
+        "android.permission3.cts.usepermission"
     private lateinit var bluetoothAdapter: BluetoothAdapter
     private var bluetoothAdapterWasEnabled: Boolean = false
 
     private enum class BluetoothScanResult {
-        UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
+        UNKNOWN, ERROR, EXCEPTION, EMPTY, FILTERED, FULL
     }
 
     @Before
@@ -53,6 +64,10 @@
         installPackage(APP_APK_PATH_30_WITH_BLUETOOTH)
     }
 
+    private fun reinstallApp() {
+        installPackage(APP_APK_PATH_30_WITH_BLUETOOTH, reinstall = true)
+    }
+
     @Before
     fun enableBluetooth() {
         assumeTrue(supportsBluetooth())
@@ -76,11 +91,52 @@
     }
 
     @Test
+    @Ignore
     fun testGivenBluetoothIsDeniedWhenScanIsAttemptedThenThenGetEmptyScanResult() {
-        revokeAppPermissions(android.Manifest.permission.BLUETOOTH_SCAN)
+        assertBluetoothRevokedCompatState(revoked = false)
+        // Should return empty while the app does not have location
         assertEquals(BluetoothScanResult.EMPTY, scanForBluetoothDevices())
+
+        uiAutomation.grantRuntimePermission(TEST_APP_PKG, ACCESS_FINE_LOCATION)
+        uiAutomation.grantRuntimePermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION)
+        runWithShellPermissionIdentity {
+            context.getSystemService(AppOpsManager::class.java)!!.setUidMode(
+                AppOpsManager.OPSTR_FINE_LOCATION,
+                packageManager.getPackageUid(context.packageName, 0), AppOpsManager.MODE_ALLOWED)
+        }
+
+        assertEquals(BluetoothScanResult.FULL, scanForBluetoothDevices())
+        revokeAppPermissions(BLUETOOTH_SCAN, isLegacyApp = true)
+        assertBluetoothRevokedCompatState(revoked = true)
+        val res = scanForBluetoothDevices()
+        if (res != BluetoothScanResult.ERROR && res != BluetoothScanResult.EMPTY) {
+            throw AssertionFailedError("Expected to be EMPTY or ERROR, but was $res")
+        }
     }
 
+    @Test
+    @Ignore
+    fun testRevokedCompatPersistsOnReinstall() {
+        assertBluetoothRevokedCompatState(revoked = false)
+        revokeAppPermissions(BLUETOOTH_SCAN, isLegacyApp = true)
+        assertBluetoothRevokedCompatState(revoked = true)
+        reinstallApp()
+        assertBluetoothRevokedCompatState(revoked = true)
+        installApp()
+        assertBluetoothRevokedCompatState(revoked = true)
+    }
+
+    private fun assertBluetoothRevokedCompatState(revoked: Boolean = true) {
+        runWithShellPermissionIdentity {
+            val flag = context.packageManager.getPermissionFlags(BLUETOOTH_SCAN,
+                TEST_APP_PKG, Process.myUserHandle()) and FLAG_PERMISSION_REVOKED_COMPAT
+            if (revoked) {
+                assertNotEquals(0, flag)
+            } else {
+                assertEquals(0, flag)
+            }
+        }
+    }
     private fun scanForBluetoothDevices(): BluetoothScanResult {
         val resolver = InstrumentationRegistry.getTargetContext().getContentResolver()
         val result = resolver.call(TEST_APP_AUTHORITY, "", null, null)
diff --git a/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt b/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt
index 25a73fe..beca389 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RenouncedPermissionsTest.kt
@@ -127,14 +127,15 @@
             // Calculate the shellUid to account for running this from a secondary user.
             val shellUid = UserHandle.getUid(Process.myUserHandle().identifier,
                 UserHandle.getAppId(Process.SHELL_UID))
-            val shellAttributionSource = AttributionSource.Builder(shellUid)
+            var shellAttributionSource = AttributionSource.Builder(shellUid)
                     .setPackageName("com.android.shell")
                     .setRenouncedPermissions(renouncedPermissionsSet)
                     .build()
 
             SystemUtil.runWithShellPermissionIdentity {
                 val permissionManager = context.getSystemService(PermissionManager::class.java)!!
-                permissionManager.registerAttributionSource(shellAttributionSource);
+                shellAttributionSource = permissionManager.registerAttributionSource(
+                        shellAttributionSource)
             }
 
             return shellAttributionSource
diff --git a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
index 8eaea24..9c369f7 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
@@ -1143,10 +1143,11 @@
                 if (receiverAttributionTag != null) {
                     attributionSourceBuilder.setAttributionTag(receiverAttributionTag)
                 }
-                val receiverAttributionSource = attributionSourceBuilder.build()
+                var receiverAttributionSource = attributionSourceBuilder.build()
                 SystemUtil.runWithShellPermissionIdentity {
-                    context.getSystemService(PermissionManager::class.java)!!
-                            .registerAttributionSource(receiverAttributionSource)
+                    receiverAttributionSource = context.getSystemService(
+                            PermissionManager::class.java)!!.registerAttributionSource(
+                            receiverAttributionSource)
                 }
                 attributionParamsBuilder.setNextAttributionSource(receiverAttributionSource)
             }
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
index c868b1e..92335e9 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
@@ -2200,7 +2200,7 @@
             final PendingIntent intent = getLauncherApps().getShortcutIntent(
                     mPackageContext1.getPackageName(), "s1", null, getUserHandle());
             assertNotNull(intent);
-            assertFalse(intent.isImmutable());
+            assertTrue(intent.isImmutable());
             assertEquals(mPackageContext1.getPackageName(), intent.getCreatorPackage());
             assertEquals(getUserHandle(), intent.getCreatorUserHandle());
         });
diff --git a/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt b/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt
index 6b54652..fbd3f72 100644
--- a/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt
+++ b/tests/tests/systemui/src/android/systemui/cts/tv/VpnDisclosureTest.kt
@@ -18,6 +18,7 @@
 
 import android.app.Notification
 import android.content.ComponentName
+import android.platform.test.annotations.AppModeFull
 import android.platform.test.annotations.Postsubmit
 import android.server.wm.annotation.Group2
 import android.service.notification.StatusBarNotification
@@ -44,6 +45,7 @@
 @Postsubmit
 @Group2
 @RunWith(AndroidJUnit4::class)
+@AppModeFull
 class VpnDisclosureTest : TvTestBase() {
     companion object {
         private const val TAG = "VpnDisclosureTest"
diff --git a/tests/tests/telecom/src/android/telecom/cts/BluetoothCallQualityReportTest.java b/tests/tests/telecom/src/android/telecom/cts/BluetoothCallQualityReportTest.java
new file mode 100644
index 0000000..dc40407
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/BluetoothCallQualityReportTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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.telecom.cts;
+
+import android.telecom.BluetoothCallQualityReport;
+
+public class BluetoothCallQualityReportTest extends BaseTelecomTestWithMockServices {
+    /**
+     * Test passing of BT call quality report to CDS.
+     */
+    public void testBluetoothCallQualityReport() {
+        long timestamp = System.currentTimeMillis();
+        int rssi = 1;
+        int snr = 2;
+        int retransmissionCount = 3;
+        int packetsNotReceiveCount = 4;
+        int negativeAcknowledgementCount = 5;
+
+        BluetoothCallQualityReport report = new BluetoothCallQualityReport.Builder()
+                .setSentTimestampMillis(timestamp)
+                .setChoppyVoice(true)
+                .setRssiDbm(rssi)
+                .setSnrDb(snr)
+                .setRetransmittedPacketsCount(retransmissionCount)
+                .setPacketsNotReceivedCount(packetsNotReceiveCount)
+                .setNegativeAcknowledgementCount(negativeAcknowledgementCount)
+                .build();
+
+        assertEquals(timestamp, report.getSentTimestampMillis());
+        assertEquals(true, report.isChoppyVoice());
+        assertEquals(rssi, report.getRssiDbm());
+        assertEquals(snr, report.getSnrDb());
+        assertEquals(retransmissionCount, report.getRetransmittedPacketsCount());
+        assertEquals(packetsNotReceiveCount, report.getPacketsNotReceivedCount());
+        assertEquals(negativeAcknowledgementCount, report.getNegativeAcknowledgementCount());
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java b/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
index 8e2d759..d2d9539 100644
--- a/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
+++ b/tests/tests/telecom2/src/android/telecom/cts/TelecomManagerNoPermissionsTest.java
@@ -75,16 +75,6 @@
             } catch (SecurityException e) {
                 // expected
             }
-
-            TestUtils.disableCompatCommand(getInstrumentation(),
-                    TestUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
-            try {
-                tm.getCallState();
-            } catch (SecurityException e) {
-                fail("TelecomManager#getCallState must not require READ_PHONE_STATE when "
-                        + "TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is "
-                        + "disabled.");
-            }
         } finally {
             TestUtils.resetCompatCommand(getInstrumentation(),
                     TestUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
@@ -108,16 +98,6 @@
             } catch (SecurityException e) {
                 //expected
             }
-
-            TestUtils.disableCompatCommand(getInstrumentation(),
-                    TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
-            try {
-                mTelecomManager.getPhoneAccount(TestUtils.TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_1);
-            } catch (SecurityException e) {
-                fail("TelecomManager#getPhoneAccount shouldn't require READ_PHONE_NUMBERS or "
-                        + "READ_PRIVILEGED_PHONE_STATE when "
-                        + "ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION is disabled");
-            }
         } finally {
             TestUtils.resetCompatCommand(getInstrumentation(),
                     TestUtils.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING);
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 83c4a7e..11e5979 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -3559,6 +3559,13 @@
     }
 
     private void disableNrDualConnectivity() {
+        if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
+                        TelephonyManager
+                                .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
+            return;
+        }
+
         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                 mTelephonyManager,
                 (tm) -> tm.setNrDualConnectivityState(
@@ -3579,6 +3586,13 @@
             return;
         }
 
+        if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
+                        TelephonyManager
+                                .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
+            return;
+        }
+
         boolean isInitiallyEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
         boolean isNrDualConnectivityEnabled;
diff --git a/tests/tests/time/Android.bp b/tests/tests/time/Android.bp
index 086f9d8..651dcf8 100644
--- a/tests/tests/time/Android.bp
+++ b/tests/tests/time/Android.bp
@@ -29,6 +29,7 @@
         "androidx.test.rules",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
+        "device_time_shell_utils",
     ],
     srcs: ["src/**/*.java"],
     sdk_version: "system_current",
diff --git a/tests/tests/time/AndroidManifest.xml b/tests/tests/time/AndroidManifest.xml
index aaf2c47..7dee4c0 100644
--- a/tests/tests/time/AndroidManifest.xml
+++ b/tests/tests/time/AndroidManifest.xml
@@ -25,8 +25,7 @@
     <!-- uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/-->
     <eat-comment />
 
-    <application>
-    </application>
+    <application android:debuggable="true" />
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="android.time.cts"
diff --git a/tests/tests/time/shell_utils/Android.bp b/tests/tests/time/shell_utils/Android.bp
new file mode 100644
index 0000000..ffd5256
--- /dev/null
+++ b/tests/tests/time/shell_utils/Android.bp
@@ -0,0 +1,56 @@
+//
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// A library for interacting with time-related shell "cmd" commands from host
+// tests.
+java_library_host {
+    name: "host_time_shell_utils",
+    defaults: ["cts_defaults"],
+    libs: [
+        "androidx.annotation_annotation",
+        "junit",
+    ],
+    static_libs: [
+        "tradefed",
+    ],
+    srcs: [
+        "common/**/*.java",
+        "host/**/*.java",
+    ],
+}
+
+// A library for interacting with time-related shell "cmd" commands from
+// instrumentation/device tests.
+java_library {
+    name: "device_time_shell_utils",
+    defaults: ["cts_defaults"],
+    libs: [
+        "androidx.annotation_annotation",
+        "junit",
+    ],
+    static_libs: [
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
+    ],
+    srcs: [
+        "common/**/*.java",
+        "device/**/*.java",
+    ],
+}
diff --git a/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceConfigKeys.java b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceConfigKeys.java
new file mode 100644
index 0000000..67c0289
--- /dev/null
+++ b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceConfigKeys.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell;
+
+/** Constants for interacting with the device_config service. */
+public final class DeviceConfigKeys {
+
+    /**
+     * The DeviceConfig namespace used for the time_detector, time_zone_detector and
+     * location_time_zone_manager.
+     */
+    public static final String NAMESPACE_SYSTEM_TIME = "system_time";
+
+    private DeviceConfigKeys() {
+        // No need to instantiate.
+    }
+
+    /**
+     * Keys and values associated with the location_time_zone_manager.
+     * See also {@link LocationTimeZoneManagerShellHelper}.
+     */
+    final class LocationTimeZoneManager {
+
+        private LocationTimeZoneManager() {
+            // No need to instantiate.
+        }
+
+        /**
+         * The key for the server flag that can override the device config for whether the primary
+         * location time zone provider is enabled, disabled, or (for testing) in simulation mode.
+         */
+        static final String KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE =
+                "primary_location_time_zone_provider_mode_override";
+
+        /**
+         * The key for the server flag that can override the device config for whether the secondary
+         * location time zone provider is enabled or disabled, or (for testing) in simulation mode.
+         */
+        static final String KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE =
+                "secondary_location_time_zone_provider_mode_override";
+
+        /**
+         * The "simulated" provider mode.
+         * For use with {@link #KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE} and {@link
+         * #KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE}.
+         */
+        static final String PROVIDER_MODE_SIMULATED = "simulated";
+
+        /**
+         * The "disabled" provider mode (equivalent to there being no provider configured).
+         * For use with {@link #KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE} and {@link
+         * #KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE}.
+         */
+        static final String PROVIDER_MODE_DISABLED = "disabled";
+
+        /**
+         * The key for the server flag that can override the device config for the package name of
+         * the primary provider (when enabled).
+         */
+        static final String KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_PACKAGE_NAME_OVERRIDE =
+                "primary_location_time_zone_provider_package_name_override";
+
+        /**
+         * The key for the server flag that can override the device config for the package name of
+         * the secondary provider (when enabled).
+         */
+        static final String KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_PACKAGE_NAME_OVERRIDE =
+                "secondary_location_time_zone_provider_package_name_override";
+    }
+
+    /**
+     * Keys and values associated with the time_detector. See also {@link
+     * TimeZoneDetectorShellHelper}.
+     */
+    public final class TimeDetector {
+
+        private TimeDetector() {
+            // No need to instantiate.
+        }
+
+        /**
+         * See {@link
+         * com.android.server.timedetector.ServerFlags#KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE}
+         */
+        public static final String KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE =
+                "time_detector_origin_priorities_override";
+
+        /**
+         * See {@link com.android.server.timedetector.TimeDetectorStrategy#ORIGIN_NETWORK}.
+         */
+        public static final String ORIGIN_NETWORK = "network";
+
+        /**
+         * See {@link com.android.server.timedetector.TimeDetectorStrategy#ORIGIN_EXTERNAL}.
+         */
+        public static final String ORIGIN_EXTERNAL = "external";
+    }
+}
diff --git a/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceConfigShellHelper.java b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceConfigShellHelper.java
new file mode 100644
index 0000000..550daf8
--- /dev/null
+++ b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceConfigShellHelper.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell;
+
+import androidx.annotation.NonNull;
+
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.Maps;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A class for interacting with the {@code device_config} service via the shell "cmd" command-line
+ * interface. Some behavior it supports is not available via the Android @SystemApi.
+ * See {@link com.android.providers.settings.DeviceConfigService} for the shell command
+ * implementation details.
+ */
+public class DeviceConfigShellHelper {
+
+    /**
+     * Value used with {@link #setSyncModeForTest}, {@link #setSyncDisabled(String)}.
+     */
+    public static final String SYNC_DISABLED_MODE_NONE = "none";
+
+    /**
+     * Value used with {@link #setSyncModeForTest}, {@link #setSyncDisabled(String)}.
+     */
+    public static final String SYNC_DISABLED_MODE_UNTIL_REBOOT = "until_reboot";
+
+    /**
+     * Value used with {@link #setSyncModeForTest}, {@link #setSyncDisabled(String)}.
+     */
+    public static final String SYNC_DISABLED_MODE_PERSISTENT = "persistent";
+
+    private static final String SERVICE_NAME = "device_config";
+
+    private static final String SHELL_CMD_PREFIX = "cmd " + SERVICE_NAME + " ";
+
+    @NonNull
+    private final DeviceShellCommandExecutor mShellCommandExecutor;
+
+    public DeviceConfigShellHelper(DeviceShellCommandExecutor shellCommandExecutor) {
+        mShellCommandExecutor = Objects.requireNonNull(shellCommandExecutor);
+    }
+
+    /**
+     * Executes "is_sync_disabled_for_tests". Returns {@code true} or {@code false}.
+     */
+    public boolean isSyncDisabled() throws Exception {
+        String cmd = SHELL_CMD_PREFIX + "is_sync_disabled_for_tests";
+        return mShellCommandExecutor.executeToBoolean(cmd);
+    }
+
+    /**
+     * Executes "set_sync_disabled_for_tests". Accepts one of
+     * {@link #SYNC_DISABLED_MODE_PERSISTENT}, {@link #SYNC_DISABLED_MODE_UNTIL_REBOOT} or
+     * {@link #SYNC_DISABLED_MODE_NONE}.
+     */
+    public void setSyncDisabled(String syncDisabledMode) throws Exception {
+        String cmd = String.format(
+                SHELL_CMD_PREFIX + "set_sync_disabled_for_tests %s", syncDisabledMode);
+        mShellCommandExecutor.executeToTrimmedString(cmd);
+    }
+
+    /**
+     * Executes "list" with a namespace.
+     */
+    public NamespaceEntries list(String namespace) throws Exception {
+        Objects.requireNonNull(namespace);
+
+        String cmd = String.format(SHELL_CMD_PREFIX + "list %s", namespace);
+        String output = mShellCommandExecutor.executeToTrimmedString(cmd);
+        Map<String, String> keyValues = new HashMap();
+        try (BufferedReader reader = new BufferedReader(new StringReader(output))) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                int separatorPos = line.indexOf('=');
+                String key = line.substring(0, separatorPos);
+                String value = line.substring(separatorPos + 1);
+                keyValues.put(key, value);
+            }
+        }
+        return new NamespaceEntries(namespace, keyValues);
+    }
+
+    /** Executes "put" without the trailing "default" argument. */
+    public void put(String namespace, String key, String value) throws Exception {
+        put(namespace, key, value, /*makeDefault=*/false);
+    }
+
+    /** Executes "put". */
+    public void put(String namespace, String key, String value, boolean makeDefault)
+            throws Exception {
+        String cmd = String.format(SHELL_CMD_PREFIX + "put %s %s %s", namespace, key, value);
+        if (makeDefault) {
+            cmd += " default";
+        }
+        mShellCommandExecutor.executeToTrimmedString(cmd);
+    }
+
+    /** Executes "delete". */
+    public void delete(String namespace, String key) throws Exception {
+        String cmd = String.format(SHELL_CMD_PREFIX + "delete %s %s", namespace, key);
+        mShellCommandExecutor.executeToTrimmedString(cmd);
+    }
+
+    /**
+     * A test helper method that captures the current sync mode and set of namespace values and sets
+     * the current sync mode. See {@link #restoreDeviceConfigStateForTest(PreTestState)}.
+     */
+    public PreTestState setSyncModeForTest(String syncMode, String... namespacesToSave)
+            throws Exception {
+        List<NamespaceEntries> savedValues = new ArrayList<>();
+        for (String namespacetoSave : namespacesToSave) {
+            NamespaceEntries namespaceValues = list(namespacetoSave);
+            savedValues.add(namespaceValues);
+        }
+        PreTestState preTestState = new PreTestState(isSyncDisabled(), savedValues);
+        setSyncDisabled(syncMode);
+        return preTestState;
+    }
+
+    /**
+     * Restores the sync mode after a test. See {@link #setSyncModeForTest}.
+     */
+    public void restoreDeviceConfigStateForTest(PreTestState restoreState) throws Exception {
+        for (NamespaceEntries oldEntries : restoreState.mSavedValues) {
+            NamespaceEntries currentEntries = list(oldEntries.namespace);
+
+            MapDifference<String, String> difference =
+                    Maps.difference(oldEntries.keyValues, currentEntries.keyValues);
+            deleteAll(oldEntries.namespace, difference.entriesOnlyOnRight());
+            putAll(oldEntries.namespace, difference.entriesOnlyOnLeft());
+            Map<String, String> entriesToUpdate =
+                    subMap(oldEntries.keyValues, difference.entriesDiffering().keySet());
+            putAll(oldEntries.namespace, entriesToUpdate);
+        }
+        setSyncDisabled(restoreState.mIsSyncDisabled
+                ? SYNC_DISABLED_MODE_UNTIL_REBOOT : SYNC_DISABLED_MODE_NONE);
+    }
+
+    private static <X, Y> Map<X, Y> subMap(Map<X, Y> keyValues, Set<X> keySet) {
+        return Maps.filterKeys(keyValues, keySet::contains);
+    }
+
+    private void putAll(String namespace, Map<String, String> entriesToAdd) throws Exception {
+        for (Map.Entry<String, String> entryToAdd : entriesToAdd.entrySet()) {
+            put(namespace, entryToAdd.getKey(), entryToAdd.getValue());
+        }
+    }
+
+    private void deleteAll(String namespace, Map<String, String> entriesToDelete) throws Exception {
+        for (Map.Entry<String, String> entryToDelete : entriesToDelete.entrySet()) {
+            delete(namespace, entryToDelete.getKey());
+        }
+    }
+
+    /** Opaque saved state information. */
+    public static class PreTestState {
+        private final boolean mIsSyncDisabled;
+        private final List<NamespaceEntries> mSavedValues = new ArrayList<>();
+
+        private PreTestState(boolean isSyncDisabled, List<NamespaceEntries> values) {
+            mIsSyncDisabled = isSyncDisabled;
+            mSavedValues.addAll(values);
+        }
+    }
+
+    public static class NamespaceEntries {
+        public final String namespace;
+        public final Map<String, String> keyValues = new HashMap<>();
+
+        public NamespaceEntries(String namespace, Map<String, String> keyValues) {
+            this.namespace = Objects.requireNonNull(namespace);
+            this.keyValues.putAll(Objects.requireNonNull(keyValues));
+        }
+    }
+}
diff --git a/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceShellCommandExecutor.java b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceShellCommandExecutor.java
new file mode 100644
index 0000000..c999181
--- /dev/null
+++ b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/DeviceShellCommandExecutor.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell;
+
+import androidx.annotation.NonNull;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+/** An abstraction for running shell commands. */
+public abstract class DeviceShellCommandExecutor {
+
+    /** Executes a command, logs and returns a string from stdout. */
+    @NonNull
+    public final String executeToString(@NonNull String command) throws Exception {
+        byte[] bytes = executeToBytesInternal(command);
+        String result = parseBytesAsString(bytes);
+        log("Executed '" + command + "': Result='" + result + "'");
+        return result;
+    }
+
+    /** Executes a command, logs and returns a trimmed string from stdout. */
+    @NonNull
+    public final String executeToTrimmedString(@NonNull String command) throws Exception {
+        byte[] bytes = executeToBytesInternal(command);
+        String result = parseBytesAsString(bytes).trim();
+        log("Executed '" + command + "': Result='" + result + "'");
+        return result;
+    }
+
+    /**
+     * Executes a command, logs and returns a boolean based on whether "true" or "false" was
+     * printed to from stdout.
+     */
+    @NonNull
+    public final boolean executeToBoolean(@NonNull String command) throws Exception {
+        byte[] bytes = executeToBytesInternal(command);
+        boolean result = parseBytesAsBoolean(bytes);
+        log("Executed '" + command + "': Result='" + result + "'");
+        return result;
+    }
+
+    /** Executes a command, logs and returns a byte array from stdout. */
+    @NonNull
+    public final byte[] executeToBytes(@NonNull String command) throws Exception {
+        byte[] bytes = executeToBytesInternal(command);
+        log("Executed '" + command + "': Result='" + Arrays.toString(bytes) + "'");
+        return bytes;
+    }
+
+    /** The raw execution method for subclasses to implement. */
+    @NonNull
+    protected abstract byte[] executeToBytesInternal(@NonNull String command) throws Exception;
+
+    /** The logging method for subclasses to implement. */
+    protected abstract void log(@NonNull String msg);
+
+    /**
+     * Ignoring leading/trainling whitespace, matches "true" or "false" or throws an exception.
+     */
+    public static boolean parseBytesAsBoolean(@NonNull byte[] result) {
+        String resultString = parseBytesAsString(result).trim();
+        if (resultString.equals("true")) {
+            return true;
+        } else if (resultString.equals("false")) {
+            return false;
+        } else {
+            throw new AssertionError("Command returned unexpected result: " + resultString);
+        }
+    }
+
+    /**
+     * Converts command line bytes to a String.
+     */
+    protected static String parseBytesAsString(byte[] result) {
+        return new String(result, 0, result.length, StandardCharsets.ISO_8859_1);
+    }
+}
diff --git a/tests/tests/time/shell_utils/common/android/app/time/cts/shell/LocationShellHelper.java b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/LocationShellHelper.java
new file mode 100644
index 0000000..7049f1b
--- /dev/null
+++ b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/LocationShellHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell;
+
+import static android.app.time.cts.shell.DeviceShellCommandExecutor.parseBytesAsBoolean;
+
+import java.util.Objects;
+
+/**
+ * A class for interacting with the {@code location} service via the shell "cmd" command-line
+ * interface.
+ */
+public class LocationShellHelper {
+
+    /**
+     * The name of the service for shell commands,
+     */
+    private static final String SERVICE_NAME = "location";
+
+    /**
+     * A shell command that sets the current user's "location enabled" setting value.
+     */
+    private static final String SHELL_COMMAND_SET_LOCATION_ENABLED = "set-location-enabled";
+
+    /**
+     * A shell command that gets the current user's "location enabled" setting value.
+     */
+    private static final String SHELL_COMMAND_IS_LOCATION_ENABLED = "is-location-enabled";
+
+    private static final String SHELL_CMD_PREFIX = "cmd " + SERVICE_NAME + " ";
+
+    private final DeviceShellCommandExecutor mShellCommandExecutor;
+
+    public LocationShellHelper(DeviceShellCommandExecutor shellCommandExecutor) {
+        mShellCommandExecutor = Objects.requireNonNull(shellCommandExecutor);
+    }
+
+    /** Executes "is-location-enabled". */
+    public boolean isLocationEnabledForCurrentUser() throws Exception {
+        return mShellCommandExecutor.executeToBoolean(
+                SHELL_CMD_PREFIX + SHELL_COMMAND_IS_LOCATION_ENABLED);
+    }
+
+    /** Executes "set-location-enabled". */
+    public void setLocationEnabledForCurrentUser(boolean enabled) throws Exception {
+        String cmd = String.format("%s %s", SHELL_COMMAND_SET_LOCATION_ENABLED, enabled);
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd);
+    }
+}
diff --git a/tests/tests/time/shell_utils/common/android/app/time/cts/shell/LocationTimeZoneManagerShellHelper.java b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/LocationTimeZoneManagerShellHelper.java
new file mode 100644
index 0000000..416443c
--- /dev/null
+++ b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/LocationTimeZoneManagerShellHelper.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell;
+
+import static android.app.time.cts.shell.DeviceConfigKeys.LocationTimeZoneManager.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
+import static android.app.time.cts.shell.DeviceConfigKeys.LocationTimeZoneManager.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
+import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.Objects;
+
+/**
+ * A class for interacting with the {@code location_time_zone_manager} service via the shell "cmd"
+ * command-line interface.
+ */
+public class LocationTimeZoneManagerShellHelper {
+    /**
+     * The index of the primary location time zone provider, used for shell commands.
+     */
+    public static final int PRIMARY_PROVIDER_INDEX = 0;
+
+    /**
+     * The index of the secondary location time zone provider, used for shell commands.
+     */
+    public static final int SECONDARY_PROVIDER_INDEX = 1;
+
+    /**
+     * The "disabled" provider mode (equivalent to there being no provider configured).
+     */
+    public static final String PROVIDER_MODE_DISABLED =
+            DeviceConfigKeys.LocationTimeZoneManager.PROVIDER_MODE_DISABLED;
+
+    /**
+     * The "simulated" provider mode.
+     */
+    public static final String PROVIDER_MODE_SIMULATED =
+            DeviceConfigKeys.LocationTimeZoneManager.PROVIDER_MODE_SIMULATED;
+
+    /**
+     * Simulated provider test command that simulates the bind succeeding.
+     */
+    public static final String SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND = "on_bind";
+
+    /**
+     * Simulated provider test command that simulates the provider reporting uncertainty.
+     */
+    public static final String SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN = "uncertain";
+
+    /**
+     * Simulated provider test command that simulates a successful time zone detection.
+     */
+    public static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS = "success";
+
+    /**
+     * Argument for {@link #SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS} to specify TZDB time zone IDs.
+     */
+    public static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ = "tz";
+
+    /**
+     * The name of the service for shell commands.
+     */
+    private static final String SERVICE_NAME = "location_time_zone_manager";
+
+    /**
+     * A shell command that starts the service (after stop).
+     */
+    private static final String SHELL_COMMAND_START = "start";
+
+    /**
+     * A shell command that stops the service.
+     */
+    private static final String SHELL_COMMAND_STOP = "stop";
+
+    /**
+     * A shell command that tells the service to record state information during tests. The next
+     * argument value is "true" or "false".
+     */
+    private static final String SHELL_COMMAND_RECORD_PROVIDER_STATES = "record_provider_states";
+
+    /**
+     * A shell command that tells the service to dump its current state.
+     */
+    private static final String SHELL_COMMAND_DUMP_STATE = "dump_state";
+
+    /**
+     * Option for {@link #SHELL_COMMAND_DUMP_STATE} that tells it to dump state as a binary proto.
+     */
+    private static final String DUMP_STATE_OPTION_PROTO = "proto";
+
+    /**
+     * A shell command that sends test commands to a provider
+     */
+    private static final String SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND =
+            "send_provider_test_command";
+
+    private static final String SHELL_CMD_PREFIX = "cmd " + SERVICE_NAME + " ";
+
+    private final DeviceShellCommandExecutor mShellCommandExecutor;
+    private final DeviceConfigShellHelper mDeviceConfigShellHelper;
+
+    public LocationTimeZoneManagerShellHelper(DeviceShellCommandExecutor shellCommandExecutor) {
+        mShellCommandExecutor = Objects.requireNonNull(shellCommandExecutor);
+        mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor);
+    }
+
+    /**
+     * Throws an {@link org.junit.AssumptionViolatedException} if the location_time_zone_manager
+     * service is not found. The service can be turned off in config, so this can be used to prevent
+     * CTS tests that need it from running.
+     */
+    public void assumeLocationTimeZoneManagerIsPresent() throws Exception {
+        assumeTrue(isLocationTimeZoneManagerPresent());
+    }
+
+    /**
+     * Returns {@code false} if the location_time_zone_manager service is not found.
+     */
+    public boolean isLocationTimeZoneManagerPresent() throws Exception {
+        // Look for the service name in "cmd -l".
+        String serviceList = mShellCommandExecutor.executeToString("cmd -l");
+        try (BufferedReader reader = new BufferedReader(new StringReader(serviceList))) {
+            String serviceName;
+            while ((serviceName = reader.readLine()) != null) {
+                serviceName = serviceName.trim();
+                if (SERVICE_NAME.equals(serviceName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /** Executes "start". Starts the service. */
+    public void start() throws Exception {
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + SHELL_COMMAND_START);
+    }
+
+    /** Executes "stop". Stops the service. */
+    public void stop() throws Exception {
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + SHELL_COMMAND_STOP);
+    }
+
+    /** Executes "record_provider_states". */
+    public void recordProviderStates(boolean enabled) throws Exception {
+        String cmd = String.format("%s %s", SHELL_COMMAND_RECORD_PROVIDER_STATES, enabled);
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd);
+    }
+
+    /** Executes "dump_state". */
+    public byte[] dumpState() throws Exception {
+        String cmd = String.format("%s --%s", SHELL_COMMAND_DUMP_STATE, DUMP_STATE_OPTION_PROTO);
+        return mShellCommandExecutor.executeToBytes(SHELL_CMD_PREFIX + cmd);
+    }
+
+    /** Modifies a provider's mode using "device_config" commands. */
+    public void setProviderModeOverride(int providerIndex, String mode) throws Exception {
+        String deviceConfigKey;
+        if (providerIndex == PRIMARY_PROVIDER_INDEX) {
+            deviceConfigKey = KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
+        } else {
+            deviceConfigKey = KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
+        }
+
+        if (mode == null) {
+            mDeviceConfigShellHelper.delete(NAMESPACE_SYSTEM_TIME, deviceConfigKey);
+        } else {
+            mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME, deviceConfigKey, mode);
+        }
+    }
+
+    /**
+     * Simulates a provider successfully binding using the "send_provider_test_command" command.
+     */
+    public void simulateProviderBind(int providerIndex) throws Exception {
+        sendProviderTestCommand(providerIndex, SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND);
+    }
+
+    /**
+     * Simulates a provider generating an uncertain report using the "send_provider_test_command"
+     * command.
+     */
+    public void simulateProviderUncertain(int providerIndex) throws Exception {
+        sendProviderTestCommand(providerIndex, SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN);
+    }
+
+    /**
+     * Simulates a provider generating a suggestion using the "send_provider_test_command" command.
+     */
+    public void simulateProviderSuggestion(int providerIndex, String... zoneIds)
+            throws Exception {
+        String timeZoneIds = String.join("&", zoneIds);
+        String testCommand = String.format("%s %s=string_array:%s",
+                SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS,
+                SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ,
+                timeZoneIds);
+        sendProviderTestCommand(providerIndex, testCommand);
+    }
+
+    /** Executes "send_provider_test_command". */
+    private void sendProviderTestCommand(int providerIndex, String testCommand) throws Exception {
+        String cmd = String.format("%s %s %s",
+                SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND, providerIndex, testCommand);
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd);
+    }
+}
diff --git a/tests/tests/time/shell_utils/common/android/app/time/cts/shell/TimeZoneDetectorShellHelper.java b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/TimeZoneDetectorShellHelper.java
new file mode 100644
index 0000000..8b8625e
--- /dev/null
+++ b/tests/tests/time/shell_utils/common/android/app/time/cts/shell/TimeZoneDetectorShellHelper.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell;
+
+import java.util.Objects;
+
+/**
+ * A class for interacting with the {@code time_zone_detector} service via the shell "cmd"
+ * command-line interface.
+ */
+public final class TimeZoneDetectorShellHelper {
+
+    /**
+     * The name of the service for shell commands.
+     */
+    private static final String SERVICE_NAME = "time_zone_detector";
+
+    /**
+     * A shell command that prints the current "auto time zone detection" global setting value.
+     */
+    private static final String SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED =
+            "is_auto_detection_enabled";
+
+    /**
+     * A shell command that sets the current "auto time zone detection" global setting value.
+     */
+    private static final String SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED =
+            "set_auto_detection_enabled";
+
+    /**
+     * A shell command that prints whether the telephony-based time zone detection feature is
+     * supported on the device.
+     */
+    private static final String SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED =
+            "is_telephony_detection_supported";
+
+    /**
+     * A shell command that prints whether the geolocation-based time zone detection feature is
+     * supported on the device.
+     */
+    private static final String SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED =
+            "is_geo_detection_supported";
+
+    /**
+     * A shell command that prints the current user's "location-based time zone detection enabled"
+     * setting.
+     */
+    private static final String SHELL_COMMAND_IS_GEO_DETECTION_ENABLED = "is_geo_detection_enabled";
+
+    /**
+     * A shell command that sets the current user's "location-based time zone detection enabled"
+     * setting.
+     */
+    private static final String SHELL_COMMAND_SET_GEO_DETECTION_ENABLED =
+            "set_geo_detection_enabled";
+
+    private static final String SHELL_CMD_PREFIX = "cmd " + SERVICE_NAME + " ";
+
+    private final DeviceShellCommandExecutor mShellCommandExecutor;
+
+    public TimeZoneDetectorShellHelper(DeviceShellCommandExecutor shellCommandExecutor) {
+        mShellCommandExecutor = Objects.requireNonNull(shellCommandExecutor);
+    }
+
+    /** Executes "is_auto_detection_enabled" */
+    public boolean isAutoDetectionEnabled() throws Exception {
+        return mShellCommandExecutor.executeToBoolean(
+                SHELL_CMD_PREFIX + SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED);
+    }
+
+    /** Executes "set_auto_detection_enabled" */
+    public void setAutoDetectionEnabled(boolean enabled) throws Exception {
+        String cmd = String.format("%s %s", SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED, enabled);
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd);
+    }
+
+    /** Executes "is_geo_detection_enabled" */
+    public boolean isGeoDetectionEnabled() throws Exception {
+        return mShellCommandExecutor.executeToBoolean(
+                SHELL_CMD_PREFIX + SHELL_COMMAND_IS_GEO_DETECTION_ENABLED);
+    }
+
+    /** Executes "set_geo_detection_enabled" */
+    public void setGeoDetectionEnabled(boolean enabled) throws Exception {
+        String cmd = String.format("%s %s", SHELL_COMMAND_SET_GEO_DETECTION_ENABLED, enabled);
+        mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd);
+    }
+
+    /** Executes "is_geo_detection_supported" */
+    public boolean isGeoDetectionSupported() throws Exception {
+        return mShellCommandExecutor.executeToBoolean(
+                SHELL_CMD_PREFIX + SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED);
+    }
+
+    /** Executes "is_telephony_detection_supported" */
+    public boolean isTelephonyDetectionSupported() throws Exception {
+        return mShellCommandExecutor.executeToBoolean(
+                SHELL_CMD_PREFIX + SHELL_COMMAND_IS_TELEPHONY_DETECTION_SUPPORTED);
+    }
+}
diff --git a/tests/tests/time/shell_utils/device/android/app/time/cts/shell/device/InstrumentationShellCommandExecutor.java b/tests/tests/time/shell_utils/device/android/app/time/cts/shell/device/InstrumentationShellCommandExecutor.java
new file mode 100644
index 0000000..5d7d7ac
--- /dev/null
+++ b/tests/tests/time/shell_utils/device/android/app/time/cts/shell/device/InstrumentationShellCommandExecutor.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell.device;
+
+import static org.junit.Assert.fail;
+
+import android.app.UiAutomation;
+import android.app.time.cts.shell.DeviceShellCommandExecutor;
+import android.os.ParcelFileDescriptor;
+
+import androidx.annotation.NonNull;
+
+import com.google.common.io.ByteStreams;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Objects;
+
+public final class InstrumentationShellCommandExecutor
+        extends DeviceShellCommandExecutor {
+
+    private final UiAutomation mUiAutomation;
+
+    public InstrumentationShellCommandExecutor(@NonNull UiAutomation uiAutomation) {
+        mUiAutomation = Objects.requireNonNull(uiAutomation);
+    }
+
+    @Override
+    protected byte[] executeToBytesInternal(String command) throws Exception {
+        ParcelFileDescriptor[] parcelFileDescriptors =
+                mUiAutomation.executeShellCommandRwe(command);
+        // Close stdin immediately.
+        parcelFileDescriptors[1].close();
+
+        byte[] stdOut = readBytesAndClose(parcelFileDescriptors[0]);
+        byte[] stdErr = readBytesAndClose(parcelFileDescriptors[2]);
+        if (stdErr.length > 0) {
+            fail("Command \'" + command + "\'produced stderr: "
+                    + parseBytesAsString(stdErr).trim());
+        }
+        return stdOut;
+    }
+
+    private static byte[] readBytesAndClose(ParcelFileDescriptor parcelFileDescriptor)
+            throws IOException {
+        try (FileInputStream output = new FileInputStream(
+                parcelFileDescriptor.getFileDescriptor())) {
+            return ByteStreams.toByteArray(output);
+        }
+    }
+
+    @Override
+    protected void log(String msg) {
+        System.out.println("InstrumentationShellCommandExecutor: " + msg);
+    }
+}
diff --git a/tests/tests/time/shell_utils/host/android/app/time/cts/shell/host/HostShellCommandExecutor.java b/tests/tests/time/shell_utils/host/android/app/time/cts/shell/host/HostShellCommandExecutor.java
new file mode 100644
index 0000000..5356617
--- /dev/null
+++ b/tests/tests/time/shell_utils/host/android/app/time/cts/shell/host/HostShellCommandExecutor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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.app.time.cts.shell.host;
+
+import android.app.time.cts.shell.DeviceShellCommandExecutor;
+
+import androidx.annotation.NonNull;
+
+import com.android.tradefed.device.CollectingByteOutputReceiver;
+import com.android.tradefed.device.ITestDevice;
+
+import java.util.Objects;
+
+public final class HostShellCommandExecutor extends DeviceShellCommandExecutor {
+
+    private final ITestDevice mDevice;
+
+    public HostShellCommandExecutor(@NonNull ITestDevice device) {
+        mDevice = Objects.requireNonNull(device);
+    }
+
+    @Override
+    @NonNull
+    protected byte[] executeToBytesInternal(String command) throws Exception {
+        CollectingByteOutputReceiver bytesReceiver = new CollectingByteOutputReceiver();
+        mDevice.executeShellCommand(command, bytesReceiver);
+        return bytesReceiver.getOutput();
+    }
+
+    @Override
+    protected void log(String msg) {
+        System.out.println("HostShellCommandExecutor: " + msg);
+    }
+}
diff --git a/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java b/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java
index ee69fc1..0128c80 100644
--- a/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java
+++ b/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java
@@ -16,39 +16,39 @@
 
 package android.app.time.cts;
 
-import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
+import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME;
+import static android.app.time.cts.shell.DeviceConfigShellHelper.SYNC_DISABLED_MODE_UNTIL_REBOOT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-import android.app.UiAutomation;
+import android.app.Instrumentation;
 import android.app.time.Capabilities;
 import android.app.time.ExternalTimeSuggestion;
 import android.app.time.TimeManager;
 import android.app.time.TimeZoneCapabilities;
 import android.app.time.TimeZoneCapabilitiesAndConfig;
 import android.app.time.TimeZoneConfiguration;
+import android.app.time.cts.shell.DeviceConfigKeys;
+import android.app.time.cts.shell.DeviceConfigShellHelper;
+import android.app.time.cts.shell.DeviceShellCommandExecutor;
+import android.app.time.cts.shell.device.InstrumentationShellCommandExecutor;
 import android.content.Context;
 import android.location.LocationManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.provider.DeviceConfig;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
-import com.google.common.io.ByteStreams;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
-import java.io.FileInputStream;
-import java.io.IOException;
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
 import java.util.concurrent.ExecutorService;
@@ -65,29 +65,26 @@
     @Rule
     public final AdoptShellPermissionsRule shellPermRule = new AdoptShellPermissionsRule();
 
-    private boolean mWasDeviceConfigSyncDisabled;
+    private DeviceConfigShellHelper mDeviceConfigShellHelper;
+    private DeviceConfigShellHelper.PreTestState mDeviceConfigPreTestState;
 
     @Before
     public void before() throws Exception {
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        DeviceShellCommandExecutor shellCommandExecutor = new InstrumentationShellCommandExecutor(
+                instrumentation.getUiAutomation());
+        mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor);
+
         // This anticipates a future state where a generally applied target preparer may disable
         // device_config sync for all CTS tests: only suspend syncing if it isn't already suspended,
         // and only resume it if this test suspended it.
-        mWasDeviceConfigSyncDisabled = DeviceConfigShellCommand.isSyncDisabled();
-        if (!mWasDeviceConfigSyncDisabled) {
-            DeviceConfigShellCommand.setSyncDisabled(
-                    DeviceConfigShellCommand.SYNC_DISABLED_MODE_UNTIL_REBOOT);
-        }
+        mDeviceConfigPreTestState = mDeviceConfigShellHelper.setSyncModeForTest(
+                SYNC_DISABLED_MODE_UNTIL_REBOOT, NAMESPACE_SYSTEM_TIME);
     }
 
     @After
     public void after() throws Exception {
-        DeviceConfigShellCommand.resetToDefaults(
-                DeviceConfigShellCommand.RESET_MODE_TRUSTED_DEFAULTS, NAMESPACE_SYSTEM_TIME);
-        if (!mWasDeviceConfigSyncDisabled) {
-            // Turn syncing back on if this test disabled it.
-            DeviceConfigShellCommand.setSyncDisabled(
-                    DeviceConfigShellCommand.SYNC_DISABLED_MODE_NONE);
-        }
+        mDeviceConfigShellHelper.restoreDeviceConfigStateForTest(mDeviceConfigPreTestState);
     }
 
     /**
@@ -188,10 +185,9 @@
 
         // Set the time detector to only use ORIGIN_NETWORK. The important aspect is that it isn't
         // ORIGIN_EXTERNAL, and so suggestions from external should be ignored.
-        DeviceConfig.setProperty(NAMESPACE_SYSTEM_TIME,
-                TimeDetectorServerFlags.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE,
-                TimeDetectorServerFlags.ORIGIN_NETWORK,
-                /*makeDefault=*/false);
+        mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME,
+                DeviceConfigKeys.TimeDetector.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE,
+                DeviceConfigKeys.TimeDetector.ORIGIN_NETWORK);
         sleepForAsyncOperation();
 
         long suggestion1Millis =
@@ -212,10 +208,9 @@
 
         // Set the time detector to only use ORIGIN_EXTERNAL.
         // The suggestion should have been stored and acted upon when the origin list changes.
-        DeviceConfig.setProperty(NAMESPACE_SYSTEM_TIME,
-                TimeDetectorServerFlags.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE,
-                TimeDetectorServerFlags.ORIGIN_EXTERNAL,
-                /*makeDefault=*/false);
+        mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME,
+                DeviceConfigKeys.TimeDetector.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE,
+                DeviceConfigKeys.TimeDetector.ORIGIN_EXTERNAL);
         sleepForAsyncOperation();
         assertTrue(System.currentTimeMillis() >= suggestion1Millis);
 
@@ -230,9 +225,6 @@
         timeManager.suggestExternalTime(
                 originalTimeSuggestion);
         sleepForAsyncOperation();
-
-        DeviceConfigShellCommand.resetToDefaults(
-                DeviceConfigShellCommand.RESET_MODE_TRUSTED_DEFAULTS, NAMESPACE_SYSTEM_TIME);
     }
 
     /**
@@ -299,71 +291,6 @@
     }
 
     /**
-     * A class for interacting with the {@link DeviceConfig} service via the command line. Some
-     * behavior it supports is not available via the Android @SystemApi.
-     * See {@link com.android.providers.settings.DeviceConfigService} for the shell command
-     * implementation details.
-     */
-    private static class DeviceConfigShellCommand {
-
-        static final String RESET_MODE_TRUSTED_DEFAULTS = "trusted_defaults";
-        static final String SYNC_DISABLED_MODE_NONE = "none";
-        static final String SYNC_DISABLED_MODE_UNTIL_REBOOT = "until_reboot";
-
-        private static final String SHELL_CMD_PREFIX = "cmd device_config ";
-
-        private DeviceConfigShellCommand() {}
-
-        static boolean isSyncDisabled() throws Exception {
-            String cmd = SHELL_CMD_PREFIX + "is_sync_disabled_for_tests";
-            String result = executeShellCommandInternal(cmd);
-            return Boolean.parseBoolean(result);
-        }
-
-        static void setSyncDisabled(String syncDisabledMode) throws Exception {
-            String cmd = String.format(
-                    SHELL_CMD_PREFIX + "set_sync_disabled_for_tests %s", syncDisabledMode);
-            executeShellCommandInternal(cmd);
-        }
-
-        static void resetToDefaults(String resetMode, String namespace) throws Exception {
-            String cmd = String.format(SHELL_CMD_PREFIX + "reset %s %s", resetMode, namespace);
-            executeShellCommandInternal(cmd);
-        }
-
-        private static String executeShellCommandInternal(String cmd) throws IOException {
-            UiAutomation uiAutomation =
-                    InstrumentationRegistry.getInstrumentation().getUiAutomation();
-            try (FileInputStream output = new FileInputStream(
-                    uiAutomation.executeShellCommand(cmd).getFileDescriptor())) {
-                return new String(ByteStreams.toByteArray(output));
-            }
-        }
-    }
-
-    /**
-     * device_config service flags and values for controlling the time_detector service.
-     */
-    private interface TimeDetectorServerFlags {
-        /**
-         * See {@link
-         * com.android.server.timedetector.ServerFlags#KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE}
-         */
-        String KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE =
-                "time_detector_origin_priorities_override";
-
-        /**
-         * See {@link com.android.server.timedetector.TimeDetectorStrategy#ORIGIN_NETWORK}.
-         */
-        String ORIGIN_NETWORK = "network";
-
-        /**
-         * See {@link com.android.server.timedetector.TimeDetectorStrategy#ORIGIN_EXTERNAL}.
-         */
-        String ORIGIN_EXTERNAL = "external";
-    }
-
-    /**
      * Sleeps for a length of time sufficient to allow async operations to complete. Many time
      * manager APIs are or could be asynchronous and deal with time, so there are no practical
      * alternatives.
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
index 04b80cf..352e31c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
@@ -228,6 +228,40 @@
         });
     }
 
+    /**
+     * Can't stretch past 1.0
+     */
+    @Test
+    public void testMaxStretch() throws Throwable {
+        EdgeEffect edgeEffect = new EdgeEffect(getContext());
+        edgeEffect.setSize(WIDTH, HEIGHT);
+        float pulled = edgeEffect.onPullDistance(1f, 0.5f);
+        assertEquals(1f, pulled, 0.001f);
+        assertEquals(1f, edgeEffect.getDistance(), 0.001f);
+        pulled = edgeEffect.onPullDistance(0.1f, 0.5f);
+        assertEquals(0.1f, pulled, 0.001f);
+        assertEquals(1f, edgeEffect.getDistance(), 0.001f);
+    }
+
+    /**
+     * A fling past 1.0 results in stopping at 1 and then retracting.
+     */
+    @Test
+    public void testMaxFling() throws Throwable {
+        MockVsyncHelper.runOnVsyncThread(() -> {
+            EdgeEffect edgeEffect = new EdgeEffect(getContext());
+            edgeEffect.setSize(WIDTH, HEIGHT);
+            assertEquals(0.99f, edgeEffect.onPullDistance(0.99f, 0.5f), 0.001f);
+            edgeEffect.onAbsorb(10000);
+            nextFrame();
+            drawEdgeEffect(edgeEffect, 0f, 0f);
+            assertEquals(1f, edgeEffect.getDistance(), 0.001f);
+            nextFrame();
+            drawEdgeEffect(edgeEffect, 0f, 0f);
+            assertTrue(edgeEffect.getDistance() < 1f);
+        });
+    }
+
     private RenderNode drawStretchEffect(float rotation) {
         EdgeEffect edgeEffect = new EdgeEffect(getContext());
         edgeEffect.setSize(WIDTH, HEIGHT);
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
index 2572593..7ab8c9c 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -63,7 +63,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.util.Collections;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
@@ -81,10 +81,10 @@
 
     private static final int TEST_NETWORK_MTU = 1500;
 
-    private static final Inet6Address LOCAL_V6_ADDRESS =
-            (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::2");
-    private static final Inet6Address SECONDARY_LOCAL_V6_ADDRESS =
-            (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::3");
+    private static final InetAddress LOCAL_ADDRESS =
+            InetAddresses.parseNumericAddress("198.51.100.1");
+    private static final InetAddress SECONDARY_LOCAL_ADDRESS =
+            InetAddresses.parseNumericAddress("198.51.100.2");
 
     private static final long IKE_DETERMINISTIC_INITIATOR_SPI =
             Long.parseLong("46B8ECA1E0D72A18", 16);
@@ -362,7 +362,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Before the VCN starts, the test network should have NOT_VCN_MANAGED
@@ -436,7 +436,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Get current cell Network then wait for it to drop (due to losing NOT_VCN_MANAGED) before
@@ -544,7 +544,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Get current cell Network then wait for it to drop (due to losing NOT_VCN_MANAGED) before
@@ -570,7 +570,7 @@
                                 TEST_NETWORK_MTU,
                                 true /* isMetered */,
                                 Collections.singleton(subId),
-                                SECONDARY_LOCAL_V6_ADDRESS);
+                                SECONDARY_LOCAL_ADDRESS);
 
                 try {
                     assertNotNull("No test network found", secondaryTestNetworkWrapper.tunNetwork);
@@ -639,7 +639,7 @@
                         TEST_NETWORK_MTU,
                         true /* isMetered */,
                         Collections.singleton(subId),
-                        LOCAL_V6_ADDRESS);
+                        LOCAL_ADDRESS);
         assertNotNull("No test network found", mTestNetworkWrapper.tunNetwork);
 
         // Before the VCN starts, the test network should have NOT_VCN_MANAGED
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java
index 4b79fa9..d7485b1 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnTestBase.java
@@ -60,7 +60,8 @@
                         .addDhGroup(DH_GROUP_2048_BIT_MODP)
                         .build();
 
-        final String serverHostname = "2001:db8:1::100";
+        // TODO: b/192610392 Improve VcnManagerTest CTS by adding IPv6 test case.
+        final String serverHostname = "192.0.2.1";
         final String testLocalId = "client.test.ike.android.net";
         final String testRemoteId = "server.test.ike.android.net";
         final byte[] psk = "ikeAndroidPsk".getBytes();
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
index 6a9aecc..c0a850d 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
@@ -45,6 +45,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -160,6 +161,7 @@
         return componentName != null ? componentName.getPackageName() : "";
     }
 
+    @Ignore("b/184963112")
     @Test
     public void testNonTrustedRecognitionServiceCanBlameCallingApp() throws Throwable {
         // This is a workaound solution for R QPR. We treat trusted if the current voice recognizer
@@ -170,6 +172,7 @@
         testVoiceRecognitionServiceBlameCallingApp(/* trustVoiceService */ true);
     }
 
+    @Ignore("b/184963112")
     @Test
     public void testTrustedRecognitionServiceCanBlameCallingApp() throws Throwable {
         // This is a workaround solution for R QPR. We treat trusted if the current voice recognizer
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
index 4ee903a..337d017 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
@@ -16,9 +16,13 @@
 
 package android.voiceinteraction.service;
 
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.RECORD_AUDIO;
+
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
 import android.Manifest;
+import android.app.UiAutomation;
 import android.content.Intent;
 import android.media.AudioFormat;
 import android.os.ParcelFileDescriptor;
@@ -35,6 +39,7 @@
 import android.voiceinteraction.common.Utils;
 
 import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -75,6 +80,10 @@
             return START_NOT_STICKY;
         }
 
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        // Drop any identity adopted earlier.
+        uiAutomation.dropShellPermissionIdentity();
+
         final int testEvent = intent.getIntExtra(Utils.KEY_TEST_EVENT, -1);
         Log.i(TAG, "testEvent = " + testEvent);
         if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST) {
@@ -87,15 +96,15 @@
         } else if (testEvent == Utils.VIS_HOLD_BIND_HOTWORD_DETECTION_PERMISSION_TEST) {
             runWithShellPermissionIdentity(() -> callCreateAlwaysOnHotwordDetector());
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST) {
-            runWithShellPermissionIdentity(() -> {
-                if (mAlwaysOnHotwordDetector != null) {
-                    mAlwaysOnHotwordDetector.triggerHardwareRecognitionEventForTest(/* status */ 0,
-                            /* soundModelHandle */ 100, /* captureAvailable */ true,
-                            /* captureSession */ 101, /* captureDelayMs */ 1000,
-                            /* capturePreambleMs */ 1001, /* triggerInData */ true,
-                            createFakeAudioFormat(), new byte[1024]);
-                }
-            });
+            // need to retain the identity until the callback is triggered
+            uiAutomation.adoptShellPermissionIdentity(RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD);
+            if (mAlwaysOnHotwordDetector != null) {
+                mAlwaysOnHotwordDetector.triggerHardwareRecognitionEventForTest(/* status */ 0,
+                        /* soundModelHandle */ 100, /* captureAvailable */ true,
+                        /* captureSession */ 101, /* captureDelayMs */ 1000,
+                        /* capturePreambleMs */ 1001, /* triggerInData */ true,
+                        createFakeAudioFormat(), new byte[1024]);
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_DSP_ONREJECT_TEST) {
             runWithShellPermissionIdentity(() -> {
                 if (mAlwaysOnHotwordDetector != null) {
@@ -107,33 +116,29 @@
                 }
             });
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST) {
-            runWithShellPermissionIdentity(() -> {
-                if (mAlwaysOnHotwordDetector != null) {
-                    ParcelFileDescriptor audioStream = createFakeAudioStream();
-                    if (audioStream != null) {
-                        mAlwaysOnHotwordDetector.startRecognition(
-                                audioStream,
-                                createFakeAudioFormat(),
-                                createFakePersistableBundleData());
-                    }
+            uiAutomation.adoptShellPermissionIdentity(RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD);
+            if (mAlwaysOnHotwordDetector != null) {
+                ParcelFileDescriptor audioStream = createFakeAudioStream();
+                if (audioStream != null) {
+                    mAlwaysOnHotwordDetector.startRecognition(
+                            audioStream,
+                            createFakeAudioFormat(),
+                            createFakePersistableBundleData());
                 }
-            });
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_FROM_SOFTWARE_TRIGGER_TEST) {
             runWithShellPermissionIdentity(() -> {
                 mSoftwareHotwordDetector = callCreateSoftwareHotwordDetector();
             }, Manifest.permission.MANAGE_HOTWORD_DETECTION);
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST) {
-            runWithShellPermissionIdentity(() -> {
-                if (mSoftwareHotwordDetector != null) {
-                    mSoftwareHotwordDetector.startRecognition();
-                }
-            });
+            uiAutomation.adoptShellPermissionIdentity(RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD);
+            if (mSoftwareHotwordDetector != null) {
+                mSoftwareHotwordDetector.startRecognition();
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_CALL_STOP_RECOGNITION) {
-            runWithShellPermissionIdentity(() -> {
-                if (mSoftwareHotwordDetector != null) {
-                    mSoftwareHotwordDetector.stopRecognition();
-                }
-            });
+            if (mSoftwareHotwordDetector != null) {
+                mSoftwareHotwordDetector.stopRecognition();
+            }
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_PROCESS_DIED_TEST) {
             runWithShellPermissionIdentity(() -> {
                 if (mAlwaysOnHotwordDetector != null) {
@@ -154,6 +159,8 @@
     public void onDestroy() {
         super.onDestroy();
         closeFakeAudioStream();
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
     }
 
     private AlwaysOnHotwordDetector callCreateAlwaysOnHotwordDetector() {
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
index 2a8309a..4faa7ae 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
@@ -71,7 +71,7 @@
     private static final String PRIVACY_CHIP_PKG = "com.android.systemui";
     private static final String PRIVACY_CHIP_ID = "privacy_chip";
     private static final Long PERMISSION_INDICATORS_NOT_PRESENT = 162547999L;
-    private static final Long CLEAR_CHIP_MS = 3000L;
+    private static final Long CLEAR_CHIP_MS = 5000L;
 
     private static Instrumentation sInstrumentation = InstrumentationRegistry.getInstrumentation();
     private static UiDevice sUiDevice = UiDevice.getInstance(sInstrumentation);
@@ -138,6 +138,7 @@
     @RequiresDevice
     public void testHotwordDetectionService_onDetectFromDsp_success()
             throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
         // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
         testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
@@ -146,6 +147,7 @@
         verifyDetectedResult(
                 performAndGetDetectionResult(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST),
                 MainHotwordDetectionService.DETECTED_RESULT);
+        verifyMicrophoneChip(true);
     }
 
     @Test
@@ -160,18 +162,13 @@
 
         assertThat(performAndGetDetectionResult(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONREJECT_TEST))
                 .isEqualTo(MainHotwordDetectionService.REJECTED_RESULT);
-        if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
-            // TODO ntmyren: test TV indicator
-        } else if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-            // TODO ntmyren: test Auto indicator
-        } else {
-            verifyMicrophoneChipHandheld(false);
-        }
+        verifyMicrophoneChip(false);
     }
 
     @Test
     public void testHotwordDetectionService_onDetectFromExternalSource_success()
             throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
         // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
         testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
@@ -181,12 +178,14 @@
                 performAndGetDetectionResult(
                         Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST),
                 MainHotwordDetectionService.DETECTED_RESULT);
+        verifyMicrophoneChip(true);
     }
 
     @Test
     @RequiresDevice
     public void testHotwordDetectionService_onDetectFromMic_success()
             throws Throwable {
+        Thread.sleep(CLEAR_CHIP_MS);
         // Create SoftwareHotwordDetector and wait the HotwordDetectionService ready
         testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_FROM_SOFTWARE_TRIGGER_TEST,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
@@ -195,6 +194,7 @@
         verifyDetectedResult(
                 performAndGetDetectionResult(Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST),
                 MainHotwordDetectionService.DETECTED_RESULT);
+        verifyMicrophoneChip(true);
     }
 
     @Test
@@ -291,6 +291,16 @@
         assertThat(audioStream).isNull();
     }
 
+    private void verifyMicrophoneChip(boolean shouldBePresent) throws Exception {
+        if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+            // TODO ntmyren: test TV indicator
+        } else if (sPkgMgr.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            // TODO ntmyren: test Auto indicator
+        } else {
+            verifyMicrophoneChipHandheld(shouldBePresent);
+        }
+    }
+
     private void verifyMicrophoneChipHandheld(boolean shouldBePresent) throws Exception {
         // If the change Id is not present, then isChangeEnabled will return true. To bypass this,
         // the change is set to "false" if present.
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 642e558..64a5cf3 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -17,7 +17,6 @@
 package android.widget.cts;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -862,12 +861,11 @@
                 ACTION_TRANSLUCENT_ACTIVITY_RESUMED);
         Intent intent = new Intent();
         intent.setComponent(COMPONENT_TRANSLUCENT_ACTIVITY);
-        intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
         // Launch the translucent activity in fullscreen to ensure the test activity won't resume
         // even on the freeform-first multi-window device.
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        mContext.startActivity(intent, options.toBundle());
+        mActivityRule.getActivity().startActivity(intent, options.toBundle());
         activityStarted.block();
         makeCustomToast();
         View view = mToast.getView();
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index fb825f7..850e81b 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -44,6 +44,9 @@
 import org.junit.runner.RunWith;
 import org.xmlpull.v1.XmlPullParser;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ZoomButtonTest {
@@ -126,11 +129,13 @@
 
     @LargeTest
     @Test
-    public void testSetZoomSpeed() {
+    public void testSetZoomSpeed() throws Throwable {
         final long[] zoomSpeeds = { 0, 100 };
         mZoomButton.setEnabled(true);
         ZoomClickListener zoomClickListener = new ZoomClickListener();
         mZoomButton.setOnClickListener(zoomClickListener);
+        final ZoomLongClickListener longClickListener = new ZoomLongClickListener();
+        mZoomButton.setOnLongClickListener(longClickListener);
 
         for (long zoomSpeed : zoomSpeeds) {
             // Reset the tracking state of our listener, but continue using it for testing
@@ -156,10 +161,29 @@
                             + " while long press timeout is " + minTimeUntilFirstInvocationMs,
                     actualTimeUntilFirstInvocationNs
                             > minTimeUntilFirstInvocationMs * NANOS_IN_MILLI);
+            assertTrue(longClickListener.postLatch.await(1, TimeUnit.SECONDS));
             assertTrue("First callback should have happened sooner than "
                             + actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI,
                     actualTimeUntilFirstInvocationNs
-                            <= (minTimeUntilFirstInvocationMs + 200) * NANOS_IN_MILLI);
+                            <= longClickListener.postAfterLongClick);
+        }
+    }
+
+    private static class ZoomLongClickListener implements View.OnLongClickListener, Runnable {
+        public long postAfterLongClick;
+        public CountDownLatch postLatch;
+
+        @Override
+        public boolean onLongClick(View v) {
+            postLatch = new CountDownLatch(1);
+            v.post(this);
+            return false;
+        }
+
+        @Override
+        public void run() {
+            postAfterLongClick = System.nanoTime();
+            postLatch.countDown();
         }
     }
 
diff --git a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
index 804b36d..e50d3a6 100644
--- a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
@@ -122,8 +122,8 @@
         boolean waitForStateChange() throws InterruptedException {
             CountDownLatch blocker;
             synchronized (mLock) {
-                if (mCountNumber > 0) {
-                    mCountNumber--;
+                mCountNumber--;
+                if (mCountNumber >= 0) {
                     return true;
                 }
                 blocker = mBlocker;
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
index 6b22913..188c2a9 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -201,6 +201,9 @@
             super.tearDown();
             return;
         }
+        if (null != mWifiP2pManager) {
+            removeAllPersistentGroups();
+        }
         mContext.unregisterReceiver(mReceiver);
 
         ShellIdentityUtils.invokeWithShellPermissions(
@@ -304,6 +307,24 @@
         cm.unregisterNetworkCallback(networkCallback);
     }
 
+    private void removeAllPersistentGroups() {
+        WifiP2pGroupList persistentGroups = getPersistentGroups();
+        assertNotNull(persistentGroups);
+        for (WifiP2pGroup group: persistentGroups.getGroupList()) {
+            resetResponse(mMyResponse);
+            ShellIdentityUtils.invokeWithShellPermissions(() -> {
+                mWifiP2pManager.deletePersistentGroup(mWifiP2pChannel,
+                        group.getNetworkId(),
+                        mActionListener);
+                assertTrue(waitForServiceResponse(mMyResponse));
+                assertTrue(mMyResponse.success);
+            });
+        }
+        persistentGroups = getPersistentGroups();
+        assertNotNull(persistentGroups);
+        assertEquals(0, persistentGroups.getGroupList().size());
+    }
+
     private boolean setupWifiP2p() {
         // Cannot support p2p alone
         if (!WifiFeature.isWifiSupported(getContext())) {
@@ -348,6 +369,7 @@
 
         assertEquals(WifiManager.WIFI_STATE_ENABLED, mMySync.expectedWifiState);
         assertEquals(WifiP2pManager.WIFI_P2P_STATE_ENABLED, mMySync.expectedP2pState);
+        removeAllPersistentGroups();
 
         return true;
     }
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index f851126..7cb6c17 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -97,6 +97,7 @@
 import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.compatibility.common.util.ThrowingRunnable;
+import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.MacAddressUtils;
 
 import java.io.BufferedReader;
@@ -1384,27 +1385,37 @@
                 assertTrue(result.networkId >= 0);
                 c.networkId = result.networkId;
             }
-            // open/owe, psk/sae, and wpa2e/wpa3e should be merged
-            // so they should have the same network ID.
-            assertEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
-            assertEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
-            assertEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
+            List<WifiConfiguration> expectedConfigs = testConfigs;
+            if (SdkLevel.isAtLeastS()) {
+                // open/owe, psk/sae, and wpa2e/wpa3e should be merged
+                // so they should have the same network ID.
+                assertEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
+                assertEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
+                assertEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
+            } else {
+                // Network IDs for different security types should be unique for R
+                assertNotEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
+                assertNotEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
+                assertNotEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
+                // WPA3-Enterprise is omitted when WPA2-Enterprise is present for R
+                expectedConfigs = testConfigs.subList(0, 5);
+            }
             List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
-            assertEquals(originalConfiguredNetworksNumber + testConfigs.size(),
+            assertEquals(originalConfiguredNetworksNumber + expectedConfigs.size(),
                     configuredNetworks.size());
-            assertConfigsAreFound(testConfigs, configuredNetworks);
+            assertConfigsAreFound(expectedConfigs, configuredNetworks);
 
             List<WifiConfiguration> privilegedConfiguredNetworks =
                     mWifiManager.getPrivilegedConfiguredNetworks();
-            assertEquals(originalPrivilegedConfiguredNetworksNumber + testConfigs.size(),
+            assertEquals(originalPrivilegedConfiguredNetworksNumber + expectedConfigs.size(),
                     privilegedConfiguredNetworks.size());
-            assertConfigsAreFound(testConfigs, privilegedConfiguredNetworks);
+            assertConfigsAreFound(expectedConfigs, privilegedConfiguredNetworks);
 
             List<WifiConfiguration> callerConfiguredNetworks =
                     mWifiManager.getCallerConfiguredNetworks();
-            assertEquals(originalCallerConfiguredNetworksNumber + testConfigs.size(),
+            assertEquals(originalCallerConfiguredNetworksNumber + expectedConfigs.size(),
                     callerConfiguredNetworks.size());
-            assertConfigsAreFound(testConfigs, callerConfiguredNetworks);
+            assertConfigsAreFound(expectedConfigs, callerConfiguredNetworks);
 
         } finally {
             for (WifiConfiguration c: testConfigs) {
@@ -2559,8 +2570,17 @@
             assertTrue(actionListener.onSuccessCalled);
             // Wait for connection to complete & ensure we are connected to the saved network.
             waitForConnection();
-            assertEquals(savedNetworkToConnect.networkId,
-                    mWifiManager.getConnectionInfo().getNetworkId());
+            if (SdkLevel.isAtLeastS()) {
+                assertEquals(savedNetworkToConnect.networkId,
+                        mWifiManager.getConnectionInfo().getNetworkId());
+            } else {
+                // In R, auto-upgraded network IDs may be different from the original saved network.
+                // Since we may end up selecting the auto-upgraded network ID for connection and end
+                // up connected to the original saved network with a different network ID, we should
+                // instead match by SSID.
+                assertEquals(savedNetworkToConnect.SSID,
+                        mWifiManager.getConnectionInfo().getSSID());
+            }
         } finally {
             // Re-enable all saved networks before exiting.
             if (savedNetworks != null) {
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 fca5cbc..a8866f2 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
@@ -571,54 +571,55 @@
                 ResultType.NEUTRAL, ResultUnit.NONE);
         reportLog.submit();
 
-        // Analyze results
-        assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures
-                        + ", ITERATIONS="
-                        + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level
-                        + ", AP SSID=" + testAp.SSID,
-                numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100);
+        /** TODO(b/192909380): enable the performance verification after device fix.
+            // Analyze results
+            assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures
+                            + ", ITERATIONS="
+                            + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level
+                            + ", AP SSID=" + testAp.SSID,
+                    numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100);
 
-        if (numFailures != NUM_OF_RTT_ITERATIONS) {
-            // Calculate an initial average using all measurements to determine distance outliers
-            double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
-            // Now figure out the distance outliers and mark them in the distance inclusion map
-            int validDistances = 0;
-            for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
-                if (distanceMms[i] - MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM < distanceAvg) {
-                    // Distances that are in range for the distribution are included in the map
-                    distanceInclusionMap[i] = true;
-                    validDistances++;
-                } else {
-                    // Distances that are out of range for the distribution are excluded in the map
-                    distanceInclusionMap[i] = false;
+            if (numFailures != NUM_OF_RTT_ITERATIONS) {
+                // Calculate an initial average using all measurements to determine distance outliers
+                double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
+                // Now figure out the distance outliers and mark them in the distance inclusion map
+                int validDistances = 0;
+                for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
+                    if (distanceMms[i] - MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM < distanceAvg) {
+                        // Distances that are in range for the distribution are included in the map
+                        distanceInclusionMap[i] = true;
+                        validDistances++;
+                    } else {
+                        // Distances that are out of range for the distribution are excluded in the map
+                        distanceInclusionMap[i] = false;
+                    }
                 }
-            }
 
-            assertTrue("After fails+outlier removal greater that 50% distances must remain: " +
-                    NUM_OF_RTT_ITERATIONS / 2, validDistances > NUM_OF_RTT_ITERATIONS / 2);
+                assertTrue("After fails+outlier removal greater that 50% distances must remain: " +
+                        NUM_OF_RTT_ITERATIONS / 2, validDistances > NUM_OF_RTT_ITERATIONS / 2);
 
-            // Remove the distance outliers and find the new average, min and max.
-            distanceSum = 0;
-            distanceMax = Integer.MIN_VALUE;
-            distanceMin = Integer.MAX_VALUE;
-            for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
-                if (distanceInclusionMap[i]) {
-                    distanceSum += distanceMms[i];
-                    distanceMin = Math.min(distanceMin, distanceMms[i]);
-                    distanceMax = Math.max(distanceMax, distanceMms[i]);
+                // Remove the distance outliers and find the new average, min and max.
+                distanceSum = 0;
+                distanceMax = Integer.MIN_VALUE;
+                distanceMin = Integer.MAX_VALUE;
+                for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
+                    if (distanceInclusionMap[i]) {
+                        distanceSum += distanceMms[i];
+                        distanceMin = Math.min(distanceMin, distanceMms[i]);
+                        distanceMax = Math.max(distanceMax, distanceMms[i]);
+                    }
                 }
-            }
-            distanceAvg = (double) distanceSum / validDistances;
-            assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation ="
-                            + (distanceMax - distanceAvg),
-                    (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
-            assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation ="
-                            + (distanceAvg - distanceMin),
-                    (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
-            for (int i = 0; i < numGoodResults; ++i) {
-                assertNotSame("Number of attempted measurements is 0", 0, numAttempted[i]);
-                assertNotSame("Number of successful measurements is 0", 0, numSuccessful[i]);
-            }
-        }
+                distanceAvg = (double) distanceSum / validDistances;
+                assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation ="
+                                + (distanceMax - distanceAvg),
+                        (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
+                assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation ="
+                                + (distanceAvg - distanceMin),
+                        (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
+                for (int i = 0; i < numGoodResults; ++i) {
+                    assertNotSame("Number of attempted measurements is 0", 0, numAttempted[i]);
+                    assertNotSame("Number of successful measurements is 0", 0, numSuccessful[i]);
+                }
+         */
     }
 }
diff --git a/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java b/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
index 37b995c..c2c24e5 100644
--- a/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
+++ b/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
@@ -119,8 +119,10 @@
         decode();
         String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, Key-priority: " +
                 "%d :: ", mDecoderMime, mDecoderName, mHeight, mKeyPriority);
-        Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + mOperatingRateExpected);
+        double expectedFps =
+                Math.min(mOperatingRateExpected, MAX_EXPECTED_FPS) * FPS_TOLERANCE_FACTOR;
+        Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + expectedFps);
         assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + mAchievedFps
-                + "/" + mOperatingRateExpected, mAchievedFps >= mOperatingRateExpected);
+                + "/" + expectedFps, mAchievedFps >= expectedFps);
     }
 }
diff --git a/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java b/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
index e599fa0..bd4c481 100644
--- a/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
+++ b/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
@@ -111,8 +111,10 @@
         String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, EncodeMime: %s," +
                 " Encoder: %s, Key-priority: %d :: ", mDecoderMime, mDecoderName, mHeight,
                 mEncoderMime, mEncoderName, mKeyPriority);
-        Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + mOperatingRateExpected);
+        double expectedFps =
+                Math.min(mOperatingRateExpected, MAX_EXPECTED_FPS) * FPS_TOLERANCE_FACTOR;
+        Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + expectedFps);
         assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + mAchievedFps
-                + "/" + mOperatingRateExpected, mAchievedFps >= mOperatingRateExpected);
+                + "/" + expectedFps, mAchievedFps >= expectedFps);
     }
 }
diff --git a/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java b/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java
index e590fb7..2805bbd 100644
--- a/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java
+++ b/tests/video/src/android/video/cts/CodecEncoderPerformanceTestBase.java
@@ -124,6 +124,8 @@
             mDecoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, -1);
             mEncoderFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, -1);
         }
+        mEncoderFormat.setInteger(MediaFormat.KEY_COMPLEXITY,
+                getEncoderMinComplexity(mEncoderName, mEncoderMime));
         mOperatingRateExpected /= 2.0;
     }
 
diff --git a/tests/video/src/android/video/cts/CodecPerformanceTestBase.java b/tests/video/src/android/video/cts/CodecPerformanceTestBase.java
index bb1b96b..8c8d705 100644
--- a/tests/video/src/android/video/cts/CodecPerformanceTestBase.java
+++ b/tests/video/src/android/video/cts/CodecPerformanceTestBase.java
@@ -22,6 +22,7 @@
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.os.Build;
+import android.util.Range;
 import android.view.Surface;
 
 import java.io.File;
@@ -41,6 +42,12 @@
     static final int SELECT_ALL = 0; // Select all codecs
     static final int SELECT_HARDWARE = 1; // Select Hardware codecs only
     static final int SELECT_SOFTWARE = 2; // Select Software codecs only
+    // allowed tolerance in measured fps vs expected fps, i.e. codecs achieving fps
+    // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as
+    // passing the test
+    static final double FPS_TOLERANCE_FACTOR = 0.95;
+    // TODO (b/193458026) Limit max expected fps to 240
+    static final int MAX_EXPECTED_FPS = 240;
     static final String mInputPrefix = WorkDir.getMediaDirString();
 
     ArrayList<MediaCodec.BufferInfo> mBufferInfos;
@@ -230,6 +237,20 @@
         return maxOperatingRate;
     }
 
+    int getEncoderMinComplexity(String codecName, String mime) throws IOException {
+        MediaCodec codec = MediaCodec.createByCodecName(codecName);
+        MediaCodecInfo mediaCodecInfo = codec.getCodecInfo();
+        int minComplexity = -1;
+        if (mediaCodecInfo.isEncoder()) {
+            Range<Integer> complexityRange = mediaCodecInfo
+                    .getCapabilitiesForType(mime).getEncoderCapabilities()
+                    .getComplexityRange();
+            minComplexity = complexityRange.getLower();
+        }
+        codec.release();
+        return minComplexity;
+    }
+
     void enqueueDecoderInput(int bufferIndex) {
         MediaCodec.BufferInfo info = mBufferInfos.get(mSampleIndex++);
         if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
diff --git a/tests/vr/jni/VrExtensionsJni.cpp b/tests/vr/jni/VrExtensionsJni.cpp
index fadc5e9..db573eb 100644
--- a/tests/vr/jni/VrExtensionsJni.cpp
+++ b/tests/vr/jni/VrExtensionsJni.cpp
@@ -449,7 +449,7 @@
         desc.layers = 1;
         desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
         desc.usage =
-                AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
+                AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
         AHardwareBuffer* hwbuffer = nullptr;
         int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
         ASSERT_EQ(error, NO_ERROR);
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index de90e52..835abfd 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -134,6 +134,9 @@
     <!-- b/62481870 -->
     <option name="compatibility:exclude-filter" value="CtsNativeMediaAAudioTestCases android.nativemedia.aaudio.AAudioOutputStreamCallbackTest#testPlayback" />
 
+    <!-- b/192313064 , b/192984235 -->
+    <option name="compatibility:exclude-filter" value="CtsNativeMediaAAudioTestCases android.nativemedia.aaudio.AAudioTests#test_aaudio_mmap_testBasicMmapOutput" />
+
     <!-- b/134654621 -->
     <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.AppConfigurationTests#testTaskCloseRestoreFreeOrientation" />
     <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.AppConfigurationTests#testAppOrientationRequestConfigClears" />
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index 886edd3..b60c486 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -59,6 +59,9 @@
     <!-- No Statsd -->
     <option name="compatibility:exclude-filter" value="CtsStatsdHostTestCases" />
 
+    <!-- No AppOps -->
+    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsdatom.appops.AppOpsTests" />
+
     <!-- b/183654427 Remove CtsTelecomTestCases from cts-on-gsi -->
     <option name="compatibility:exclude-filter" value="CtsTelecomTestCases" />
 
diff --git a/tools/cts-tradefed/res/config/cts-validation.xml b/tools/cts-tradefed/res/config/cts-validation.xml
index dc33eca..662d7ea 100644
--- a/tools/cts-tradefed/res/config/cts-validation.xml
+++ b/tools/cts-tradefed/res/config/cts-validation.xml
@@ -15,6 +15,8 @@
 -->
 <configuration description="Runs a subset of CTS tests using a general kernel image (GKI)">
     <option name="plan" value="cts-validation" />
+    <option name="result-attribute" key="GKI" value="1" />
+    <option name="result-attribute" key="camera_apex" value="1" />
     <include name="cts-on-gsi" />
     <include name="cts-validation-exclude" />
 </configuration>