Merge "mediav2 CTS: Update color format(s) support as per CDD"
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 a9d7348..ecfae1d 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/CtsShimPrivUpgradeWrongSHA.apk"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 62ab040..5e6ea43 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/CtsShimPrivUpgrade.apk"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__riscv64_CtsShimPrivUpgradeWrongSHA_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__riscv64_CtsShimPrivUpgradeWrongSHA_apk.asciipb
new file mode 100644
index 0000000..c673a8e
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__riscv64_CtsShimPrivUpgradeWrongSHA_apk.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/CtsShimPrivUpgradeWrongSHA.apk"
+  }
+  dest_file: "hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk//riscv64/CtsShimPrivUpgradeWrongSHA.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__riscv64_CtsShimPrivUpgrade_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__riscv64_CtsShimPrivUpgrade_apk.asciipb
new file mode 100644
index 0000000..6e33933
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__riscv64_CtsShimPrivUpgrade_apk.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/CtsShimPrivUpgrade.apk"
+  }
+  dest_file: "hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk//riscv64/CtsShimPrivUpgrade.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  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 a20b738..ffb065a 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/CtsShimPrivUpgradeWrongSHA.apk"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 3371432..fb4f3c0 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/CtsShimPrivUpgrade.apk"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 7806ac3..3f4930d 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim_not_pre_installed.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 280dc99..4b29501 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v1.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 2b13a41..8ce5112 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_file.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 c852f2c..f8bf31f 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_folder.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 566d73d..cd498e3 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 7f394da..a0887fc 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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_upgrades_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
index c3b3d1c..d1ee7273 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 8ad7148..758c77e 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_certificate.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 c5bf540..75a2430 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_package_name.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb
new file mode 100644
index 0000000..b4a6c21
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_arm64/com.android.apex.cts.shim.v2_install_constraints_empty.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//arm/com.android.apex.cts.shim.v2_install_constraints_empty.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb
new file mode 100644
index 0000000..d8d5767
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_arm64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//arm/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb
new file mode 100644
index 0000000..375df80
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_arm64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//arm/com.android.apex.cts.shim.v2_install_constraints_no_value.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  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 b43824e4..feabb30 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_no_hashtree.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 86dd2d0..f2382a5 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_rebootless.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 63e244b..6102710 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 d301677..173bbe2 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 0a0fa3a..38ccaca 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 cde81d7..f434b84 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 4b7066b..80ee3be 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
index 72382d7..eaddd4e 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "6508977"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex"
   }
@@ -8,5 +8,8 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "rvc-dev"
+  git_branch: "master"
+  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 64f31fb..21ce24e 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 6430590..b6eed44 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 b103b78..e605a5e 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 b3f859b..9554303 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 eced4cc..c020196 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_wrong_sha.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 f0a1f9a..d2d9a78 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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
index d730662..6cdc73c 100644
--- 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
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_rebootless.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 f617b9a..a1e8127 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 21a4921..9c66ba4 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
new file mode 100644
index 0000000..976b465
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim_not_pre_installed.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim_not_pre_installed.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v1_apex.asciipb
new file mode 100644
index 0000000..91997c8
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v1_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v1.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v1.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
new file mode 100644
index 0000000..fec7f1f
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_additional_file.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_additional_file.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
new file mode 100644
index 0000000..b95d08d
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_additional_folder.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_additional_folder.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apex.asciipb
new file mode 100644
index 0000000..05f89d0
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
new file mode 100644
index 0000000..a740018
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
new file mode 100644
index 0000000..c85af99
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
new file mode 100644
index 0000000..428414e
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_different_certificate.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_different_certificate.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
new file mode 100644
index 0000000..99bf48a
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_different_package_name.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_different_package_name.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb
new file mode 100644
index 0000000..2ba3297
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_install_constraints_empty.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_install_constraints_empty.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb
new file mode 100644
index 0000000..ac86962
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb
new file mode 100644
index 0000000..ab4fd5f
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
new file mode 100644
index 0000000..f7d552f
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_no_hashtree.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_no_hashtree.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
new file mode 100644
index 0000000..aba6009
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_rebootless.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_rebootless.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
new file mode 100644
index 0000000..4e6c8cf
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
new file mode 100644
index 0000000..ebf91e9
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
new file mode 100644
index 0000000..5604f0e
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_signed_bob.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_signed_bob.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
new file mode 100644
index 0000000..989cb20
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
new file mode 100644
index 0000000..1d8ba1a
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
new file mode 100644
index 0000000..cc8fae7
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
new file mode 100644
index 0000000..1ad007c
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
new file mode 100644
index 0000000..3cc8c69
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
new file mode 100644
index 0000000..691591e
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
new file mode 100644
index 0000000..f44f7c7
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
new file mode 100644
index 0000000..b367f5c
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v2_wrong_sha.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v2_wrong_sha.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_apex.asciipb
new file mode 100644
index 0000000..ed61c23
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v3.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v3.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
new file mode 100644
index 0000000..4f4803a
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v3_rebootless.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v3_rebootless.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
new file mode 100644
index 0000000..e399165
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v3_signed_bob.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v3_signed_bob.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
new file mode 100644
index 0000000..ad1602a
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__riscv64_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//riscv64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  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 9fee80e..f9e83cc 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim_not_pre_installed.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 e00e0c0..9cf087d 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v1.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 70ea7a4..a80aef4 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_file.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 fe22126..48c88bd 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_folder.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 4f7f762..af30e4c 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 76f970a..98f4832 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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_upgrades_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
index 405905e..a5b69b9 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 ba4d65d..82fcf64 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_certificate.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 a0cc1809..6ef9746 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_package_name.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb
new file mode 100644
index 0000000..00006a4
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_empty_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_install_constraints_empty.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//x86/com.android.apex.cts.shim.v2_install_constraints_empty.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb
new file mode 100644
index 0000000..c5a5824
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_invalid_fingerprint_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//x86/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  transform: TRANSFORM_NONE
+  transform_options {
+  }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb
new file mode 100644
index 0000000..910083f
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_install_constraints_no_value_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apex//x86/com.android.apex.cts.shim.v2_install_constraints_no_value.apex"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  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 a491c76..c2c5b1c 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_no_hashtree.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 bc87363..265843a 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_rebootless.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 1399178..ffde898 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 70a1d02..f52731c 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 10f11a4..a6773c7 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 ec33561..406f5a5 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 57bd84b..c467cf4 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
index 4aa6913..58dff41 100644
--- a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_apk_container_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "6508977"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex"
   }
@@ -8,5 +8,8 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "rvc-dev"
+  git_branch: "master"
+  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 d2dd61b..c156060 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 3ec6a81..82cea69 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 43416aa..94aefd7 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 f6e5294..1e7eae7 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 4e9edcd..1d14b52 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_wrong_sha.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 5391c48..0ebddf7a 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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
index bc44538..58af33a 100644
--- 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
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_rebootless.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 4257f29..9879717 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 022a4bb..beee119 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   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 3f1c95d..0e7a997 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_arm64/CtsShimTargetPSdk.apk"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__riscv64_CtsShimTargetPSdk_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__riscv64_CtsShimTargetPSdk_apk.asciipb
new file mode 100644
index 0000000..8947dee
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__riscv64_CtsShimTargetPSdk_apk.asciipb
@@ -0,0 +1,15 @@
+drops {
+  android_build_drop {
+    build_id: "9653376"
+    target: "CtsShim"
+    source_file: "aosp_riscv64/CtsShimTargetPSdk.apk"
+  }
+  dest_file: "hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk//riscv64/CtsShimTargetPSdk.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/cts"
+  git_branch: "master"
+  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 d4a6c09..4b47d85 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: "8572644"
+    build_id: "9653376"
     target: "CtsShim"
     source_file: "aosp_x86_64/CtsShimTargetPSdk.apk"
   }
@@ -8,7 +8,7 @@
   version: ""
   version_group: ""
   git_project: "platform/cts"
-  git_branch: "tm-dev"
+  git_branch: "master"
   transform: TRANSFORM_NONE
   transform_options {
   }
diff --git a/OWNERS b/OWNERS
index f923618..adb9461 100644
--- a/OWNERS
+++ b/OWNERS
@@ -12,6 +12,6 @@
 
 # Android EngProd Approvers
 wenshan@google.com
-normancheung@google.com
-guangzhu@google.com
-jdesprez@google.com
\ No newline at end of file
+guangzhu@google.com #{LAST_RESORT_SUGGESTION}
+jdesprez@google.com #{LAST_RESORT_SUGGESTION}
+normancheung@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/apps/CameraITS/tests/its_base_test.py b/apps/CameraITS/tests/its_base_test.py
index 60e0b38..c0b8665 100644
--- a/apps/CameraITS/tests/its_base_test.py
+++ b/apps/CameraITS/tests/its_base_test.py
@@ -103,6 +103,13 @@
       try:
         self.tablet = devices[1]
         self.tablet_screen_brightness = self.user_params['brightness']
+        tablet_name_unencoded = self.tablet.adb.shell(
+            ['getprop', 'ro.build.product']
+        )
+        tablet_name = str(tablet_name_unencoded.decode('utf-8')).strip()
+        logging.debug('tablet name: %s', tablet_name)
+        its_session_utils.validate_tablet_brightness(
+            tablet_name, self.tablet_screen_brightness)
       except KeyError:
         logging.debug('Not all tablet arguments set.')
     else:  # sensor_fusion or manual run
@@ -251,9 +258,11 @@
     # edit root_output_path and summary_writer path
     # to add test name to output directory
     logging.debug('summary_writer._path: %s', self.summary_writer._path)
-    logging.debug('root_output_path: %s', self.root_output_path)
     summary_head, summary_tail = os.path.split(self.summary_writer._path)
     self.summary_writer._path = os.path.join(
         f'{summary_head}_{self.__class__.__name__}', summary_tail)
     os.rename(self.root_output_path,
               f'{self.root_output_path}_{self.__class__.__name__}')
+    # print root_output_path so that it can be written to report log.
+    # Note: Do not replace print with logging.debug here.
+    print('root_output_path:', f'{self.root_output_path}_{self.__class__.__name__}')
\ No newline at end of file
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index fbc882e..2b211ba 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -38,7 +38,7 @@
 MIN_FOCUS_DIST_TOL = 0.80  # allow charts a little closer than min
 NAME = os.path.splitext(os.path.basename(__file__))[0]
 NUM_STEPS = 10
-OFFSET_LOW_VAL = 10  # number of pixels
+OFFSET_ATOL = 10  # number of pixels
 OFFSET_RTOL = 0.15
 OFFSET_RTOL_LOW_OFFSET = 0.20
 OFFSET_RTOL_MIN_FD = 0.30
@@ -207,6 +207,7 @@
 
   def test_zoom(self):
     test_data = {}
+    test_failed = False
     with its_session_utils.ItsSession(
         device_id=self.dut.serial,
         camera_id=self.camera_id,
@@ -310,10 +311,10 @@
 
     for i, data in test_data.items():
       logging.debug('Zoom: %.2f, fl: %.2f', data['z'], data['fl'])
-      offset_abs = [(data['circle'][0] - size[0] // 2),
-                    (data['circle'][1] - size[1] // 2)]
+      offset_xy = [(data['circle'][0] - size[0] // 2),
+                   (data['circle'][1] - size[1] // 2)]
       logging.debug('Circle r: %.1f, center offset x, y: %d, %d',
-                    data['circle'][2], offset_abs[0], offset_abs[1])
+                    data['circle'][2], offset_xy[0], offset_xy[1])
       z_ratio = data['z'] / z_0
 
       # check relative size against zoom[0]
@@ -326,20 +327,24 @@
       # check relative offset against init vals w/ no focal length change
       if i == 0 or test_data[i-1]['fl'] != data['fl']:  # set init values
         z_init = float(data['z'])
-        offset_init = [(data['circle'][0] - size[0] // 2),
-                       (data['circle'][1] - size[1] // 2)]
+        offset_hypot_init = math.hypot(offset_xy[0], offset_xy[1])
+        logging.debug('offset_hypot_init: %.3f', offset_hypot_init)
       else:  # check
         z_ratio = data['z'] / z_init
-        offset_rel = (distance(offset_abs[0], offset_abs[1]) / z_ratio /
-                      distance(offset_init[0], offset_init[1]))
-        logging.debug('offset_rel: %.3f', offset_rel)
+        offset_hypot_rel = math.hypot(offset_xy[0], offset_xy[1]) / z_ratio
+        logging.debug('offset_hypot_rel: %.3f', offset_hypot_rel)
         rel_tol = data['o_tol']
-        if (np.linalg.norm(offset_init) < OFFSET_LOW_VAL and
-            rel_tol == OFFSET_RTOL):
-          rel_tol = OFFSET_RTOL_LOW_OFFSET
-        if not math.isclose(offset_rel, 1.0, rel_tol=rel_tol):
-          raise AssertionError(f"zoom: {data['z']:.2f}, offset(rel to 1): "
-                               f'{offset_rel:.4f}, RTOL: {rel_tol}')
+        if not math.isclose(offset_hypot_init, offset_hypot_rel,
+                            rel_tol=rel_tol, abs_tol=OFFSET_ATOL):
+          test_failed = True
+          e_msg = (f"zoom: {data['z']:.2f}, "
+                   f'offset init: {offset_hypot_init:.4f}, '
+                   f'offset rel: {offset_hypot_rel:.4f}, '
+                   f'RTOL: {rel_tol}, ATOL: {OFFSET_ATOL}')
+          logging.error(e_msg)
+
+    if test_failed:
+      raise AssertionError(f'{NAME} failed! Check test_log.DEBUG for errors')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index a75ce5e..ed3d50d 100755
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -475,6 +475,13 @@
   config_file_test_key = config_file_contents['TestBeds'][0]['Name'].lower()
   if TEST_KEY_TABLET in config_file_test_key:
     tablet_id = get_device_serial_number('tablet', config_file_contents)
+    tablet_name_cmd = f'adb -s {tablet_id} shell getprop ro.build.product'
+    raw_output = subprocess.check_output(
+        tablet_name_cmd, stderr=subprocess.STDOUT, shell=True)
+    tablet_name = str(raw_output.decode('utf-8')).strip()
+    logging.debug('Tablet name: %s', tablet_name)
+    brightness = test_params_content['brightness']
+    its_session_utils.validate_tablet_brightness(tablet_name, brightness)
   else:
     tablet_id = None
 
diff --git a/apps/CameraITS/tools/run_sensor_fusion.py b/apps/CameraITS/tools/run_sensor_fusion.py
index c000562..daf822f 100644
--- a/apps/CameraITS/tools/run_sensor_fusion.py
+++ b/apps/CameraITS/tools/run_sensor_fusion.py
@@ -168,17 +168,26 @@
         else:
           return_string = 'FAIL'
 
+      with open(run_all_tests.MOBLY_TEST_SUMMARY_TXT_FILE, 'r') as file:
+        content = file.read()
+        lines = content.splitlines()
+        for one_line in lines:
+          if 'root_output_path:' in one_line:
+            root_output_path = one_line.split(':')[1].strip()
+        file.close()
+
         os.remove(run_all_tests.MOBLY_TEST_SUMMARY_TXT_FILE)
-        file_name = os.path.join(
-            mobly_scene_output_logs_path, _TEST_BED_SENSOR_FUSION, 'latest',
-            'test_log.DEBUG')
+        file_name = os.path.join(root_output_path, 'test_log.DEBUG')
         time_shift = find_time_shift(file_name)
-        logging.info('%s time_shift: %.4f ms, corr: %.6f', return_string,
-                     time_shift['time_shift'], time_shift['corr'])
-        if time_shift['corr'] < _CORR_DIST_THRESH_MAX:
-          time_shifts.append(time_shift)
+        if time_shift is not None:
+          logging.info('%s time_shift: %.4f ms, corr: %.6f', return_string,
+                       time_shift['time_shift'], time_shift['corr'])
+          if time_shift['corr'] < _CORR_DIST_THRESH_MAX:
+            time_shifts.append(time_shift)
+          else:
+            logging.info('Correlation distance too large. Not used for stats.')
         else:
-          logging.info('Correlation distance too large. Not used for stats.')
+          logging.info('time_shift not found')
 
     # Summarize results with stats
     times = [t['time_shift'] for t in time_shifts]
diff --git a/apps/CameraITS/utils/capture_request_utils.py b/apps/CameraITS/utils/capture_request_utils.py
index 2887925..521ec84 100644
--- a/apps/CameraITS/utils/capture_request_utils.py
+++ b/apps/CameraITS/utils/capture_request_utils.py
@@ -173,7 +173,7 @@
   out_sizes = [(cfg['width'], cfg['height']) for cfg in out_configs]
   if max_size:
     out_sizes = [
-        s for s in out_sizes if s[0] <= max_size[0] and s[1] <= max_size[1]
+        s for s in out_sizes if s[0] <= int(max_size[0]) and s[1] <= int(max_size[1])
     ]
   if match_ar_size:
     ar = match_ar_size[0] / float(match_ar_size[1])
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index b1fb77a..3caad99 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -38,6 +38,15 @@
 ANDROID13_API_LEVEL = 33
 LOAD_SCENE_DELAY_SEC = 3
 SUB_CAMERA_SEPARATOR = '.'
+DEFAULT_TABLET_BRIGHTNESS = 192  # 8-bit tablet 75% brightness
+ELEVEN_BIT_TABLET_BRIGHTNESS = 1536
+ELEVEN_BIT_TABLET_NAMES = ('nabu',)
+LEGACY_TABLET_BRIGHTNESS = 96
+LEGACY_TABLET_NAME = 'dragon'
+TABLET_REQUIREMENTS_URL = 'https://source.android.com/docs/compatibility/cts/camera-its-box#tablet-requirements'
+BRIGHTNESS_ERROR_MSG = ('Tablet brightness not set as per '
+                        f'{TABLET_REQUIREMENTS_URL} in the config file')
+
 _VALIDATE_LIGHTING_PATCH_H = 0.05
 _VALIDATE_LIGHTING_PATCH_W = 0.05
 _VALIDATE_LIGHTING_REGIONS = {
@@ -50,6 +59,27 @@
 _VALIDATE_LIGHTING_THRESH = 0.05  # Determined empirically from scene[1:6] tests
 
 
+def validate_tablet_brightness(tablet_name, brightness):
+  """Ensures tablet brightness is set according to documentation.
+
+  https://source.android.com/docs/compatibility/cts/camera-its-box#tablet-requirements
+  Args:
+    tablet_name: tablet product name specified by `ro.build.product`.
+    brightness: brightness specified by config file.
+  """
+  name_to_brightness = {
+      LEGACY_TABLET_NAME: LEGACY_TABLET_BRIGHTNESS,
+  }
+  for name in ELEVEN_BIT_TABLET_NAMES:
+    name_to_brightness[name] = ELEVEN_BIT_TABLET_BRIGHTNESS
+  if tablet_name in name_to_brightness:
+    if brightness != name_to_brightness[tablet_name]:
+      raise AssertionError(BRIGHTNESS_ERROR_MSG)
+  else:
+    if brightness != DEFAULT_TABLET_BRIGHTNESS:
+      raise AssertionError(BRIGHTNESS_ERROR_MSG)
+
+
 class ItsSession(object):
   """Controls a device over adb to run ITS scripts.
 
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 8b4cfa5..e357e8f 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -271,6 +271,8 @@
                        android:value="multi_display_mode" />
             <meta-data android:name="ApiTest"
                        android:value="android.companion.CompanionDeviceManager#associate" />
+            <meta-data android:name="test_excluded_features"
+                android:value="android.hardware.type.watch" />
         </activity>
 
         <activity android:name=".companion.CompanionDeviceServiceTestActivity"
@@ -288,6 +290,8 @@
                        android:value="multi_display_mode" />
             <meta-data android:name="ApiTest"
                        android:value="android.companion.CompanionDeviceManager#startObservingDevicePresence|android.companion.CompanionDeviceManager#stopObservingDevicePresence" />
+            <meta-data android:name="test_excluded_features"
+                android:value="android.hardware.type.watch" />
         </activity>
 
         <service
diff --git a/apps/CtsVerifier/OWNERS b/apps/CtsVerifier/OWNERS
index 00c4a06..e555f55 100644
--- a/apps/CtsVerifier/OWNERS
+++ b/apps/CtsVerifier/OWNERS
@@ -1 +1,2 @@
-per-file AndroidManifest*.xml = rossyeh@google.com,robinjacob@google.com,mariay@google.com,normancheung@google.com,slotus@google.com,kgui@google.com
+per-file AndroidManifest*.xml = rossyeh@google.com,robinjacob@google.com,mariay@google.com,slotus@google.com,kgui@google.com
+per-file AndroidManifest*.xml = normancheung@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/test_category_row.xml b/apps/CtsVerifier/res/layout/test_category_row.xml
index ad47c0a..5f953846 100644
--- a/apps/CtsVerifier/res/layout/test_category_row.xml
+++ b/apps/CtsVerifier/res/layout/test_category_row.xml
@@ -16,5 +16,5 @@
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     style="?android:attr/listSeparatorTextViewStyle"
-    android:id="@+android:id/text1"
-    />
\ No newline at end of file
+    android:id="@android:id/text1"
+    />
diff --git a/apps/CtsVerifier/res/values-watch/strings.xml b/apps/CtsVerifier/res/values-watch/strings.xml
index e594b9e..4f412bf 100644
--- a/apps/CtsVerifier/res/values-watch/strings.xml
+++ b/apps/CtsVerifier/res/values-watch/strings.xml
@@ -61,4 +61,7 @@
         7) Repeat steps (1) through (6) for each screen lock type other than \"None\".
     </string>
     <string name="usb_tapjacking_usb_debugging_component">com.google.android.apps.wearable.settings/com.google.android.clockwork.settings.SecureAdbActivityAlias</string>
+
+    <!-- Adjusted for watches to leave out second part, since not applicable to watches. -->
+    <string name="add_screen_lock">Add a secure screen lock of any type.</string>
 </resources>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0a93025..5754c45 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -5777,6 +5777,7 @@
     <string name="audio_tap2tone_too_few">Not enough edges. Use fingernail.</string>
     <string name="audio_tap2tone_too_many">Too many edges. Use fingernail. Ensure there is
     no background noise.</string>
+    <string name="audio_tap2tone_bad_streams">Can\'t open streams.</string>
 
     <!-- Strings for 6DoF test -->
     <string name="six_dof_test">6DoF Test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 307eb6f..40bcae8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -154,7 +154,9 @@
         mHeadsetVolUpText = (TextView)findViewById(R.id.headset_keycode_volume_up);
         mHeadsetVolDownText = (TextView)findViewById(R.id.headset_keycode_volume_down);
 
-        if (isTelevision()) {
+        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+
+        if (isTelevisionOrFixedVolume()) {
             mButtonsPromptTxt.setVisibility(View.GONE);
             mHeadsetHookText.setVisibility(View.GONE);
             mHeadsetVolUpText.setVisibility(View.GONE);
@@ -164,8 +166,6 @@
 
         mResultsTxt = (TextView)findViewById(R.id.headset_results);
 
-        mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
-
         setupPlayer();
 
         mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
@@ -177,7 +177,7 @@
 
         showKeyMessagesState();
 
-        setInfoResources(R.string.analog_headset_test, isTelevision()
+        setInfoResources(R.string.analog_headset_test, isTelevisionOrFixedVolume()
                 ? R.string.analog_headset_test_info_tv : R.string.analog_headset_test_info, -1);
 
         setPassFailButtonClickListeners();
@@ -196,7 +196,7 @@
                     mPlugIntentReceived &&
                     mHeadsetDeviceInfo != null &&
                     mPlaybackSuccess &&
-                    (isTelevision()
+                    (isTelevisionOrFixedVolume()
                     || ((mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown));
             if (pass) {
                 mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
@@ -500,7 +500,8 @@
         return super.onKeyDown(keyCode, event);
     }
 
-    private boolean isTelevision() {
-        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    private boolean isTelevisionOrFixedVolume() {
+        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+                || mAudioManager.isVolumeFixed();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
index 3f1266e..5c3ee1c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
@@ -259,11 +259,15 @@
                 setLevelForStream(playbackStreamType, desiredLevel);
 
                 int currentLevel = getLevelForStream(playbackStreamType);
-                if (currentLevel != desiredLevel) {
+                if (am.isVolumeFixed()) {
+                    sendMessage(AudioTestRunner.TEST_MESSAGE,
+                        "configured for Fixed volume, bypassing volume level check");
+
+                } else if (currentLevel != desiredLevel) {
                     am.setMode(originalMode);
                     sendMessage(AudioTestRunner.TEST_ENDED_ERROR,
-                            "Couldn't set level for STREAM_VOICE_CALL. Expected " +
-                                    desiredLevel +" got: " + currentLevel);
+                        "Couldn't set level for STREAM_VOICE_CALL. Expected " +
+                        desiredLevel +" got: " + currentLevel);
                     return;
                 }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index cf09a74..c61689c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -44,6 +44,7 @@
 import com.android.cts.verifier.audio.sources.BlipAudioSourceProvider;
 
 import org.hyphonate.megaaudio.common.BuilderBase;
+import org.hyphonate.megaaudio.common.StreamBase;
 import org.hyphonate.megaaudio.duplex.DuplexAudioManager;
 import org.hyphonate.megaaudio.player.AudioSource;
 import org.hyphonate.megaaudio.player.AudioSourceProvider;
@@ -270,12 +271,18 @@
             mDuplexAudioManager.setNumRecorderChannels(NUM_RECORD_CHANNELS);
         }
 
-        mDuplexAudioManager.setupStreams(mPlayerType, BuilderBase.TYPE_JAVA);
-        mDuplexAudioManager.start();
+        if (mDuplexAudioManager.setupStreams(BuilderBase.TYPE_OBOE, BuilderBase.TYPE_JAVA)
+                == StreamBase.OK) {
+            mDuplexAudioManager.start();
 
-        mBlipSource = (AudioSource) mDuplexAudioManager.getAudioSource();
+            mBlipSource = (AudioSource) mDuplexAudioManager.getAudioSource();
 
-        mIsRecording = true;
+            mIsRecording = true;
+            mResultsView.setText("Successfully opened streams");
+        } else {
+            mIsRecording = false;
+            mResultsView.setText(getString(R.string.audio_tap2tone_bad_streams));
+        }
         enableAudioButtons();
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
old mode 100755
new mode 100644
index 793cbf7..c8cd8fd
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -653,7 +653,7 @@
                     rotation = (360 - rotation) % 360;  // de-compensate the mirror
                 }
 
-                if (rotation != 0) {
+                if (rotation != 0 && rotation != 180) {
                     Matrix transform = new Matrix();
                     mFormatView.setScaleType(ImageView.ScaleType.MATRIX);
                     Rect viewRect = mFormatView.getDrawable().getBounds();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
index eddd930..a7b58fa 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
@@ -96,7 +96,7 @@
     /**
      * Checks whether the device is watch .
      */
-    private static boolean isWatch(Context context) {
+    public static boolean isWatch(Context context) {
         PackageManager pm = context.getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java
index 760bd71..6c63037 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java
@@ -29,7 +29,6 @@
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.util.Log;
@@ -39,6 +38,7 @@
 import androidx.annotation.StringRes;
 
 import com.android.cts.verifier.R;
+import com.android.cts.verifier.features.FeatureUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -105,12 +105,14 @@
 
     @Override
     protected List<InteractiveTestCase> createTestItems() {
-        boolean isAutomotive = getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE);
         List<InteractiveTestCase> tests = new ArrayList<>();
-        if (!isAutomotive) {
-            // FIRST: set redaction settings
-            tests.add(new SetScreenLockEnabledStep());
+
+        // FIRST: enable lock screen
+        tests.add(new SetScreenLockEnabledStep());
+
+        // for watches, no notifications should appear on the secure lock screen
+        if (!FeatureUtil.isWatch(this)) {
+            // THEN: set redaction settings
             tests.add(new SetGlobalVisibilityPublicStep());
             tests.add(new SetChannelLockscreenVisibilityPrivateStep());
             // NOW TESTING: redacted by channel
@@ -132,13 +134,16 @@
             tests.add(new NotificationWhenOccludedShowsRedactedTest());
 
             tests.add(new SetGlobalVisibilitySecretStep());
-            // NOW TESTING: notifications do not appear
-            tests.add(new NotificationWhenLockedIsHiddenTest());
-            tests.add(new NotificationWhenOccludedIsHiddenTest());
-
-            // FINALLY: restore device state
-            tests.add(new SetScreenLockDisabledStep());
         }
+
+        // NOW TESTING: notifications do not appear
+        tests.add(new NotificationWhenLockedIsHiddenTest());
+        if (!FeatureUtil.isWatch(this)) {
+            tests.add(new NotificationWhenOccludedIsHiddenTest());
+        }
+
+        // FINALLY: restore device state
+        tests.add(new SetScreenLockDisabledStep());
         return tests;
     }
 
diff --git a/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/permissions/CommonPermissions.java b/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/permissions/CommonPermissions.java
index d2af212..59e8433 100644
--- a/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/permissions/CommonPermissions.java
+++ b/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/permissions/CommonPermissions.java
@@ -832,6 +832,14 @@
     public static final String BIND_JOB_SERVICE = "android.permission.BIND_JOB_SERVICE";
     /** See {@code Manifest#UPDATE_CONFIG} */
     public static final String UPDATE_CONFIG = "android.permission.UPDATE_CONFIG";
+    /** See {@code Manifest#QUERY_TIME_ZONE_RULES} */
+    public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
+    /** See {@code Manifest#UPDATE_TIME_ZONE_RULES} */
+    public static final String UPDATE_TIME_ZONE_RULES = "android.permission"
+            + ".UPDATE_TIME_ZONE_RULES";
+    /** See {@code Manifest#TRIGGER_TIME_ZONE_RULES_CHECK} */
+    public static final String TRIGGER_TIME_ZONE_RULES_CHECK = "android.permission"
+            + ".TRIGGER_TIME_ZONE_RULES_CHECK";
     /** See {@code Manifest#RESET_SHORTCUT_MANAGER_THROTTLING} */
     public static final String RESET_SHORTCUT_MANAGER_THROTTLING =
             "android.permission.RESET_SHORTCUT_MANAGER_THROTTLING";
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
index 56a053b..2e17a8c 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
@@ -1,3 +1,7 @@
+per-file AmMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
 per-file AnrMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
 per-file BaseDefaultPermissionGrantPolicyTest.java = file:platform/frameworks/base:/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
 per-file ReadElf.java = enh@google.com
+per-file *Settings*.java = felipeal@google.com
+per-file User*Helper*.java = felipeal@google.com
+per-file *StateManager*.java = felipeal@google.com
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index ff1e122..de8c4e2 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -32,6 +32,7 @@
         "compatibility-host-util",
         "truth-prebuilt",
         "hamcrest-library",
+        "sts-host-util",
     ],
 
     static_libs: [
diff --git a/hostsidetests/appsecurity/OWNERS b/hostsidetests/appsecurity/OWNERS
index 5208e7b..b0f0145 100644
--- a/hostsidetests/appsecurity/OWNERS
+++ b/hostsidetests/appsecurity/OWNERS
@@ -1,36 +1,62 @@
-# Bug component: 533114
-toddke@google.com
+# Bug component: 36137
+# Bug component: 36137 = per-file ApplicationVisibilityTest.java
+# Bug component: 36137 = per-file BaseInstallMultiple.java
+# Bug component: 568761 = per-file CorruptApkTests.java
+# Bug component: 36137 = per-file EphemeralTest.java
+# Bug component: 36137 = per-file InstantAppUserTest.java
+# Bug component: 36137 = per-file InstantCookieHostTest.java
+# Bug component: 36137 = per-file IsolatedSplitsTests.java
+# Bug component: 36137 = per-file MajorVersionTest.java
+# Bug component: 568631 = per-file OverlayHostTest.java
+# Bug component: 36137 = per-file Package*
+# Bug component: 36137 = per-file Pkg*
+# Bug component: 36137 = per-file PrivilegedUpdateTests.java
+# Bug component: 36137 = per-file SharedUserIdTest.java
+# Bug component: 36137 = per-file SplitTests.java
+
+# Storage bug component
+# Bug component: 46626 = per-file *Adoptable*
+# Bug component: 46626 = per-file *DirectBoot*
+# Bug component: 46626 = per-file *Storage*
+# Bug component: 46626 = per-file *Documents*
+# Bug component: 46626 = per-file ScopedDirectoryAccessTest.java
+
+# DocsUI bug component
+# Bug component: 46626 = per-file *Documents*
+# Bug component: 46626 = per-file ScopedDirectoryAccessTest.java
+
 patb@google.com
 per-file AccessSerialNumberTest.java = ashfall@google.com
 per-file ApexSignatureVerificationTest.java = dariofreni@google.com
-per-file ApplicationVisibilityTest.java = toddke@google.com,patb@google.com
 per-file AppDataIsolationTests.java = rickywai@google.com,alanstokes@google.com
 per-file AppOpsTest.java = ashfall@google.com
 per-file AppSecurityTests.java = cbrubaker@google.com
 per-file AuthBoundKeyTest.java = file:test-apps/AuthBoundKeyApp/OWNERS
-per-file BaseInstallMultiple.java = toddke@google.com,patb@google.com
-per-file CorruptApkTests.java = zyy@google.com
 per-file DeviceIdentifierTest.java = cbrubaker@google.com
-per-file EphemeralTest.java = toddke@google.com,patb@google.com
 per-file ExternalStorageHostTest.java = nandana@google.com
 per-file ExternalStorageHostTest.java = zezeozue@google.com
-per-file InstantAppUserTest.java = toddke@google.com,patb@google.com
-per-file InstantCookieHostTest.java = toddke@google.com,patb@google.com
-per-file IsolatedSplitsTests.java = patb@google.com,toddke@google.com
 per-file KeySetHostTest.java = cbrubaker@google.com
-per-file ListeningPortsTest.java = cbrubaker@google.com
-per-file MajorVersionTest.java = toddke@google.com,patb@google.com
-per-file OverlayHostTest.java = zyy@google.com
-per-file Package* = chiuwinson@google.com,patb@google.com,toddke@google.com
+per-file ListeningPortsTest.java = cbrubaker@google.com,mpgroover@google.com
 per-file PermissionsHostTest.java = ashfall@google.com
-per-file Pkg* = chiuwinson@google.com,patb@google.com,toddke@google.com
-per-file PkgInstallSignatureVerificationTest.java = cbrubaker@google.com
-per-file PrivilegedUpdateTests.java = toddke@google.com,patb@google.com
-per-file ReviewPermissionHelper = moltmann@google.com
+per-file PkgInstallSignatureVerificationTest.java = cbrubaker@google.com,mpgroover@google.com
 per-file RequestsOnlyCalendarApp22.java = ashfall@google.com
-per-file SharedUserIdTest.java = toddke@google.com,patb@google.com
-per-file SplitTests.java = patb@google.com,toddke@google.com,patb@google.com
 per-file UseEmbeddedDexTest.java = victorhsieh@google.com
+# Package Manager
+per-file ApplicationVisibilityTest.java = chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file BaseInstallMultiple.java =  chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file EphemeralTest.java =  chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file InstantAppUserTest.java =  chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file InstantCookieHostTest.java =  chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file IsolatedSplitsTests.java = chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file MajorVersionTest.java =  chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file PermissionsHostTest.java = ashfall@google.com
+per-file Pkg* = chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file PrivilegedUpdateTests.java = chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file SharedUserIdTest.java = chiuwinson@google.com, patb@google.com, schfan@google.com
+per-file SplitTests.java = chiuwinson@google.com, patb@google.com, schfan@google.com
+# Resources
+per-file CorruptApkTests.java = patb@google.com, zyy@google.com
+per-file OverlayHostTest.java = patb@google.com, zyy@google.com
 # test apps
 per-file BasePermissionsTest.java = ashfall@google.com
 per-file RequestsOnlyCalendarApp22.java = ashfall@google.com
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
index eff95b9..b2da44e 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
@@ -99,6 +99,7 @@
     @Test
     public void resumeOnReboot_ManagedProfile_Success() throws Exception {
         assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+        assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
 
         if (!getDevice().hasFeature("android.software.managed_users")) {
             CLog.v(TAG, "Device doesn't support managed users; skipping test");
@@ -140,6 +141,7 @@
     @Test
     public void resumeOnReboot_TwoUsers_SingleUserUnlock_Success() throws Exception {
         assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+        assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
 
         if (!mSupportsMultiUser) {
             CLog.v(TAG, "Device doesn't support multi-user; skipping test");
@@ -192,6 +194,7 @@
     @Test
     public void resumeOnReboot_TwoUsers_BothUserUnlock_Success() throws Exception {
         assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+        assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
 
         if (!mSupportsMultiUser) {
             CLog.v(TAG, "Device doesn't support multi-user; skipping test");
@@ -246,6 +249,7 @@
     @Test
     public void resumeOnReboot_SingleUser_ServerBased_Success() throws Exception {
         assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+        assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
 
         int[] users = Utils.prepareSingleUser(getDevice());
         int initialUser = users[0];
@@ -279,6 +283,7 @@
     @Test
     public void resumeOnReboot_SingleUser_MultiClient_ClientASuccess() throws Exception {
         assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+        assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
 
         int[] users = Utils.prepareSingleUser(getDevice());
         int initialUser = users[0];
@@ -319,6 +324,7 @@
     @Test
     public void resumeOnReboot_SingleUser_MultiClient_ClientBSuccess() throws Exception {
         assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+        assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
 
         int[] users = Utils.prepareSingleUser(getDevice());
         int initialUser = users[0];
@@ -569,6 +575,10 @@
         return isAtleastS && getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN);
     }
 
+    private boolean supportFileBasedEncryption() throws Exception {
+        return "file".equals(getDevice().getProperty("ro.crypto.type"));
+    }
+
     private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
         public InstallMultiple() {
             super(getDevice(), getBuild(), getAbi());
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
index e86aa57..2e182eb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
@@ -21,7 +21,7 @@
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
 
 import static org.junit.Assert.assertNull;
 import static org.junit.Assume.assumeTrue;
@@ -30,7 +30,7 @@
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class RoleSecurityTest extends BaseHostJUnit4Test {
+public class RoleSecurityTest extends StsExtraBusinessLogicHostTestBase {
     private static final String ROLE_SECURITY_TEST_APP_APK = "CtsRoleSecurityTestApp.apk";
     private static final String ROLE_SECURITY_TEST_APP_PACKAGE = "com.android.cts.rolesecuritytest";
 
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
index 09a4d81..c368e2e 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
@@ -61,6 +61,7 @@
 
     @Override
     public void setUp() throws Exception {
+        if (!supportedHardware()) return;
         super.setUp();
 
         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
@@ -91,6 +92,7 @@
 
     @Override
     public void tearDown() throws Exception {
+        if (!supportedHardware()) return;
         super.tearDown();
         mActivity.finish();
 
diff --git a/hostsidetests/appsecurity/test-apps/ListeningPortsApp/OWNERS b/hostsidetests/appsecurity/test-apps/ListeningPortsApp/OWNERS
index 40cc594..81145888 100644
--- a/hostsidetests/appsecurity/test-apps/ListeningPortsApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/ListeningPortsApp/OWNERS
@@ -1,2 +1,3 @@
-# Bug component: 95221
+# Bug component: 315013
 cbrubaker@google.com
+mpgroover@google.com
diff --git a/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java b/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java
index bd99b09..072effb 100644
--- a/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java
+++ b/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java
@@ -16,6 +16,7 @@
 
 package android.appsecurity.cts.listeningports;
 
+import android.app.UiAutomation;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.Process;
@@ -143,8 +144,15 @@
     }
 
     private String uidToPackage(int uid) {
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         PackageManager pm = this.getContext().getPackageManager();
-        String[] packages = pm.getPackagesForUid(uid);
+        String[] packages;
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            packages = pm.getPackagesForUid(uid);
+        } finally {
+            uiAutomation.dropShellPermissionIdentity();
+        }
         if (packages == null) {
             return "[unknown]";
         }
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
index b3d1d1c..56d2e07 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
@@ -996,12 +996,7 @@
             // to keep rolling forward if we can't find our grant button
             final UiSelector grant = new UiSelector().textMatches("(?i)Allow");
             if (isWatch()) {
-                UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
-                try {
-                    uiScrollable.scrollIntoView(grant);
-                } catch (UiObjectNotFoundException e) {
-                    // Scrolling can fail if the UI is not scrollable
-                }
+                scrollIntoView(grant);
             }
             final boolean grantExists = new UiObject(grant).waitForExists(timeout);
 
@@ -1016,8 +1011,11 @@
             // Verify that we now have access
             assertEquals(Activity.RESULT_OK, res.resultCode);
         } else {
-            // fine the Deny button
+            // find the Deny button
             final UiSelector deny = new UiSelector().textMatches("(?i)Deny");
+            if (isWatch()) {
+                scrollIntoView(deny);
+            }
             final boolean denyExists = new UiObject(deny).waitForExists(timeout);
 
             assertThat(denyExists).isTrue();
@@ -1030,6 +1028,15 @@
         }
     }
 
+    private static void scrollIntoView(UiSelector selector) {
+        UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+        try {
+            uiScrollable.scrollIntoView(selector);
+        } catch (UiObjectNotFoundException e) {
+            // Scrolling can fail if the UI is not scrollable
+        }
+    }
+
     private static Uri createDownload() throws IOException {
         final String content = "<html><body>Content</body></html>";
         final String displayName = "cts" + System.nanoTime();
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
index f1730f6..971a2cf 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 cdb279a..2f673da 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/riscv64/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/riscv64/CtsShimPrivUpgrade.apk
new file mode 100644
index 0000000..991ac90
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/riscv64/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/riscv64/CtsShimPrivUpgradeWrongSHA.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/riscv64/CtsShimPrivUpgradeWrongSHA.apk
new file mode 100644
index 0000000..13e0372
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/riscv64/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 42135bc..7b23e99 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 f9e6f96..27fb33b 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/calllog/app/Android.bp b/hostsidetests/calllog/app/Android.bp
index c89655f..7a9967c 100644
--- a/hostsidetests/calllog/app/Android.bp
+++ b/hostsidetests/calllog/app/Android.bp
@@ -26,7 +26,7 @@
         "androidx.test.rules",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
         "truth-prebuilt",
     ],
     libs: ["android.test.base"],
diff --git a/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java b/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java
index d8ca24f..9ba8ad2 100644
--- a/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java
+++ b/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java
@@ -10,13 +10,13 @@
 import android.os.OutcomeReceiver;
 import android.os.ParcelFileDescriptor;
 import android.provider.CallLog;
-import android.support.test.uiautomator.UiDevice;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 import android.util.Pair;
 import android.view.KeyEvent;
 
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiDevice;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
diff --git a/hostsidetests/car/src/android/car/cts/CarWatchdogHostTest.java b/hostsidetests/car/src/android/car/cts/CarWatchdogHostTest.java
index c7381a2..452ffd6 100644
--- a/hostsidetests/car/src/android/car/cts/CarWatchdogHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/CarWatchdogHostTest.java
@@ -131,7 +131,7 @@
             "foregroundModeBytes = (\\d+)");
 
     private static final long START_CUSTOM_COLLECTION_TIMEOUT_MS = 30_000;
-    private static final long WATCHDOG_ACTION_TIMEOUT_MS = 15_000;
+    private static final long WATCHDOG_ACTION_TIMEOUT_MS = 30_000;
 
     private boolean mDidModifyDateTime;
     private long mOriginalForegroundBytes;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
index 33bb365..1cb086a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
@@ -205,7 +205,7 @@
         setPoAsUser(mDeviceOwnerUserId);
 
         // Create another user and set PO.
-        final int secondaryUserId = createUserAndWaitStart();
+        final int secondaryUserId = createUser();
         setPoAsUser(secondaryUserId);
 
         // Let user-0 PO sets all restrictions.
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index 518144a..46fd3dc 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -489,6 +489,7 @@
         assertInteger(parts[8]); // attention
         assertInteger(parts[9]); // faceDown
         assertInteger(parts[10]); // deviceState
+
     }
 
     private void checkUserActivityCompat(String[] parts) {
diff --git a/tests/tests/gwp-asan/enabled/Android.bp b/hostsidetests/gwp_asan/Android.bp
similarity index 68%
copy from tests/tests/gwp-asan/enabled/Android.bp
copy to hostsidetests/gwp_asan/Android.bp
index a78598e..2b938eb 100644
--- a/tests/tests/gwp-asan/enabled/Android.bp
+++ b/hostsidetests/gwp_asan/Android.bp
@@ -1,10 +1,10 @@
-// Copyright (C) 2020 The Android Open Source Project
+// Copyright (C) 2023 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
+// 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,
@@ -16,27 +16,38 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_test {
+java_test_host {
     name: "CtsGwpAsanTestCases",
     defaults: ["cts_defaults"],
-    compile_multilib: "both",
-    // When built, explicitly put it in the data partition.
-    // Tag this module as a cts test artifact
+    srcs: ["src/**/*.java"],
+    libs: [
+        "cts-tradefed",
+        "tradefed",
+    ],
     test_suites: [
         "cts",
         "general-tests",
     ],
-    libs: [
-        "android.test.runner",
-        "android.test.base",
+    data: [
+        ":CtsGwpAsanEnabled",
     ],
+}
+
+java_defaults {
+    name: "cts_gwp_asan_app_defaults",
+    defaults: ["cts_defaults"],
+    compile_multilib: "both",
     static_libs: [
         "ctstestrunner-axt",
         "androidx.test.rules",
         "androidx.test.core",
         "androidx.test.ext.junit",
+        "gwp_asan_cts_common",
     ],
-    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    jni_libs: ["libgwp_asan_cts_library_jni"],
     sdk_version: "current",
-    use_embedded_native_libs: false,
 }
diff --git a/tests/tests/gwp-asan/enabled/AndroidTest.xml b/hostsidetests/gwp_asan/AndroidTest.xml
similarity index 65%
rename from tests/tests/gwp-asan/enabled/AndroidTest.xml
rename to hostsidetests/gwp_asan/AndroidTest.xml
index 61580ca..fcebdc5 100644
--- a/tests/tests/gwp-asan/enabled/AndroidTest.xml
+++ b/hostsidetests/gwp_asan/AndroidTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
+<!-- Copyright (C) 2023 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,17 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Config for CTS GWP-ASan test cases">
+<configuration description="Config for CTS GWP-ASan host test cases">
     <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="art" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
-    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsGwpAsanTestCases.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.gwpasan.cts" />
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.SkipHWASanModuleController" />
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsGwpAsanTestCases.jar" />
     </test>
 </configuration>
diff --git a/tests/tests/gwp-asan/OWNERS b/hostsidetests/gwp_asan/OWNERS
similarity index 80%
rename from tests/tests/gwp-asan/OWNERS
rename to hostsidetests/gwp_asan/OWNERS
index 9686261..13edd31 100644
--- a/tests/tests/gwp-asan/OWNERS
+++ b/hostsidetests/gwp_asan/OWNERS
@@ -2,4 +2,4 @@
 eugenis@google.com
 pcc@google.com
 mitchp@google.com
-
+fmayer@google.com
diff --git a/tests/tests/gwp-asan/TEST_MAPPING b/hostsidetests/gwp_asan/TEST_MAPPING
similarity index 100%
rename from tests/tests/gwp-asan/TEST_MAPPING
rename to hostsidetests/gwp_asan/TEST_MAPPING
diff --git a/hostsidetests/gwp_asan/common/Android.bp b/hostsidetests/gwp_asan/common/Android.bp
new file mode 100644
index 0000000..30a086b
--- /dev/null
+++ b/hostsidetests/gwp_asan/common/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2023 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: "gwp_asan_cts_common",
+    srcs: ["android/**/*.java"],
+    sdk_version: "current",
+    static_libs: [
+        "ctstestrunner-axt",
+        "androidx.test.rules",
+        "androidx.test.core",
+        "androidx.test.ext.junit",
+    ],
+}
+
+cc_test_library {
+    name: "libgwp_asan_cts_library_jni",
+    srcs: ["jni/gwp_asan_cts_library.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    header_libs: ["jni_headers"],
+    shared_libs: ["liblog"],
+    sdk_version: "current",
+    stl: "libc++",
+    gtest: false,
+}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
new file mode 100644
index 0000000..802f829
--- /dev/null
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.cts.gwp_asan;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class GwpAsanActivityTest {
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    @Rule
+    public ActivityTestRule<TestActivityLauncher> mTestActivityRule =
+            new ActivityTestRule<>(
+                    TestActivityLauncher.class,
+                    false /*initialTouchMode*/,
+                    false /*launchActivity*/);
+
+    @Test
+    public void testEnablement() throws Exception {
+        TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+        activity.callActivity(GwpAsanEnabledActivity.class);
+        activity.callActivity(GwpAsanDefaultActivity.class);
+        activity.callActivity(GwpAsanDisabledActivity.class);
+    }
+}
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDefaultActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
similarity index 72%
rename from tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDefaultActivity.java
rename to hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
index 9643fa2..227377c 100644
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDefaultActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,28 +14,24 @@
  * limitations under the License.
  */
 
-package android.gwpasan;
+package android.cts.gwp_asan;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.Log;
-
-import java.lang.Override;
-
-import android.gwpasan.Utils;
 
 public class GwpAsanDefaultActivity extends Activity {
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         try {
-          boolean enabled = Utils.isGwpAsanEnabled();
-          setResult(RESULT_FIRST_USER + (enabled ? 1 : 0));
+            if (Utils.isGwpAsanEnabled()) {
+                setResult(Utils.TEST_SUCCESS);
+            } else {
+                setResult(Utils.TEST_FAILURE);
+            }
         } catch (Exception e) {
-          setResult(RESULT_OK);
+            setResult(Utils.TEST_FAILURE);
         }
         finish();
     }
-
 }
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDefaultService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
similarity index 74%
rename from tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDefaultService.java
rename to hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
index d7e9ccf..84a44b0 100644
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDefaultService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-package android.gwpasan;
+package android.cts.gwp_asan;
 
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
-import java.lang.Override;
-
-import android.gwpasan.Utils;
 
 public class GwpAsanDefaultService extends Service {
-
     private final IBinder mBinder = new LocalBinder();
 
     @Override
@@ -35,16 +31,15 @@
     }
 
     public class LocalBinder extends Binder {
-
         @Override
         public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
-            if (code == 42) {
-              try {
-                reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
-              } catch (Exception e) {
-                reply.writeInt(-1);
-              }
-              return true;
+            if (code == Utils.SERVICE_IS_GWP_ASAN_ENABLED) {
+                try {
+                    reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
+                } catch (Exception e) {
+                    reply.writeInt(-1);
+                }
+                return true;
             }
             return false;
         }
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDisabledActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
similarity index 72%
rename from tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDisabledActivity.java
rename to hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
index 4245820..d87b541 100644
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDisabledActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,29 +14,24 @@
  * limitations under the License.
  */
 
-package android.gwpasan;
+package android.cts.gwp_asan;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.Log;
-
-
-import java.lang.Override;
-
-import android.gwpasan.Utils;
 
 public class GwpAsanDisabledActivity extends Activity {
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         try {
-          boolean enabled = Utils.isGwpAsanEnabled();
-          setResult(RESULT_FIRST_USER + (enabled ? 1 : 0));
+            if (Utils.isGwpAsanDisabled()) {
+                setResult(Utils.TEST_SUCCESS);
+            } else {
+                setResult(Utils.TEST_FAILURE);
+            }
         } catch (Exception e) {
-          setResult(RESULT_OK);
+            setResult(Utils.TEST_FAILURE);
         }
         finish();
     }
-
 }
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDisabledService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
similarity index 74%
rename from tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDisabledService.java
rename to hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
index acc3c47..2e7f18c 100644
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanDisabledService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-package android.gwpasan;
+package android.cts.gwp_asan;
 
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
-import java.lang.Override;
-
-import android.gwpasan.Utils;
 
 public class GwpAsanDisabledService extends Service {
-
     private final IBinder mBinder = new LocalBinder();
 
     @Override
@@ -35,16 +31,15 @@
     }
 
     public class LocalBinder extends Binder {
-
         @Override
         public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
-            if (code == 42) {
-              try {
-                reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
-              } catch (Exception e) {
-                reply.writeInt(-1);
-              }
-              return true;
+            if (code == Utils.SERVICE_IS_GWP_ASAN_DISABLED) {
+                try {
+                    reply.writeInt(Utils.isGwpAsanDisabled() ? 1 : 0);
+                } catch (Exception e) {
+                    reply.writeInt(-1);
+                }
+                return true;
             }
             return false;
         }
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanEnabledActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
similarity index 73%
rename from tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanEnabledActivity.java
rename to hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
index 93d49ad..6bdeed8 100644
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanEnabledActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,26 +14,23 @@
  * limitations under the License.
  */
 
-package android.gwpasan;
+package android.cts.gwp_asan;
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.Log;
-
-
-import java.lang.Override;
-
-import android.gwpasan.Utils;
 
 public class GwpAsanEnabledActivity extends Activity {
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         try {
-          boolean enabled = Utils.isGwpAsanEnabled();
-          setResult(RESULT_FIRST_USER + (enabled ? 1 : 0));
+            if (Utils.isGwpAsanEnabled()) {
+                setResult(Utils.TEST_SUCCESS);
+            } else {
+                setResult(Utils.TEST_FAILURE);
+            }
         } catch (Exception e) {
-          setResult(RESULT_OK);
+            setResult(Utils.TEST_FAILURE);
         }
         finish();
     }
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanEnabledService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
similarity index 74%
rename from tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanEnabledService.java
rename to hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
index 489081f..f195480 100644
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanEnabledService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-package android.gwpasan;
+package android.cts.gwp_asan;
 
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
-import java.lang.Override;
-
-import android.gwpasan.Utils;
 
 public class GwpAsanEnabledService extends Service {
-
     private final IBinder mBinder = new LocalBinder();
 
     @Override
@@ -35,16 +31,15 @@
     }
 
     public class LocalBinder extends Binder {
-
         @Override
         public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
-            if (code == 42) {
-              try {
-                reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
-              } catch (Exception e) {
-                reply.writeInt(-1);
-              }
-              return true;
+            if (code == Utils.SERVICE_IS_GWP_ASAN_ENABLED) {
+                try {
+                    reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
+                } catch (Exception e) {
+                    reply.writeInt(-1);
+                }
+                return true;
             }
             return false;
         }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
new file mode 100644
index 0000000..f4ec2be
--- /dev/null
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.cts.gwp_asan;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.rule.ServiceTestRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class GwpAsanServiceTest {
+    @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
+
+    private boolean runService(Class<?> cls, int testNum) throws Exception {
+        Intent serviceIntent = new Intent(getApplicationContext(), cls);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        final Parcel request = Parcel.obtain();
+        final Parcel reply = Parcel.obtain();
+        if (!binder.transact(testNum, request, reply, 0)) {
+            throw new Exception();
+        }
+        int res = reply.readInt();
+        if (res < 0) {
+            throw new Exception();
+        }
+        return res != 0;
+    }
+
+    @Test
+    public void testEnablement() throws Exception {
+        assertTrue(runService(GwpAsanEnabledService.class, Utils.SERVICE_IS_GWP_ASAN_ENABLED));
+        assertTrue(runService(GwpAsanDefaultService.class, Utils.SERVICE_IS_GWP_ASAN_ENABLED));
+        assertTrue(runService(GwpAsanDisabledService.class, Utils.SERVICE_IS_GWP_ASAN_DISABLED));
+    }
+}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
new file mode 100644
index 0000000..95c8ecc
--- /dev/null
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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.cts.gwp_asan;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class TestActivityLauncher extends Activity {
+    static final String TAG = "TestActivityLauncher";
+
+    private int mResult;
+    private final Object mFinishEvent = new Object();
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        mResult = resultCode;
+        synchronized (mFinishEvent) {
+            mFinishEvent.notify();
+        }
+    }
+
+    public void callActivity(Class<?> cls) throws Exception {
+        Thread thread =
+                new Thread() {
+                    @Override
+                    public void run() {
+                        try {
+                            Context context = getApplicationContext();
+                            Intent intent = new Intent(context, cls);
+                            startActivityForResult(intent, 0);
+
+                            synchronized (mFinishEvent) {
+                                mFinishEvent.wait();
+                            }
+                        } catch (Exception e) {
+                            Log.d(TAG, "callActivity got an exception " + e.toString());
+                        }
+                    }
+                };
+        thread.start();
+        thread.join(50000 /* millis */);
+
+        if (mResult != Utils.TEST_SUCCESS) {
+            throw new Exception();
+        }
+    }
+}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
new file mode 100644
index 0000000..cf08537
--- /dev/null
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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.cts.gwp_asan;
+
+import android.app.Activity;
+import android.app.Application;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class Utils {
+    static {
+        System.loadLibrary("gwp_asan_cts_library_jni");
+    }
+
+    public static final int TEST_SUCCESS = Activity.RESULT_FIRST_USER + 100;
+    public static final int TEST_FAILURE = Activity.RESULT_FIRST_USER + 101;
+
+    public static final int SERVICE_IS_GWP_ASAN_ENABLED = 42;
+    public static final int SERVICE_IS_GWP_ASAN_DISABLED = 43;
+
+    // Check that GWP-ASan is enabled by allocating a whole bunch of heap
+    // pointers and making sure one of them is a GWP-ASan allocation (by
+    // comparing with /proc/self/maps).
+    public static native boolean isGwpAsanEnabled();
+    // Check that GWP-ASan is disabled by ensuring there's no GWP-ASan mappings
+    // in /proc/self/maps.
+    public static boolean isGwpAsanDisabled() throws IOException {
+        try (FileReader fr = new FileReader("/proc/self/maps");
+                BufferedReader reader = new BufferedReader(fr)) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                if (line.contains("GWP-ASan Guard Page")) {
+                    Log.e(Application.getProcessName(),
+                            "Line contained guard page: " + line);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
diff --git a/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp b/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
new file mode 100644
index 0000000..f7d0176
--- /dev/null
+++ b/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/log.h>
+#include <jni.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <fstream>
+#include <memory>
+#include <shared_mutex>
+#include <string>
+#include <vector>
+
+// We can get all the GWP-ASan ranges ahead of time. GWP-ASan doesn't do an mmap() for each
+// allocation, it reserves the entire pool up front (with the name "[anon:GWP-ASan Guard Page]") and
+// then mprotect()s and renames pages in that pool as necessary. At the point where we're observing
+// the range, it's normal to have a couple of slots already in use. Technically, the metadata region
+// also exists at startup ("[anon:GWP-ASan Metadata]"), but no malloc() will ever be allocated
+// there, and it's not necessary to special case this single range.
+const std::vector<std::pair<uintptr_t, uintptr_t>>& get_gwp_asan_ranges() {
+    static std::mutex gwp_asan_ranges_mutex;
+    static std::vector<std::pair<uintptr_t, uintptr_t>> gwp_asan_ranges;
+
+    std::lock_guard<std::mutex> l(gwp_asan_ranges_mutex);
+    if (gwp_asan_ranges.size() != 0) return gwp_asan_ranges;
+
+    std::ifstream mappings("/proc/self/maps");
+    if (!mappings.good()) {
+        __android_log_print(ANDROID_LOG_FATAL, getprogname(), "Failed to open /proc/self/maps");
+    }
+
+    std::string line;
+    while (std::getline(mappings, line)) {
+        uintptr_t map_start, map_end;
+        if (line.find("[anon:GWP-ASan") != std::string::npos &&
+            sscanf(line.c_str(), "%zx-%zx", &map_start, &map_end) == 2) {
+            gwp_asan_ranges.emplace_back(map_start, map_end);
+            __android_log_print(ANDROID_LOG_INFO, getprogname(),
+                                "Found 0x%zx-byte GWP-ASan mapping: \"%s\"", map_end - map_start,
+                                line.c_str());
+        }
+    }
+    return gwp_asan_ranges;
+}
+
+bool is_gwp_asan_pointer(void* ptr) {
+    static const std::vector<std::pair<uintptr_t, uintptr_t>>& ranges = get_gwp_asan_ranges();
+    uintptr_t untagged_ptr = reinterpret_cast<uintptr_t>(ptr);
+#if defined(__aarch64__)
+    // Untag the heap pointer: https://source.android.com/docs/security/test/tagged-pointers
+    untagged_ptr &= ~(0xffull << 56);
+#endif // defined(__aarch64__)
+    return std::any_of(ranges.cbegin(), ranges.cend(), [&](const auto& range) {
+        return untagged_ptr >= range.first && untagged_ptr < range.second;
+    });
+}
+
+constexpr size_t kMallocsToGuaranteeAGwpAsanPointer = 0x10000;
+
+std::unique_ptr<char[]> get_gwp_asan_pointer() {
+    for (size_t i = 0; i < kMallocsToGuaranteeAGwpAsanPointer; ++i) {
+        auto p = std::make_unique<char[]>(4096);
+        if (is_gwp_asan_pointer(p.get())) {
+            __android_log_print(ANDROID_LOG_INFO, getprogname(), "Found GWP-ASan pointer: %p",
+                                p.get());
+            return p;
+        }
+    }
+    return std::unique_ptr<char[]>();
+}
+
+// Note: The '_1' in the function signature here is the JNI literalization of the underscore in the
+// 'gwp_asan' part of the package name. See "Table 2-1 Unicode Character Translation" in
+// https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html
+extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_gwp_1asan_Utils_isGwpAsanEnabled(JNIEnv*) {
+    std::unique_ptr<char[]> gwp_asan_ptr = get_gwp_asan_pointer();
+    return gwp_asan_ptr.get() == nullptr ? JNI_FALSE : JNI_TRUE;
+}
diff --git a/hostsidetests/gwp_asan/enabled/Android.bp b/hostsidetests/gwp_asan/enabled/Android.bp
new file mode 100644
index 0000000..df592d2
--- /dev/null
+++ b/hostsidetests/gwp_asan/enabled/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2023 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"],
+}
+
+android_test_helper_app {
+    name: "CtsGwpAsanEnabled",
+    defaults: ["cts_gwp_asan_app_defaults"],
+    srcs: [
+        "src/**/*.java",
+    ],
+    use_embedded_native_libs: false,
+}
diff --git a/tests/tests/gwp-asan/enabled/AndroidManifest.xml b/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
similarity index 62%
rename from tests/tests/gwp-asan/enabled/AndroidManifest.xml
rename to hostsidetests/gwp_asan/enabled/AndroidManifest.xml
index acded16..414d0c5 100644
--- a/tests/tests/gwp-asan/enabled/AndroidManifest.xml
+++ b/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
+<!-- Copyright (C) 2023 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.
@@ -15,10 +15,12 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-       package="android.gwpasan.cts"
-       android:targetSandboxVersion="2">
+          package="android.cts.gwp_asan"
+          android:targetSandboxVersion="2">
 
-  <application android:extractNativeLibs="true"
+  <uses-sdk android:targetSdkVersion="30" />
+  <application android:debuggable="true"
+               android:extractNativeLibs="true"
                android:gwpAsanMode="always">
     <processes>
       <process />
@@ -28,26 +30,28 @@
                android:gwpAsanMode="never" />
       <process android:process=":gwp_asan_default" />
     </processes>
+
     <uses-library android:name="android.test.runner" />
-    <activity android:name="android.gwpasan.GwpAsanTestActivity" />
-    <activity android:name="android.gwpasan.GwpAsanEnabledActivity"
+
+    <activity android:name=".TestActivityLauncher" />
+    <activity android:name=".GwpAsanActivityTest" />
+
+    <activity android:name=".GwpAsanEnabledActivity"
               android:process=":gwp_asan_enabled" />
-    <activity android:name="android.gwpasan.GwpAsanDisabledActivity"
+    <activity android:name=".GwpAsanDisabledActivity"
               android:process=":gwp_asan_disabled" />
-    <activity android:name="android.gwpasan.GwpAsanDefaultActivity"
+    <activity android:name=".GwpAsanDefaultActivity"
               android:process=":gwp_asan_default" />
-    <service android:name="android.gwpasan.GwpAsanEnabledService"
+
+    <service android:name=".GwpAsanEnabledService"
              android:process=":gwp_asan_enabled" />
-    <service android:name="android.gwpasan.GwpAsanDisabledService"
+    <service android:name=".GwpAsanDisabledService"
              android:process=":gwp_asan_disabled" />
-    <service android:name="android.gwpasan.GwpAsanDefaultService"
+    <service android:name=".GwpAsanDefaultService"
              android:process=":gwp_asan_default" />
   </application>
 
   <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                   android:targetPackage="android.gwpasan.cts"
-                   android:label="CTS tests of GWP-ASan">
-    <meta-data android:name="listener"
-               android:value="com.android.cts.runner.CtsTestRunListener" />
-  </instrumentation>
+                   android:targetPackage="android.cts.gwp_asan"
+                   android:label="CTS tests of GWP-ASan" />
 </manifest>
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
new file mode 100644
index 0000000..012a2ba
--- /dev/null
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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.cts.gwp_asan;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class EnabledTest extends BaseHostJUnit4Test {
+    private static final String TEST_APK = "CtsGwpAsanEnabled.apk";
+    private static final String TEST_PKG = "android.cts.gwp_asan";
+    private ITestDevice mDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = getDevice();
+        installPackage(TEST_APK, new String[0]);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        uninstallPackage(mDevice, TEST_PKG);
+    }
+
+    @Test
+    public void testGwpAsanEnabled() throws Exception {
+        Assert.assertTrue(
+                runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testEnablement"));
+        Assert.assertTrue(
+                runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testEnablement"));
+    }
+}
diff --git a/hostsidetests/hdmicec/app/AndroidManifest.xml b/hostsidetests/hdmicec/app/AndroidManifest.xml
index 4eb046e3..4db04bd 100644
--- a/hostsidetests/hdmicec/app/AndroidManifest.xml
+++ b/hostsidetests/hdmicec/app/AndroidManifest.xml
@@ -22,7 +22,8 @@
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <application>
         <activity android:name=".HdmiCecKeyEventCapture"
-             android:exported="true">
+             android:exported="true"
+             android:launchMode="singleInstance">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
diff --git a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
index 63736bf..d2070db 100644
--- a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
+++ b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
@@ -19,8 +19,8 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.Gravity;
+import android.view.KeyEvent;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TableRow;
@@ -81,4 +81,20 @@
         return true;
     }
 
-}
\ No newline at end of file
+    /*
+    Override onUserLeaveHint() to simulate KEYCODE_HOME pressing for now.
+    If the activity will be used to test other complicated scenarios
+    which will let the activity go into the background,
+    the onUserLeaveHint() might be called without KEYCODE_HOME pressing.
+    */
+    @Override
+    protected void onUserLeaveHint() {
+        text.setText((longPressed ? "Long press " : "Short press ")
+                + "KEYCODE_HOME");
+        Log.d(TAG, "onUserLeaveHint: KEYCODE_HOME Press");
+        Log.i(TAG, (longPressed ? "Long press " : "Short press ") + "KEYCODE_HOME");
+
+        longPressed = false;
+        super.onUserLeaveHint();
+    }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
index c23e16b..33465a1 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
@@ -258,6 +258,11 @@
                     device,
                     CLASS,
                     "Short press KEYCODE_" + mUserControlPressKeys_20.get(userControlPressKey));
+            // KEYCODE_HOME pressing will let the activity HdmiCecKeyEventCapture be paused.
+            // Resume the activity after tesing for KEYCODE_HOME pressing.
+            if (userControlPressKey == HdmiCecConstants.CEC_KEYCODE_ROOT_MENU) {
+                device.executeShellCommand(START_COMMAND);
+            }
         }
     }
 
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
index baaccc8..dad1800 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
@@ -132,7 +132,7 @@
             sendUcpMenuCommand(HdmiCecConstants.CEC_KEYCODE_SETUP_MENU, "SETTINGS");
         }
         if ((remoteControlProfileSource & 0x10) == 0x10) {
-            sendUcpMenuCommand(HdmiCecConstants.CEC_KEYCODE_ROOT_MENU, "MENU");
+            sendUcpMenuCommand(HdmiCecConstants.CEC_KEYCODE_ROOT_MENU, "HOME");
         }
     }
 
diff --git a/hostsidetests/incident/AndroidTest.xml b/hostsidetests/incident/AndroidTest.xml
index 727277d..73be7b4 100644
--- a/hostsidetests/incident/AndroidTest.xml
+++ b/hostsidetests/incident/AndroidTest.xml
@@ -20,9 +20,6 @@
     <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
     <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
-    <target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
-        <option name="user-type" value="system" />
-    </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsIncidentHostTestCases.jar" />
     </test>
diff --git a/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp b/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
index 8c59b53..1608365 100644
--- a/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
+++ b/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
@@ -28,6 +28,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     sdk_version: "test_current",
     min_sdk_version: "19",
diff --git a/hostsidetests/multidevices/wifi_aware/Android.bp b/hostsidetests/multidevices/wifi_aware/Android.bp
index 54668ad..9e90d28 100644
--- a/hostsidetests/multidevices/wifi_aware/Android.bp
+++ b/hostsidetests/multidevices/wifi_aware/Android.bp
@@ -33,6 +33,7 @@
     data: [
         // Package the snippet with the mobly test
         ":wifi_aware_snippet",
+	"requirements.txt",
     ],
     version: {
         py3: {
diff --git a/hostsidetests/multidevices/wifi_aware/requirements.txt b/hostsidetests/multidevices/wifi_aware/requirements.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hostsidetests/multidevices/wifi_aware/requirements.txt
diff --git a/hostsidetests/multidevices/wifi_aware/wifi_aware_test.py b/hostsidetests/multidevices/wifi_aware/wifi_aware_test.py
index d2ab7df..e7188f6 100644
--- a/hostsidetests/multidevices/wifi_aware/wifi_aware_test.py
+++ b/hostsidetests/multidevices/wifi_aware/wifi_aware_test.py
@@ -63,7 +63,8 @@
 
 if __name__ == '__main__':
   # Take test args
-  index = sys.argv.index('--')
-  sys.argv = sys.argv[:1] + sys.argv[index + 1:]
+  if '--' in sys.argv:
+    index = sys.argv.index('--')
+    sys.argv = sys.argv[:1] + sys.argv[index + 1:]
 
   test_runner.main()
diff --git a/hostsidetests/security/Android.bp b/hostsidetests/security/Android.bp
index 6dab59b..4798f0c 100644
--- a/hostsidetests/security/Android.bp
+++ b/hostsidetests/security/Android.bp
@@ -45,6 +45,10 @@
     static_libs: [
         "CtsSecurityHostTestCases_StaticLibs",
         "diffutils-prebuilt-jar",
+        "CompatChangeGatingTestBase",
+    ],
+    data: [
+        ":CtsZipValidateApp",
     ],
     // These two host cc_library_* modules cannot be wrapped as java_resources directly into
     // a .jar due to the "missing variant" issue, see b/197025344 for more details. This workaround
diff --git a/tests/tests/gwp-asan/enabled/Android.bp b/hostsidetests/security/app/Android.bp
similarity index 65%
copy from tests/tests/gwp-asan/enabled/Android.bp
copy to hostsidetests/security/app/Android.bp
index a78598e..4418894 100644
--- a/tests/tests/gwp-asan/enabled/Android.bp
+++ b/hostsidetests/security/app/Android.bp
@@ -1,4 +1,5 @@
-// Copyright (C) 2020 The Android Open Source Project
+//
+// Copyright (C) 2023 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.
@@ -11,32 +12,29 @@
 // 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"],
 }
 
-android_test {
-    name: "CtsGwpAsanTestCases",
-    defaults: ["cts_defaults"],
-    compile_multilib: "both",
-    // When built, explicitly put it in the data partition.
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
+android_test_helper_app {
+    name: "CtsZipValidateApp",
+    defaults: ["cts_support_defaults"],
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
     libs: [
-        "android.test.runner",
-        "android.test.base",
+        "junit",
     ],
     static_libs: [
         "ctstestrunner-axt",
-        "androidx.test.rules",
-        "androidx.test.core",
-        "androidx.test.ext.junit",
+        "truth-prebuilt",
     ],
-    srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    use_embedded_native_libs: false,
+
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts",
+        "general-tests",
+    ],
 }
diff --git a/hostsidetests/security/app/AndroidManifest.xml b/hostsidetests/security/app/AndroidManifest.xml
new file mode 100644
index 0000000..16b7ce0
--- /dev/null
+++ b/hostsidetests/security/app/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts">
+
+    <!-- targetSdkVersion must be lower than U for testing ZipPathValidator feature
+     with appcompat change -->
+    <uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33"/>
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts">
+    </instrumentation>
+
+</manifest>
diff --git a/hostsidetests/security/app/src/android/security/cts/ZipPathValidatorTest.java b/hostsidetests/security/app/src/android/security/cts/ZipPathValidatorTest.java
new file mode 100644
index 0000000..80a4d32
--- /dev/null
+++ b/hostsidetests/security/app/src/android/security/cts/ZipPathValidatorTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2023 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 static org.junit.Assert.assertThrows;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+@RunWith(AndroidJUnit4.class)
+public class ZipPathValidatorTest {
+    @Test
+    public void newZipFile_whenZipFileHasDangerousEntriesAndChangeEnabled_throws() throws
+            Exception {
+        final String[] dangerousEntryNames = {
+                "../foo.bar",
+                "foo/../bar.baz",
+                "foo/../../bar.baz",
+                "foo.bar/..",
+                "foo.bar/../",
+                "..",
+                "../",
+                "/foo",
+        };
+        for (String entryName : dangerousEntryNames) {
+            final File tempFile = File.createTempFile("smdc", "zip");
+            try {
+                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
+
+                assertThrows(
+                        "ZipException expected for entry: " + entryName,
+                        ZipException.class,
+                        () -> {
+                            new ZipFile(tempFile);
+                        });
+            } finally {
+                tempFile.delete();
+            }
+        }
+    }
+
+    @Test
+    public void zipInputStreamGetNextEntry_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
+            throws Exception {
+        final String[] dangerousEntryNames = {
+                "../foo.bar",
+                "foo/../bar.baz",
+                "foo/../../bar.baz",
+                "foo.bar/..",
+                "foo.bar/../",
+                "..",
+                "../",
+                "/foo",
+        };
+        for (String entryName : dangerousEntryNames) {
+            byte[] badZipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
+            try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(badZipBytes))) {
+                assertThrows(
+                        "ZipException expected for entry: " + entryName,
+                        ZipException.class,
+                        () -> {
+                            zis.getNextEntry();
+                        });
+            }
+        }
+    }
+
+    @Test
+    public void newZipFile_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow() throws
+            Exception {
+        final String[] normalEntryNames = {
+                "foo", "foo.bar", "foo..bar",
+        };
+        for (String entryName : normalEntryNames) {
+            final File tempFile = File.createTempFile("smdc", "zip");
+            try {
+                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
+                ZipFile zipFile = new ZipFile((tempFile));
+            } finally {
+                tempFile.delete();
+            }
+        }
+    }
+
+    @Test
+    public void
+            zipInputStreamGetNextEntry_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
+                    throws Exception {
+        final String[] normalEntryNames = {
+                "foo", "foo.bar", "foo..bar",
+        };
+        for (String entryName : normalEntryNames) {
+            byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
+            ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
+            ZipEntry zipEntry = zis.getNextEntry();
+        }
+    }
+
+    @Test
+    public void newZipFile_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
+            throws Exception {
+        final String[] entryNames = {
+                "../foo.bar",
+                "foo/../bar.baz",
+                "foo/../../bar.baz",
+                "foo.bar/..",
+                "foo.bar/../",
+                "..",
+                "../",
+                "/foo",
+                "foo",
+                "foo.bar",
+                "foo..bar",
+        };
+        for (String entryName : entryNames) {
+            final File tempFile = File.createTempFile("smdc", "zip");
+            try {
+                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
+                ZipFile zipFile = new ZipFile((tempFile));
+            } finally {
+                tempFile.delete();
+            }
+        }
+    }
+
+    @Test
+    public void
+            zipInputStreamGetNextEntry_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
+                    throws Exception {
+        final String[] entryNames = {
+                "../foo.bar",
+                "foo/../bar.baz",
+                "foo/../../bar.baz",
+                "foo.bar/..",
+                "foo.bar/../",
+                "..",
+                "../",
+                "/foo",
+                "foo",
+                "foo.bar",
+                "foo..bar",
+        };
+        for (String entryName : entryNames) {
+            byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
+            ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
+            ZipEntry zipEntry = zis.getNextEntry();
+        }
+    }
+
+    private void writeZipFileOutputStreamWithEmptyEntry(File tempFile, String entryName)
+            throws IOException {
+        FileOutputStream tempFileStream = new FileOutputStream(tempFile);
+        writeZipOutputStreamWithEmptyEntry(tempFileStream, entryName);
+        tempFileStream.close();
+    }
+
+    private byte[] getZipBytesFromZipOutputStreamWithEmptyEntry(String entryName)
+            throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        writeZipOutputStreamWithEmptyEntry(bos, entryName);
+        return bos.toByteArray();
+    }
+
+    private void writeZipOutputStreamWithEmptyEntry(OutputStream os, String entryName)
+            throws IOException {
+        ZipOutputStream zos = new ZipOutputStream(os);
+        ZipEntry entry = new ZipEntry(entryName);
+        zos.putNextEntry(entry);
+        zos.write(new byte[2]);
+        zos.closeEntry();
+        zos.close();
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/host/ZipPathValidatorTest.java b/hostsidetests/security/src/android/security/cts/host/ZipPathValidatorTest.java
new file mode 100644
index 0000000..0567d92
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/host/ZipPathValidatorTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 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.host;
+
+import android.compat.cts.CompatChangeGatingTestCase;
+
+import com.google.common.collect.ImmutableSet;
+
+public class ZipPathValidatorTest extends CompatChangeGatingTestCase {
+    protected static final String TEST_APK = "CtsZipValidateApp.apk";
+    protected static final String TEST_PKG = "android.security.cts";
+
+    private static final long VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL = 242716250L;
+
+    @Override
+    protected void setUp() throws Exception {
+        installPackage(TEST_APK, true);
+    }
+
+    public void testNewZipFile_whenZipFileHasDangerousEntriesAndChangeEnabled_throws() throws
+            Exception {
+        runDeviceCompatTest(TEST_PKG,
+                ".ZipPathValidatorTest",
+                "newZipFile_whenZipFileHasDangerousEntriesAndChangeEnabled_throws",
+                /* enabledChanges */ ImmutableSet.of(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL),
+                /* disabledChanges */ ImmutableSet.of());
+    }
+
+    public void
+            testZipInputStreamGetNextEntry_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
+                    throws Exception {
+        runDeviceCompatTest(TEST_PKG,
+                ".ZipPathValidatorTest",
+                "zipInputStreamGetNextEntry_whenZipFileHasDangerousEntriesAndChangeEnabled_throws",
+                /* enabledChanges */ ImmutableSet.of(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL),
+                /* disabledChanges */ ImmutableSet.of());
+    }
+
+    public void testNewZipFile_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow() throws
+            Exception {
+        runDeviceCompatTest(TEST_PKG,
+                ".ZipPathValidatorTest",
+                "newZipFile_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow",
+                /* enabledChanges */ ImmutableSet.of(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL),
+                /* disabledChanges */ ImmutableSet.of());
+    }
+
+    public void
+            testZipInputStreamGetNextEntry_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
+                    throws Exception {
+        runDeviceCompatTest(TEST_PKG,
+                ".ZipPathValidatorTest",
+                "zipInputStreamGetNextEntry_whenZipFileHasNormalEntriesAndChangeEnabled_"
+                        + "doesNotThrow",
+                /* enabledChanges */ ImmutableSet.of(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL),
+                /* disabledChanges */ ImmutableSet.of());
+    }
+
+    public void
+            testNewZipFile_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
+                    throws Exception {
+        runDeviceCompatTest(TEST_PKG,
+                ".ZipPathValidatorTest",
+                "newZipFile_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow",
+                /* enabledChanges */ ImmutableSet.of(),
+                /* disabledChanges */ ImmutableSet.of(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL));
+    }
+
+    public void
+            testZipInputStreamGetNextEntry_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
+                    throws Exception {
+        runDeviceCompatTest(TEST_PKG,
+                ".ZipPathValidatorTest",
+                "zipInputStreamGetNextEntry_whenZipFileHasNormalAndDangerousEntriesAnd"
+                        + "ChangeDisabled_doesNotThrow",
+                /* enabledChanges */ ImmutableSet.of(),
+                /* disabledChanges */ ImmutableSet.of(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL));
+    }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
index 1aafea3..cea0ad0 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -18,49 +18,37 @@
 #include <media/mediaplayer.h>
 #include "../includes/common.h"
 
-#define PREPARE_DRM 39
-
 using namespace android;
 
 int main() {
+    constexpr size_t bufferSize = 16;
+    constexpr uint32_t prepareDrm = 39;
+    constexpr uint32_t unknownTrxnCode = prepareDrm + 5;
     sp<IServiceManager> serviceManager = defaultServiceManager();
-    if (serviceManager == nullptr) {
-        return EXIT_FAILURE;
-    }
+    FAIL_CHECK(serviceManager != nullptr);
 
     sp<IBinder> mediaPlayerService = serviceManager->getService(String16("media.player"));
-    if (mediaPlayerService == nullptr) {
-        return EXIT_FAILURE;
-    }
+    FAIL_CHECK(mediaPlayerService != nullptr);
 
     sp<IMediaPlayerService> iMediaPlayerService =
             IMediaPlayerService::asInterface(mediaPlayerService);
-    if (iMediaPlayerService == nullptr) {
-        return EXIT_FAILURE;
-    }
+    FAIL_CHECK(iMediaPlayerService != nullptr);
 
-    MediaPlayer *mediaPlayer = new MediaPlayer();
-    if (mediaPlayer == nullptr) {
-        return EXIT_FAILURE;
-    }
+    sp<MediaPlayer> mediaPlayer = new MediaPlayer();
+    FAIL_CHECK(mediaPlayer != nullptr);
 
     sp<IMediaPlayer> iMediaPlayer = iMediaPlayerService->create(mediaPlayer);
-    if (iMediaPlayer == nullptr) {
-        delete (mediaPlayer);
-        return EXIT_FAILURE;
-    }
+    FAIL_CHECK(iMediaPlayer != nullptr);
 
     Parcel data, reply;
     data.writeInterfaceToken(iMediaPlayer->getInterfaceDescriptor());
-    const uint8_t arr[16] = {};
-    data.write(arr, 16);
-    data.writeUint32(2);
-    data.writeUnpadded(arr, 1);
+    status_t status = IMediaPlayer::asBinder(iMediaPlayer)->transact(unknownTrxnCode, data, &reply);
+    FAIL_CHECK(status == UNKNOWN_TRANSACTION);
 
-    IMediaPlayer::asBinder(iMediaPlayer)->transact(PREPARE_DRM, data, &reply);
-    uint32_t size = 0;
-    reply.readUint32(&size);
-
-    delete (mediaPlayer);
-    return (size > 0) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+    const uint8_t arr[bufferSize] = {};
+    data.write(arr, bufferSize);
+    data.writeUint32(bufferSize);
+    data.writeUnpadded(arr, bufferSize - 1);
+    status = IMediaPlayer::asBinder(iMediaPlayer)->transact(prepareDrm, data, &reply);
+    return status == OK ? EXIT_VULNERABLE : EXIT_SUCCESS;
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 52141c6..213c7b1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -18,10 +18,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.compatibility.common.util.MetricsReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
@@ -29,14 +27,11 @@
 import com.android.ddmlib.IShellOutputReceiver;
 import com.android.ddmlib.NullOutputReceiver;
 import com.android.sts.common.tradefed.testtype.SecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -47,7 +42,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Scanner;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -64,15 +58,18 @@
     final static Pattern regexSpecialCharsEscapedPattern =
             Pattern.compile("[" + regexSpecialCharsEscaped + "]");
 
+    /**
+     * @deprecated Use {@link NativePoc} instead.
+     */
+    @Deprecated
     public static class pocConfig {
         String binaryName;
         String arguments;
         Map<String, String> envVars;
         String inputFilesDestination;
         ITestDevice device;
-        CrashUtils.Config config;
+        TombstoneUtils.Config config = new TombstoneUtils.Config();
         List<String> inputFiles = Collections.emptyList();
-        boolean checkCrash = true;
 
         pocConfig(String binaryName, ITestDevice device) {
             this.binaryName = binaryName;
@@ -80,12 +77,15 @@
         }
     }
 
-    /** Runs a commandline on the specified device
+    /**
+     * Runs a commandline on the specified device
      *
+     * @deprecated Use {@link CommandUtil} instead.
      * @param command the command to be ran
      * @param device device for the command to be ran on
      * @return the console output from running the command
      */
+    @Deprecated
     public static String runCommandLine(String command, ITestDevice device) throws Exception {
         if ("reboot".equals(command)) {
             throw new IllegalArgumentException(
@@ -97,10 +97,12 @@
     /**
      * Pushes and runs a binary to the selected device
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @return the console output from the binary
      */
+    @Deprecated
     public static String runPoc(String pocName, ITestDevice device) throws Exception {
         return runPoc(pocName, device, SecurityTestCase.TIMEOUT_NONDETERMINISTIC);
     }
@@ -108,11 +110,13 @@
     /**
      * Pushes and runs a binary to the selected device
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      * @return the console output from the binary
      */
+    @Deprecated
     public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception {
         return runPoc(pocName, device, timeout, null);
     }
@@ -120,12 +124,14 @@
     /**
      * Pushes and runs a binary to the selected device
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      * @param arguments the input arguments for the poc
      * @return the console output from the binary
      */
+    @Deprecated
     public static String runPoc(String pocName, ITestDevice device, int timeout, String arguments)
             throws Exception {
         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
@@ -136,48 +142,57 @@
     /**
      * Pushes and runs a binary to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static void runPocNoOutput(String pocName, ITestDevice device, int timeout)
             throws Exception {
         runPocNoOutput(pocName, device, timeout, null);
     }
 
     /**
-     * Pushes and runs a binary with arguments to the selected device and
-     * ignores any of its output.
+     * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      * @param arguments input arguments for the poc
      */
-    public static void runPocNoOutput(String pocName, ITestDevice device, int timeout,
-            String arguments) throws Exception {
+    @Deprecated
+    public static void runPocNoOutput(
+            String pocName, ITestDevice device, int timeout, String arguments) throws Exception {
         runPoc(pocName, device, timeout, arguments, null);
     }
 
     /**
-     * Pushes and runs a binary with arguments to the selected device and
-     * ignores any of its output.
+     * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      * @param arguments input arguments for the poc
      * @param receiver the type of receiver to run against
      */
-    public static int runPoc(String pocName, ITestDevice device, int timeout,
-            String arguments, IShellOutputReceiver receiver) throws Exception {
+    @Deprecated
+    public static int runPoc(
+            String pocName,
+            ITestDevice device,
+            int timeout,
+            String arguments,
+            IShellOutputReceiver receiver)
+            throws Exception {
               return runPoc(pocName, device, timeout, arguments, null, receiver);
     }
 
     /**
-     * Pushes and runs a binary with arguments to the selected device and
-     * ignores any of its output.
+     * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
@@ -185,9 +200,15 @@
      * @param envVars run the poc with environment variables
      * @param receiver the type of receiver to run against
      */
-    public static int runPoc(String pocName, ITestDevice device, int timeout,
-            String arguments, Map<String, String> envVars,
-            IShellOutputReceiver receiver) throws Exception {
+    @Deprecated
+    public static int runPoc(
+            String pocName,
+            ITestDevice device,
+            int timeout,
+            String arguments,
+            Map<String, String> envVars,
+            IShellOutputReceiver receiver)
+            throws Exception {
         String remoteFile = String.format("%s%s", TMP_PATH, pocName);
         SecurityTestCase.getPocPusher(device).pushFile(pocName + "_sts", remoteFile);
 
@@ -243,9 +264,12 @@
 
     /**
      * Assert the poc is executable
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      */
+    @Deprecated
     private static void assertPocExecutable(String pocName, ITestDevice device) throws Exception {
         String fullPocPath = TMP_PATH + pocName;
         device.executeShellCommand("chmod 777 " + fullPocPath);
@@ -258,48 +282,6 @@
     }
 
     /**
-     * Enables malloc debug on a given process.
-     *
-     * @param processName the name of the process to run with libc malloc debug
-     * @param device the device to use
-     * @return true if enabling malloc debug succeeded
-     */
-    public static boolean enableLibcMallocDebug(String processName, ITestDevice device) throws Exception {
-        device.executeShellCommand("setprop libc.debug.malloc.program " + processName);
-        device.executeShellCommand("setprop libc.debug.malloc.options \"backtrace guard\"");
-        /**
-         * The pidof command is being avoided because it does not exist on versions before M, and
-         * it behaves differently between M and N.
-         * Also considered was the ps -AoPID,CMDLINE command, but ps does not support options on
-         * versions before O.
-         * The [^]] prefix is being used for the grep command to avoid the case where the output of
-         * ps includes the grep command itself.
-         */
-        String cmdOut = device.executeShellCommand("ps -A | grep '[^]]" + processName + "'");
-        /**
-         * .hasNextInt() checks if the next token can be parsed as an integer, not if any remaining
-         * token is an integer.
-         * Example command: $ ps | fgrep mediaserver
-         * Out: media     269   1     77016  24416 binder_thr 00f35142ec S /system/bin/mediaserver
-         * The second field of the output is the PID, which is needed to restart the process.
-         */
-        Scanner s = new Scanner(cmdOut).useDelimiter("\\D+");
-        if(!s.hasNextInt()) {
-            CLog.w("Could not find pid for process: " + processName);
-            return false;
-        }
-
-        String result = device.executeShellCommand("kill -9 " + s.nextInt());
-        if(!result.equals("")) {
-            CLog.w("Could not restart process: " + processName);
-            return false;
-        }
-
-        TimeUnit.SECONDS.sleep(1);
-        return true;
-    }
-
-    /**
      * Pushes and installs an apk to the selected device
      *
      * @param pathToApk a string path to apk from the /res folder
@@ -394,7 +376,10 @@
     }
     /**
      * Utility function to help check the exit code of a shell command
+     *
+     * @deprecated Use {@link CommandUtil} instead.
      */
+    @Deprecated
     public static int runCommandGetExitCode(String cmd, ITestDevice device) throws Exception {
         long time = System.currentTimeMillis();
         String exitStatusString = runCommandLine(
@@ -416,16 +401,17 @@
     }
 
     /**
-     * Pushes and runs a binary to the selected device and checks exit code
-     * Return code 113 is used to indicate the vulnerability
+     * Pushes and runs a binary to the selected device and checks exit code Return code 113 is used
+     * to indicate the vulnerability
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
     @Deprecated
-    public static boolean runPocCheckExitCode(String pocName, ITestDevice device,
-                                              int timeout) throws Exception {
+    public static boolean runPocCheckExitCode(String pocName, ITestDevice device, int timeout)
+            throws Exception {
 
        //Refer to go/asdl-sts-guide Test section for knowing the significance of 113 code
        return runPocGetExitStatus(pocName, device, timeout) == 113;
@@ -433,11 +419,13 @@
 
     /**
      * Pushes and runs a binary to the device and returns the exit status.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
-
      */
+    @Deprecated
     public static int runPocGetExitStatus(String pocName, ITestDevice device, int timeout)
             throws Exception {
        return runPocGetExitStatus(pocName, null, device, timeout);
@@ -445,36 +433,49 @@
 
     /**
      * Pushes and runs a binary to the device and returns the exit status.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param arguments input arguments for the poc
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
-    public static int runPocGetExitStatus(String pocName, String arguments, ITestDevice device,
-            int timeout) throws Exception {
+    @Deprecated
+    public static int runPocGetExitStatus(
+            String pocName, String arguments, ITestDevice device, int timeout) throws Exception {
               return runPocGetExitStatus(pocName, arguments, null, device, timeout);
     }
 
     /**
      * Pushes and runs a binary to the device and returns the exit status.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param arguments input arguments for the poc
      * @param envVars run the poc with environment variables
      * @param device device to be run on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static int runPocGetExitStatus(
-            String pocName, String arguments, Map<String, String> envVars,
-            ITestDevice device, int timeout) throws Exception {
+            String pocName,
+            String arguments,
+            Map<String, String> envVars,
+            ITestDevice device,
+            int timeout)
+            throws Exception {
         return runPoc(pocName, device, timeout, arguments, envVars, null);
     }
 
     /**
      * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static void runPocAssertExitStatusNotVulnerable(
             String pocName, ITestDevice device, int timeout) throws Exception {
         runPocAssertExitStatusNotVulnerable(pocName, null, device, timeout);
@@ -482,27 +483,37 @@
 
     /**
      * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param arguments input arguments for the poc
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
-    public static void runPocAssertExitStatusNotVulnerable(String pocName, String arguments,
-            ITestDevice device, int timeout) throws Exception {
+    @Deprecated
+    public static void runPocAssertExitStatusNotVulnerable(
+            String pocName, String arguments, ITestDevice device, int timeout) throws Exception {
         runPocAssertExitStatusNotVulnerable(pocName, arguments, null, device, timeout);
     }
 
     /**
      * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param arguments input arguments for the poc
      * @param envVars run the poc with environment variables
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static void runPocAssertExitStatusNotVulnerable(
-            String pocName, String arguments, Map<String, String> envVars,
-            ITestDevice device, int timeout) throws Exception {
+            String pocName,
+            String arguments,
+            Map<String, String> envVars,
+            ITestDevice device,
+            int timeout)
+            throws Exception {
         assertTrue("PoC returned exit status 113: vulnerable",
                 runPocGetExitStatus(pocName, arguments, envVars, device, timeout) != 113);
     }
@@ -510,136 +521,164 @@
     /**
      * Runs the poc binary and asserts that there are no security crashes that match the expected
      * process pattern.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param processPatternStrings a Pattern string to match the crash tombstone process
      */
-    public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
-            String... processPatternStrings) throws Exception {
+    @Deprecated
+    public static void runPocAssertNoCrashes(
+            String pocName, ITestDevice device, String... processPatternStrings) throws Exception {
         runPocAssertNoCrashes(pocName, device,
-                new CrashUtils.Config().setProcessPatterns(processPatternStrings));
+                new TombstoneUtils.Config().setProcessPatterns(processPatternStrings));
     }
 
     /**
      * Runs the poc binary and asserts that there are no security crashes that match the expected
      * process pattern.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param config a crash parser configuration
      */
-    public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
-            CrashUtils.Config config) throws Exception {
+    @Deprecated
+    public static void runPocAssertNoCrashes(
+            String pocName, ITestDevice device, TombstoneUtils.Config config) throws Exception {
         runPocAssertNoCrashes(pocName, device, null, config);
     }
 
     /**
      * Runs the poc binary and asserts that there are no security crashes that match the expected
      * process pattern, including arguments when running.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName a string path to poc from the /res folder
      * @param device device to be ran on
      * @param arguments input arguments for the poc
      * @param config a crash parser configuration
      */
-    public static void runPocAssertNoCrashes(String pocName, ITestDevice device, String arguments,
-            CrashUtils.Config config) throws Exception {
-        AdbUtils.runCommandLine("logcat -c", device);
-        AdbUtils.runPocNoOutput(pocName, device,
-                SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments);
-        assertNoCrashes(device, config);
+    @Deprecated
+    public static void runPocAssertNoCrashes(
+            String pocName, ITestDevice device, String arguments, TombstoneUtils.Config config)
+            throws Exception {
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(device, config)) {
+            AdbUtils.runPocNoOutput(pocName, device,
+                    SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments);
+        }
     }
 
     /**
-     * Runs the poc binary and asserts following 2 conditions.
-     *  1. There are no security crashes in the binary.
-     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in
+     * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability
+     * condition).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param binaryName name of the binary
      * @param arguments arguments for running the binary
      * @param device device to be run on
      */
-    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
-            ITestDevice device) throws Exception {
+    @Deprecated
+    public static void runPocAssertNoCrashesNotVulnerable(
+            String binaryName, String arguments, ITestDevice device) throws Exception {
         runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device, null);
     }
 
     /**
-     * Runs the poc binary and asserts following 2 conditions.
-     *  1. There are no security crashes in the binary.
-     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in
+     * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability
+     * condition).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param binaryName name of the binary
      * @param arguments arguments for running the binary
      * @param device device to be run on
-     * @param processPatternStrings a Pattern string to match the crash tombstone
-     *        process
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
      */
-    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
-            ITestDevice device, String processPatternStrings[]) throws Exception {
+    @Deprecated
+    public static void runPocAssertNoCrashesNotVulnerable(
+            String binaryName, String arguments, ITestDevice device, String processPatternStrings[])
+            throws Exception {
         runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device,
                 processPatternStrings);
     }
 
     /**
-     * Runs the poc binary and asserts following 2 conditions.
-     *  1. There are no security crashes in the binary.
-     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in
+     * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability
+     * condition).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param binaryName name of the binary
      * @param arguments arguments for running the binary
      * @param inputFiles files required as input
-     * @param inputFilesDestination destination directory to which input files are
-     *        pushed
+     * @param inputFilesDestination destination directory to which input files are pushed
      * @param device device to be run on
      */
-    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
-            String inputFiles[], String inputFilesDestination, ITestDevice device)
+    @Deprecated
+    public static void runPocAssertNoCrashesNotVulnerable(
+            String binaryName,
+            String arguments,
+            String inputFiles[],
+            String inputFilesDestination,
+            ITestDevice device)
             throws Exception {
         runPocAssertNoCrashesNotVulnerable(binaryName, arguments, inputFiles, inputFilesDestination,
                 device, null);
     }
 
     /**
-     * Runs the poc binary and asserts following 3 conditions.
-     *  1. There are no security crashes in the binary.
-     *  2. There are no security crashes that match the expected process pattern.
-     *  3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in
+     * the binary. 2. There are no security crashes that match the expected process pattern. 3. The
+     * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param binaryName name of the binary
      * @param arguments arguments for running the binary
      * @param inputFiles files required as input
-     * @param inputFilesDestination destination directory to which input files are
-     *        pushed
+     * @param inputFilesDestination destination directory to which input files are pushed
      * @param device device to be run on
-     * @param processPatternStrings a Pattern string to match the crash tombstone
-     *        process
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
      */
-    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
-            String inputFiles[], String inputFilesDestination, ITestDevice device,
-            String processPatternStrings[]) throws Exception {
+    @Deprecated
+    public static void runPocAssertNoCrashesNotVulnerable(
+            String binaryName,
+            String arguments,
+            String inputFiles[],
+            String inputFilesDestination,
+            ITestDevice device,
+            String processPatternStrings[])
+            throws Exception {
         runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null,
                 inputFiles, inputFilesDestination, device, processPatternStrings);
     }
 
     /**
-     * Runs the poc binary and asserts following 3 conditions.
-     *  1. There are no security crashes in the binary.
-     *  2. There are no security crashes that match the expected process pattern.
-     *  3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in
+     * the binary. 2. There are no security crashes that match the expected process pattern. 3. The
+     * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param binaryName name of the binary
      * @param arguments arguments for running the binary
      * @param envVars run the poc with environment variables
      * @param inputFiles files required as input
-     * @param inputFilesDestination destination directory to which input files are
-     *        pushed
+     * @param inputFilesDestination destination directory to which input files are pushed
      * @param device device to be run on
      * @param processPatternStrings a Pattern string (other than binary name) to match the crash
-     *        tombstone process
+     *     tombstone process
      */
+    @Deprecated
     public static void runPocAssertNoCrashesNotVulnerable(
-            String binaryName, String arguments, Map<String, String> envVars,
-            String inputFiles[], String inputFilesDestination, ITestDevice device,
-            String... processPatternStrings) throws Exception {
+            String binaryName,
+            String arguments,
+            Map<String, String> envVars,
+            String inputFiles[],
+            String inputFilesDestination,
+            ITestDevice device,
+            String... processPatternStrings)
+            throws Exception {
         pocConfig testConfig = new pocConfig(binaryName, device);
         testConfig.arguments = arguments;
         testConfig.envVars = envVars;
@@ -657,27 +696,28 @@
         String[] processPatternStringsWithSelf = new String[processPatternList.size()];
         processPatternList.toArray(processPatternStringsWithSelf);
         testConfig.config =
-                new CrashUtils.Config().setProcessPatterns(processPatternStringsWithSelf);
+                new TombstoneUtils.Config().setProcessPatterns(processPatternStringsWithSelf);
 
         runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 
     /**
-     * Runs the poc binary and asserts following 3 conditions.
-     *  1. There are no security crashes in the binary.
-     *  2. There are no security crashes that match the expected process pattern.
-     *  3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in
+     * the binary. 2. There are no security crashes that match the expected process pattern. 3. The
+     * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param testConfig test configuration
      */
+    @Deprecated
     public static void runPocAssertNoCrashesNotVulnerable(pocConfig testConfig) throws Exception {
         String[] inputFiles = null;
         if(!testConfig.inputFiles.isEmpty()) {
             inputFiles = testConfig.inputFiles.toArray(new String[testConfig.inputFiles.size()]);
             pushResources(inputFiles, testConfig.inputFilesDestination, testConfig.device);
         }
-        runCommandLine("logcat -c", testConfig.device);
-        try {
+        try (AutoCloseable a =
+                TombstoneUtils.withAssertNoSecurityCrashes(testConfig.device, testConfig.config)) {
             runPocAssertExitStatusNotVulnerable(testConfig.binaryName, testConfig.arguments,
                     testConfig.envVars, testConfig.device, TIMEOUT_SEC);
         } catch (IllegalArgumentException e) {
@@ -693,63 +733,6 @@
                 removeResources(inputFiles, testConfig.inputFilesDestination, testConfig.device);
             }
         }
-        if(testConfig.checkCrash) {
-            if (testConfig.config == null) {
-                testConfig.config = new CrashUtils.Config();
-            }
-            assertNoCrashes(testConfig.device, testConfig.config);
-        }
-    }
-
-    /**
-     * Dumps logcat and asserts that there are no security crashes that match the expected process.
-     * By default, checks min crash addresses
-     * pattern. Ensure that adb logcat -c is called beforehand.
-     * @param device device to be ran on
-     * @param processPatternStrings a Pattern string to match the crash tombstone process
-     */
-    public static void assertNoCrashes(ITestDevice device, String... processPatternStrings)
-            throws Exception {
-        assertNoCrashes(device, new CrashUtils.Config().setProcessPatterns(processPatternStrings));
-    }
-
-    /**
-     * Dumps logcat and asserts that there are no security crashes that match the expected process
-     * pattern. Ensure that adb logcat -c is called beforehand.
-     * @param device device to be ran on
-     * @param config a crash parser configuration
-     */
-    public static void assertNoCrashes(ITestDevice device,
-            CrashUtils.Config config) throws Exception {
-        String logcat = AdbUtils.runCommandLine("logcat -d *:S DEBUG:V", device);
-
-        JSONArray crashes = CrashUtils.addAllCrashes(logcat, new JSONArray());
-        JSONArray securityCrashes = CrashUtils.matchSecurityCrashes(crashes, config);
-
-        MetricsReportLog reportLog = SecurityTestCase.buildMetricsReportLog(device);
-        reportLog.addValue("all_crashes", crashes.toString(), ResultType.NEUTRAL, ResultUnit.NONE);
-        reportLog.addValue("security_crashes", securityCrashes.toString(),
-                ResultType.NEUTRAL, ResultUnit.NONE);
-        reportLog.submit();
-
-        if (securityCrashes.length() == 0) {
-            return; // no security crashes detected
-        }
-
-        StringBuilder error = new StringBuilder();
-        error.append("Security crash detected:\n");
-        error.append("Process patterns:");
-        for (Pattern pattern : config.getProcessPatterns()) {
-            error.append(String.format(" '%s'", pattern.toString()));
-        }
-        error.append("\nCrashes:\n");
-        for (int i = 0; i < crashes.length(); i++) {
-            try {
-                JSONObject crash = crashes.getJSONObject(i);
-                error.append(String.format("%s\n", crash));
-            } catch (JSONException e) {}
-        }
-        fail(error.toString());
     }
 
     public static void assumeHasNfc(ITestDevice device) throws DeviceNotAvailableException {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
index 5580acb..21d2456 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
@@ -21,6 +21,7 @@
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -36,9 +37,11 @@
     @AsbSecurityTest(cveBugId = 187957589)
     public void testPocBug_187957589() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.os.statsd"));
-        AdbUtils.runPoc("Bug-187957589", getDevice());
-        // Sleep to ensure statsd was able to process the injected event.
-        Thread.sleep(5_000);
-        AdbUtils.assertNoCrashes(getDevice(), "statsd");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("statsd");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runPoc("Bug-187957589", getDevice());
+            // Sleep to ensure statsd was able to process the injected event.
+            Thread.sleep(5_000);
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java
new file mode 100644
index 0000000..4b8389e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java
@@ -0,0 +1,45 @@
+/*
+ * 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.security.cts;
+
+import static org.junit.Assert.*;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Bug_248251018 extends NonRootSecurityTestCase {
+
+    @Test
+    @AsbSecurityTest(cveBugId = 248251018)
+    public void testEmergencyInfo_cannotInteractAcrossUsers() throws Exception {
+        String packageList =
+                getDevice()
+                        .executeShellV2Command("pm list package com.android.emergency")
+                        .getStdout();
+        if (!packageList.isEmpty()) {
+            String result =
+                    getDevice()
+                            .executeShellV2Command("dumpsys package com.android.emergency")
+                            .getStdout();
+            assertFalse(result.contains("android.permission.INTERACT_ACROSS_USERS_FULL"));
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
index a4b8506..29601f9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
@@ -20,8 +20,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -40,8 +40,8 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.conscrypt"));
         String binaryName = "CVE-2016-2182";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
-        testConfig.config.checkMinAddress(false);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setIgnoreLowFaultAddress(false);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
index d58b3c3..3e0760d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -37,11 +37,11 @@
     @Test
     public void testPocCVE_2018_9537() throws Exception {
         String binaryName = "CVE-2018-9537";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV, TombstoneUtils.Signals.SIGBUS, TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
         // example of check crash to skip:
         // Abort message: 'frameworks/av/media/extractors/mkv/MatroskaExtractor.cpp:548 CHECK(mCluster) failed.'
-        testConfig.config = new CrashUtils.Config()
+        testConfig.config = new TombstoneUtils.Config()
                 .setProcessPatterns(binaryName)
                 .appendAbortMessageExcludes("CHECK\\(.*?\\)");
         testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
index 1db523b..0c63f53 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -36,9 +36,9 @@
     @Test
     public void testPocCVE_2018_9549() throws Exception {
         String binaryName = "CVE-2018-9549";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.config
                 .setAbortMessageIncludes(AdbUtils.escapeRegexSpecialChars("ubsan: mul-overflow"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index fdf85b7..0e0e2cf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -19,9 +19,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,10 +44,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String[] signals = {CrashUtils.SIGABRT};
+        String[] signals = {TombstoneUtils.Signals.SIGABRT};
         String binaryName = "CVE-2018-9558";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t2t_handle_tlv_detect_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
index 1b4a4a7..926bd8c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -43,10 +43,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2019-2012";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(
                         new BacktraceFilterPattern("libnfc-nci", "rw_t3t_update_block"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
index b54d767..0327e038 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -37,9 +37,9 @@
     public void testPocCVE_2019_2014() throws Exception {
         pocPusher.only64();
         String binaryName = "CVE-2019-2014";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
index bf46c60..388ac4c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -43,10 +43,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2019-2015";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t3t_act_handle_check_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
index b1a1b54..9a36d861 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -43,10 +43,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         String binaryName = "CVE-2019-2017";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t2t_handle_tlv_detect_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
index 9ea3846..baf4c63 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -43,15 +43,15 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2019-2020";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "llcp_dlc_proc_rx_pdu"));
         testConfig.config
                 .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
-        testConfig.config.checkMinAddress(false);
+        testConfig.config.setIgnoreLowFaultAddress(false);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
index ad289bf..5eafc33 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -36,9 +36,9 @@
     @Test
     public void testPocCVE_2019_2027() throws Exception {
         String binaryName = "CVE-2019-2027";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.config
                 .setAbortMessageIncludes(AdbUtils.escapeRegexSpecialChars("ubsan: mul-overflow"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
index dc94186..2476923 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -43,10 +43,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         String binaryName = "CVE-2019-2031";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t3t_act_handle_check_ndef_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
index 3d054f0..cffa74a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -40,9 +40,9 @@
         pocPusher.only32();
         String binaryName = "CVE-2020-0034";
         String inputFiles[] = {"cve_2020_0034.ivf"};
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.inputFiles = Arrays.asList(inputFiles);
         testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
index 83e6b7a..85cd75c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
@@ -38,7 +38,6 @@
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0072", getDevice());
-        testConfig.checkCrash = false;
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index 8f285d0..cbf3ef1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,9 +44,9 @@
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
         String binaryName = "CVE-2020-0073";
-        String[] signals = {CrashUtils.SIGABRT};
+        String[] signals = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t2t_handle_tlv_detect_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
index a6609a4..f5189fa 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,10 +44,10 @@
         pocPusher.only32();
         String binaryName = "CVE-2020-0241";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice",
                         "android::NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener"));
-        String signals[] = {CrashUtils.SIGABRT};
+        String[] signals = {TombstoneUtils.Signals.SIGABRT};
         testConfig.config.setSignals(signals);
         testConfig.config.setAbortMessageIncludes(
                 AdbUtils.escapeRegexSpecialChars("Pure virtual function called"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
index 59c7370..f9cd2e2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -36,8 +36,8 @@
     @AsbSecurityTest(cveBugId = 151644303)
     public void testPocCVE_2020_0243() throws Exception {
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0243", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("mediaserver");
-        testConfig.config.checkMinAddress(false);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("mediaserver");
+        testConfig.config.setIgnoreLowFaultAddress(false);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
index 524f2d6..6eb6bff 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
@@ -20,9 +20,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,9 +44,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0381";
         String inputFiles[] = {"cve_2020_0381.xmf", "cve_2020_0381.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_ptbl"));
         testConfig.config.setSignals(signals);
         testConfig.arguments =
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
index 5bdf017..f73d812 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
@@ -20,9 +20,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,9 +44,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0383";
         String inputFiles[] = {"cve_2020_0383.xmf", "cve_2020_0383.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins"));
         testConfig.config.setSignals(signals);
         testConfig.arguments =
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
index 000e970..42505ca 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
@@ -20,9 +20,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,9 +44,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0384";
         String inputFiles[] = {"cve_2020_0384.xmf", "cve_2020_0384.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(
                         new BacktraceFilterPattern("libmidiextractor", "Convert_art"));
         testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
index b9ba127..6bbc89e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
@@ -20,9 +20,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -44,9 +44,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0385";
         String inputFiles[] = {"cve_2020_0385.xmf", "cve_2020_0385.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins"));
         testConfig.config.setSignals(signals);
         testConfig.arguments =
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
index 15cdab5..4c9908f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -36,8 +36,8 @@
     @AsbSecurityTest(cveBugId = 170732441)
     public void testPocCVE_2021_0330() throws Exception {
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0330", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("storaged");
-        testConfig.config.checkMinAddress(false);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("storaged");
+        testConfig.config.setIgnoreLowFaultAddress(false);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index 71ce363..2190538 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -43,10 +43,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2021-0430";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_mfc_handle_read_op"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
index 90e65c2..77d178a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
@@ -37,7 +37,6 @@
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0473", getDevice());
-        testConfig.checkCrash = false;
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
index 05aa43e..c96b27a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -30,10 +30,12 @@
     /**
      * b/173720767
      * Vulnerability Behavior: EXIT_VULNERABLE (113)
+     * Vulnerable library    : libmedia
+     * Is Play managed       : No
      */
     @Test
     @AsbSecurityTest(cveBugId = 173720767)
     public void testPocCVE_2021_0484() throws Exception {
-        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0484", null, getDevice());
+       AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-0484", getDevice(), 300);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0487.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0487.java
new file mode 100644
index 0000000..45a1905
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0487.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0487 extends NonRootSecurityTestCase {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0487";
+
+    /**
+     * b/174046397
+     * Vulnerable app    : CalendarProvider.apk
+     * Vulnerable module : com.android.providers.calendar
+     * Is Play managed   : No
+     */
+    @AsbSecurityTest(cveBugId = 174046397)
+    @Test
+    public void testPocCVE_2021_0487() {
+        ITestDevice device = null;
+        try {
+            device = getDevice();
+            /* Wake up the screen */
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+            /* Install the application */
+            installPackage("CVE-2021-0487.apk");
+
+            AdbUtils.runCommandLine(
+                    "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW", device);
+            runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+        } catch (Exception e) {
+            assumeNoException(e);
+        } finally {
+            try {
+                // return to home screen
+                AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+            } catch (Exception e) {
+                // ignore exceptions here
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
index 41455a4..d798166 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
@@ -21,6 +21,7 @@
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -35,13 +36,14 @@
          */
         AdbUtils.pushResource(
                 "/" + mediaFileName, "/sdcard/" + mediaFileName, getDevice());
-        AdbUtils.runCommandLine("logcat -c", getDevice());
-        AdbUtils.runCommandLine(
-                "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/"
-                    + mediaFileName, getDevice());
-        Thread.sleep(4000); // Delay to run the media file and capture output in logcat
-        AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice());
-        AdbUtils.assertNoCrashes(getDevice(), "mediaserver");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("mediaserver");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runCommandLine(
+                    "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/"
+                        + mediaFileName, getDevice());
+            Thread.sleep(4000); // Delay to run the media file and capture output in logcat
+            AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice());
+        }
     }
 
     @Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
deleted file mode 100644
index 2e1ddda..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (C) 2022 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.AppModeFull;
-import android.platform.test.annotations.AsbSecurityTest;
-
-import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0642 extends NonRootSecurityTestCase {
-    static final String TEST_APP = "CVE-2021-0642.apk";
-    static final String TEST_PKG = "android.security.cts.cve_2021_0642";
-    static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
-
-    @Before
-    public void setUp() throws Exception {
-        ITestDevice device = getDevice();
-        AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
-        AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
-        AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-        uninstallPackage(device, TEST_PKG);
-    }
-
-    /**
-     * b/185126149
-     */
-    @AppModeFull
-    @AsbSecurityTest(cveBugId = 185126149)
-    @Test
-    public void testPocCVE_2021_0642() throws Exception {
-        installPackage(TEST_APP);
-        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_0642"));
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
index 5139425..095fdd3 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
@@ -19,8 +19,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -38,9 +38,9 @@
     public void testPocCVE_2021_0919() throws Exception {
         pocPusher.only32();
         String binaryName = "CVE-2021-0919";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
index 94f3b97..d4f6a45 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
@@ -57,7 +57,7 @@
         getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
 
         //run the test
-        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "test"));
+        runDeviceTests(TEST_PKG, TEST_CLASS, "test");
         CLog.i("testRunDeviceTest() end");
     }
 
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
index b3c9717..5802549 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -37,9 +37,9 @@
         pocPusher.only64();
         String binaryName = "CVE-2021-0925";
         String inputFiles[] = {"cve_2021_0925"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
index eddde21..68eabde 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
@@ -18,8 +18,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
@@ -41,9 +41,9 @@
         AdbUtils.assumeHasNfc(device);
         assumeIsSupportedNfcDevice(device);
         String binaryName = "CVE-2021-0956";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, device);
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
new file mode 100644
index 0000000..90d8196
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0963 extends StsExtraBusinessLogicHostTestBase {
+    static final String TEST_PKG = "android.security.cts.CVE_2021_0963";
+
+    /**
+     * b/199754277
+     * Vulnerable app    : KeyChain.apk
+     * Vulnerable module : com.android.keychain
+     * Is Play managed   : No
+     */
+    @AsbSecurityTest(cveBugId = 199754277)
+    @Test
+    public void testPocCVE_2021_0963() {
+        try {
+            ITestDevice device = getDevice();
+
+            /* Wake up the device */
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+            /* Install the application */
+            installPackage("CVE-2021-0963.apk");
+
+            /*
+             * Set device as owner. After the test is completed, this change is reverted in the
+             * DeviceTest.java's tearDown() method by calling clearDeviceOwnerApp() on an instance
+             * of DevicePolicyManager.
+             */
+            AdbUtils.runCommandLine("dpm set-device-owner --user 0 '" + TEST_PKG + "/" + TEST_PKG
+                    + ".PocDeviceAdminReceiver" + "'", device);
+
+            /* Run the device test "testOverlayButtonPresence" */
+            runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
index 3e8a9bd..272d2e7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
@@ -19,6 +19,7 @@
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
@@ -40,7 +41,8 @@
         String packageName = "android.security.cts.CVE_2021_30351";
         ITestDevice device = getDevice();
 
-        try {
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("media.codec");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
             /* Push the app to /data/local/tmp */
             pocPusher.appendBitness(false);
             pocPusher.pushFile(apkName, appPath);
@@ -61,11 +63,6 @@
         } finally {
             /* Un-install the app after the test */
             AdbUtils.runCommandLine("pm uninstall " + packageName, device);
-
-            /* Check if media.codec has crashed thereby indicating the presence */
-            /* of the vulnerability */
-            String logcat = AdbUtils.runCommandLine("logcat -d", device);
-            AdbUtils.assertNoCrashes(getDevice(), "media.codec");
         }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
index aaaa502..d88cc83 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -42,10 +42,10 @@
     public void testPocCVE_2021_39623() throws Exception {
         String binaryName = "CVE-2021-39623";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName)
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName)
                 .setBacktraceIncludes(new BacktraceFilterPattern("libstagefright",
                         "android::SimpleDecodingSource::doRead"));
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         testConfig.config.setSignals(signals);
         testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
         String inputFiles[] = {"cve_2021_39623.ogg"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
index 29de04e..930138f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -42,10 +42,10 @@
     @Test
     public void testPocCVE_2021_39664() throws Exception {
         String inputFiles[] = {"cve_2021_39664"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2021-39664";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libandroidfw",
                         "android::LoadedPackage::Load"));
         testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
index 79e3d0f..ef37133 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -40,10 +40,10 @@
     @AsbSecurityTest(cveBugId = 204077881)
     @Test
     public void testPocCVE_2021_39665() throws Exception {
-        String[] signals = {CrashUtils.SIGSEGV};
+        String[] signals = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2021-39665";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice",
                         "android::AAVCAssembler::checkSpsUpdated"));
         testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
index 0053fc6..9c5887a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
@@ -18,9 +18,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -42,12 +42,12 @@
     public void testPocCVE_2021_39804() throws Exception {
         String inputFiles[] = {"cve_2021_39804.heif"};
         String binaryName = "CVE-2021-39804";
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
         testConfig.config =
-                new CrashUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes(
+                new TombstoneUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes(
                         new BacktraceFilterPattern("libheif", "android::HeifDecoderImpl::reinit"));
-        testConfig.config.checkMinAddress(false);
+        testConfig.config.setIgnoreLowFaultAddress(false);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
index 1aeaa1d..bb717d2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
@@ -20,9 +20,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -45,11 +45,11 @@
             AdbUtils.assumeHasNfc(getDevice());
             assumeIsSupportedNfcDevice(getDevice());
             pocPusher.only64();
-            String signals[] = {CrashUtils.SIGSEGV};
+            String signals[] = {TombstoneUtils.Signals.SIGSEGV};
             String binaryName = "CVE-2022-20131";
             AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
             testConfig.config =
-                    new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+                    new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                             .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                                     "nfc_ncif_proc_ee_discover_req"));
             testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
index 5b1d38c..7157a13 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
@@ -20,9 +20,9 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -45,11 +45,11 @@
             AdbUtils.assumeHasNfc(getDevice());
             assumeIsSupportedNfcDevice(getDevice());
             pocPusher.only64();
-            String signals[] = { CrashUtils.SIGSEGV };
+            String signals[] = { TombstoneUtils.Signals.SIGSEGV };
             String binaryName = "CVE-2022-20147";
             AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName,
                     getDevice());
-            testConfig.config = new CrashUtils.Config()
+            testConfig.config = new TombstoneUtils.Config()
                     .setProcessPatterns(Pattern.compile(binaryName))
                     .setBacktraceIncludes(new BacktraceFilterPattern(
                             "libnfc-nci", "nfa_dm_check_set_config"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
index 3d31cee..98befd4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
@@ -16,18 +16,18 @@
 
 package android.security.cts;
 
+import static com.android.sts.common.SystemUtil.withSetting;
+
 import static org.junit.Assume.assumeNoException;
 
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class CVE_2022_20197 extends NonRootSecurityTestCase {
     private static final String TEST_PKG = "android.security.cts.CVE_2022_20197";
@@ -35,37 +35,11 @@
     @AsbSecurityTest(cveBugId = 208279300)
     @Test
     public void testPocCVE_2022_20197() {
-        ITestDevice device = null;
-        boolean isPolicyPresent = true;
-        boolean isHiddenApiEnabled = true;
-        String status = "";
-        try {
-            device = getDevice();
+        try (AutoCloseable a = withSetting(getDevice(), "global", "hidden_api_policy", "1")) {
             installPackage("CVE-2022-20197.apk");
-
-            status = AdbUtils.runCommandLine("settings get global hidden_api_policy", device);
-            if (status.toLowerCase().contains("null")) {
-                isPolicyPresent = false;
-            } else if (!status.toLowerCase().contains("1")) {
-                isHiddenApiEnabled = false;
-            }
-            if (!isPolicyPresent || !isHiddenApiEnabled) {
-                AdbUtils.runCommandLine("settings put global hidden_api_policy 1", device);
-            }
             runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testParcel");
         } catch (Exception e) {
             assumeNoException(e);
-        } finally {
-            try {
-                if (!isPolicyPresent) {
-                    AdbUtils.runCommandLine("settings delete global hidden_api_policy", device);
-                } else if (!isHiddenApiEnabled) {
-                    AdbUtils.runCommandLine("settings put global hidden_api_policy " + status,
-                            device);
-                }
-            } catch (Exception e) {
-                // ignore all exceptions.
-            }
         }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
new file mode 100644
index 0000000..62d0f16
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20475 extends NonRootSecurityTestCase {
+
+    /**
+     * b/240663194
+     * Vulnerable module : services.jar
+     * Is Play Managed   : No
+     */
+    @AsbSecurityTest(cveBugId = 240663194)
+    @Test
+    public void testPocCVE_2022_20475() {
+        try {
+            final String testPkg = "android.security.cts.CVE_2022_20475_test";
+            ITestDevice device = getDevice();
+
+            // Install the test and target apps
+            installPackage("CVE-2022-20475-test.apk");
+            installPackage("CVE-2022-20475-target.apk");
+
+            // Wake up the device
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+            // Run the test "testCVE_2022_20475"
+            runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2022_20475");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20501.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20501.java
new file mode 100644
index 0000000..067a011a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20501.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20501 extends NonRootSecurityTestCase {
+    private ITestDevice mDevice;
+
+    /**
+     * b/246933359
+     * Vulnerable app       : Telecom.apk
+     * Vulnerable module    : com.android.server.telecom
+     * Is Play managed      : No
+     */
+    @AsbSecurityTest(cveBugId = 246933359)
+    @Test
+    public void testPocCVE_2022_20501() {
+        try {
+            final String testPkg = "android.security.cts.CVE_2022_20501";
+            mDevice = getDevice();
+            installPackage("CVE-2022-20501.apk");
+
+            // Wake up the device
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP && wm dismiss-keyguard",
+                    mDevice);
+
+            AdbUtils.runCommandLine(
+                    "pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW", mDevice);
+            runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        try {
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", mDevice);
+        } catch (Exception ignored) {
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
index a0200f1..cc3fd42 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
@@ -20,6 +20,7 @@
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -39,12 +40,13 @@
          */
         safeReboot();
         AdbUtils.pushResource("/cve_2022_22082.dsf", "/sdcard/cve_2022_22082.dsf", getDevice());
-        AdbUtils.runCommandLine("logcat -c", getDevice());
-        AdbUtils.runCommandLine(
-                "am start -a android.intent.action.VIEW -t audio/dsf -d"
-                        + " file:///sdcard/cve_2022_22082.dsf",
-                getDevice());
-        Thread.sleep(10000);
-        AdbUtils.assertNoCrashes(getDevice(), "media.extractor");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("media.extractor");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runCommandLine(
+                    "am start -a android.intent.action.VIEW -t audio/dsf -d"
+                            + " file:///sdcard/cve_2022_22082.dsf",
+                    getDevice());
+            Thread.sleep(10000);
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java
new file mode 100644
index 0000000..659c002
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.SystemUtil;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_20918 extends NonRootSecurityTestCase {
+
+    // b/243794108
+    // Vulnerable library : services.jar
+    // Vulnerable module  : Not applicable
+    // Is Play Managed    : No
+    @AsbSecurityTest(cveBugId = 243794108)
+    @Test
+    public void testPocCVE_2023_20918() {
+        try {
+            final String testPkg = "android.security.cts.CVE_2023_20918_test";
+
+            // Install the test and attacker apps
+            installPackage("CVE-2023-20918-test.apk");
+            installPackage("CVE-2023-20918-attacker.apk");
+
+            // Allow access to hidden api "ActivityOptions#setPendingIntentLaunchFlags()"
+            try (AutoCloseable closable =
+                    SystemUtil.withSetting(getDevice(), "global", "hidden_api_policy", "1")) {
+                // Run the test "testCVE_2023_20918"
+                runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2023_20918");
+            }
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
index 4d406b7..ca50ea8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
@@ -21,6 +21,7 @@
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -35,13 +36,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 36075131)
     public void testPocCVE_2017_0859() throws Exception {
-        AdbUtils.runCommandLine("logcat -c", getDevice());
         AdbUtils.pushResource("/cve_2017_0859.mp4", "/sdcard/cve_2017_0859.mp4", getDevice());
-        AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " +
-                                    "-d file:///sdcard/cve_2017_0859.mp4" +
-                                    " -t audio/amr", getDevice());
-        // Wait for intent to be processed before checking logcat
-        Thread.sleep(5000);
-        AdbUtils.assertNoCrashes(getDevice(), "mediaserver");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("mediaserver");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " +
+                                        "-d file:///sdcard/cve_2017_0859.mp4" +
+                                        " -t audio/amr", getDevice());
+            // Wait for intent to be processed before checking logcat
+            Thread.sleep(5000);
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
index 3f2d1d0..32d8251 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
@@ -17,10 +17,12 @@
 package android.security.cts;
 
 import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
@@ -36,13 +38,11 @@
     @AsbSecurityTest(cveBugId = 148817146)
     public void testPocCVE_2020_3635() throws Exception {
         String isApplicable = AdbUtils.runCommandLine("service list", getDevice());
-        if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) {
-            AdbUtils.runCommandLine("logcat -c", getDevice());
+        assumeTrue(isApplicable.contains("com.qualcomm.qti.IPerfManager"));
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("perfservice");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
             AdbUtils.runCommandLine(
                     "service call vendor.perfservice 4 i32 1 i64 4702394920265069920", getDevice());
-            String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
-            assertNotMatchesMultiLine(
-                    "Fatal signal 11 \\(SIGSEGV\\).*?>>> /system/bin/perfservice <<<", logcatOut);
         }
     }
 
@@ -79,11 +79,11 @@
     @AsbSecurityTest(cveBugId = 152310294)
     public void testPocCVE_2020_3676() throws Exception {
         String isApplicable = AdbUtils.runCommandLine("service list", getDevice());
-        if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) {
-            AdbUtils.runCommandLine("logcat -c", getDevice());
+        assumeTrue(isApplicable.contains("com.qualcomm.qti.IPerfManager"));
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("perfservice");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
             AdbUtils.runCommandLine(
                     "service call vendor.perfservice 4 i32 2442302356 i64 -2", getDevice());
-            AdbUtils.assertNoCrashes(getDevice(), "perfservice");
         }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index c2956f3..7f10976 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -23,8 +23,8 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 
-import com.android.compatibility.common.util.CrashUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import junit.framework.Assert;
@@ -124,10 +124,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 156997193)
     public void testPocCVE_2020_0409() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2020-0409";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -139,10 +143,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 161894517)
     public void testPocCVE_2020_0421() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2020-0421";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -237,7 +245,11 @@
     @Test
     @AsbSecurityTest(cveBugId = 74122779)
     public void testPocCVE_2018_9428() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2018-9428", getDevice());
     }
 
@@ -248,9 +260,13 @@
     @Test
     @AsbSecurityTest(cveBugId = 64340921)
     public void testPocCVE_2017_0837() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2017-0837", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver");
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("audioserver");
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -265,9 +281,13 @@
     @AsbSecurityTest(cveBugId = 62151041)
     public void testPocCVE_2018_9466_CVE_2017_9047() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9047";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -279,9 +299,13 @@
     @AsbSecurityTest(cveBugId = 62151041)
     public void testPocCVE_2018_9466_CVE_2017_9048() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9048";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -294,9 +318,13 @@
     public void testPocCVE_2018_9466_CVE_2017_9049() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9049";
         String inputFiles[] = {"cve_2018_9466_cve_2017_9049.xml"};
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -312,9 +340,13 @@
     public void testPocCVE_2018_9466_CVE_2017_9050() throws Exception {
         String binaryName = "CVE-2018-9466-CVE-2017-9049";
         String inputFiles[] = {"cve_2018_9466_cve_2017_9050.xml"};
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -331,9 +363,13 @@
     public void testPocCVE_2015_3873() throws Exception {
         String inputFiles[] = {"cve_2015_3873.mp4"};
         String binaryName = "CVE-2015-3873";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -476,9 +512,13 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media.swcodec"));
         String inputFiles[] = {"cve_2020_0451.aac"};
         String binaryName = "CVE-2020-0451";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -526,10 +566,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 120426980)
     public void testPocCVE_2019_9362() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2019-9362";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -543,9 +587,13 @@
     public void testPocCVE_2019_9308() throws Exception {
         String inputFiles[] = {"cve_2019_9308.mp4"};
         String binaryName = "CVE-2019-9308";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -560,10 +608,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 112662995)
     public void testPocCVE_2019_9357() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2019-9357";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/Android.bp
similarity index 93%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
rename to hostsidetests/securitybulletin/test-apps/CVE-2021-0487/Android.bp
index 50acd29..14d6baf 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/Android.bp
@@ -20,11 +20,13 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2021-0487",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/AndroidManifest.xml
new file mode 100644
index 0000000..5c5934c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_0487">
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <application>
+        <service android:name=".PocService" />
+    </application>
+   <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2021_0487" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/res/values/integers.xml
similarity index 64%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0487/res/values/integers.xml
index 7460b96..de5f253 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/res/values/integers.xml
@@ -14,13 +14,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
+
+<resources>
+    <integer name="assumptionFailure">-1</integer>
+    <integer name="pass">0</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/res/values/strings.xml
new file mode 100644
index 0000000..4d4098d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="broadcastReceiverCalendar">CalendarProviderBroadcastReceiver</string>
+    <string name="calendarClsName">%1$s.CalendarDebugActivity</string>
+    <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+    <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+    <string name="dumpsysActivity">dumpsys activity %1$s</string>
+    <string name="errorMessage">Device is vulnerable to b/174046397 hence any app with
+    "SYSTEM_ALERT_WINDOW" can overlay the CalendarDebugActivity screen</string>
+    <string name="messageKey">message</string>
+    <string name="overlayButtonText">OverlayButton</string>
+    <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+    <string name="resultKey">result</string>
+    <string name="resumedTrue">mResumed=true</string>
+    <string name="sharedPreferences">CVE_2021_0487_prefs</string>
+    <string name="vulActivityNotRunningError">The CalendarDebugActivity is not currently
+    running on the device</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/src/android/security/cts/CVE_2021_0487/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/src/android/security/cts/CVE_2021_0487/DeviceTest.java
new file mode 100644
index 0000000..0a3e65d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/src/android/security/cts/CVE_2021_0487/DeviceTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 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_0487;
+
+import static android.provider.CalendarContract.ACTION_EVENT_REMINDER;
+import static android.provider.CalendarContract.CONTENT_URI;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final int LAUNCH_TIMEOUT_MS = 10000;
+    private String mVulnerablePkgName = "";
+    private Context mContext = getApplicationContext();
+    Resources mResources;
+
+    private void startOverlayService() {
+        Intent intent = new Intent(mContext, PocService.class);
+        assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg),
+                Settings.canDrawOverlays(mContext));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startService(intent);
+    }
+
+    private void startVulnerableActivity() {
+        Intent intent = new Intent(ACTION_EVENT_REMINDER);
+        Intent vulnPkgNameIntent = new Intent();
+        intent.setData(CONTENT_URI);
+        PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> ris = pm.queryBroadcastReceivers(intent, 0);
+        for (ResolveInfo ri : ris) {
+            if (ri.activityInfo.name
+                    .contains(mContext.getString(R.string.broadcastReceiverCalendar))) {
+                mVulnerablePkgName = ri.activityInfo.packageName;
+            }
+        }
+        vulnPkgNameIntent.setClassName(mVulnerablePkgName,
+                mContext.getString(R.string.calendarClsName, mVulnerablePkgName));
+        vulnPkgNameIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(vulnPkgNameIntent);
+    }
+
+    @Test
+    public void testOverlayButtonPresence() {
+        try {
+            UiDevice device = UiDevice.getInstance(getInstrumentation());
+
+            /* Go to home screen */
+            device.pressHome();
+
+            /* Start the overlay service */
+            startOverlayService();
+            mResources = mContext.getResources();
+
+            SharedPreferences sharedPrefs = mContext.getSharedPreferences(
+                    mResources.getString(R.string.sharedPreferences), Context.MODE_APPEND);
+            Semaphore preferenceChanged = new Semaphore(0);
+            OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+                @Override
+                public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+                        String key) {
+                    if (key.equals(mResources.getString(R.string.resultKey))) {
+                        preferenceChanged.release();
+                    }
+                }
+            };
+            sharedPrefs.registerOnSharedPreferenceChangeListener(listener);
+
+            /* Wait for the overlay service to set some result in shared preferences */
+            assumeTrue(preferenceChanged.tryAcquire(LAUNCH_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+            int result = sharedPrefs.getInt(mResources.getString(R.string.resultKey),
+                    mResources.getInteger(R.integer.assumptionFailure));
+            String message = sharedPrefs.getString(mResources.getString(R.string.messageKey),
+                    mResources.getString(R.string.defaultSemaphoreMsg));
+            assumeTrue(message, result != mResources.getInteger(R.integer.assumptionFailure));
+
+            /* Wait for the overlay window */
+            Pattern overlayTextPattern = Pattern.compile(
+                    mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+            assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+                    device.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS));
+
+            /* Start the vulnerable activity */
+            startVulnerableActivity();
+
+            /* Wait until the object of overlay window is gone */
+            boolean overlayDisallowed =
+                    device.wait(Until.gone(By.pkg(mContext.getPackageName())), LAUNCH_TIMEOUT_MS);
+
+            /* Check if the currently running activity is the vulnerable activity */
+            String activityDump = device.executeShellCommand(
+                    mContext.getString(R.string.dumpsysActivity, mVulnerablePkgName));
+            Pattern activityPattern = Pattern.compile(mContext.getString(R.string.resumedTrue),
+                    Pattern.CASE_INSENSITIVE);
+            assumeTrue(mContext.getString(R.string.vulActivityNotRunningError),
+                    activityPattern.matcher(activityDump).find());
+
+            /* Failing the test as fix is not present */
+            assertTrue(mContext.getString(R.string.errorMessage), overlayDisallowed);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/src/android/security/cts/CVE_2021_0487/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/src/android/security/cts/CVE_2021_0487/PocService.java
new file mode 100644
index 0000000..1a8cd0f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0487/src/android/security/cts/CVE_2021_0487/PocService.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2022 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_0487;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import androidx.annotation.IntegerRes;
+
+public class PocService extends Service {
+    private Button mButton;
+    private WindowManager mWindowManager;
+    private WindowManager.LayoutParams mLayoutParams;
+
+    int getInteger(@IntegerRes int resId) {
+        return getResources().getInteger(resId);
+    }
+
+    private static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    private static int getScreenHeight() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        try {
+            mWindowManager = getSystemService(WindowManager.class);
+            mLayoutParams = new WindowManager.LayoutParams();
+            mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+            mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLayoutParams.format = PixelFormat.OPAQUE;
+            mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+            mLayoutParams.width = getScreenWidth();
+            mLayoutParams.height = getScreenHeight();
+            mLayoutParams.x = getScreenWidth() / 2;
+            mLayoutParams.y = getScreenHeight() / 2;
+        } catch (Exception e) {
+            sendTestResult(getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        try {
+            showFloatingWindow();
+            sendTestResult(getInteger(R.integer.pass), "");
+        } catch (Exception e) {
+            sendTestResult(getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        try {
+            mWindowManager.removeView(mButton);
+            super.onDestroy();
+        } catch (Exception e) {
+            // ignore the exception
+        }
+    }
+
+    private void showFloatingWindow() {
+        mButton = new Button(this);
+        mButton.setText(getString(R.string.overlayButtonText));
+        mWindowManager.addView(mButton, mLayoutParams);
+        mButton.setTag(mButton.getVisibility());
+    }
+
+    private void sendTestResult(int result, String message) {
+        try {
+            SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
+                    Context.MODE_PRIVATE);
+            SharedPreferences.Editor edit = sh.edit();
+            edit.putInt(getString(R.string.resultKey), result);
+            edit.putString(getString(R.string.messageKey), message);
+            edit.commit();
+        } catch (Exception e) {
+            // ignore the exception
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
deleted file mode 100644
index fadda57..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2022 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.security.cts.cve_2021_0642"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
-    <application
-        android:allowBackup="true"
-        android:label="CVE-2021-0642"
-        android:supportsRtl="true">
-
-        <activity
-            android:name=".PocActivity"
-            android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
-                <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_0642" />
-</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
deleted file mode 100644
index 8fc235b..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 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_0642;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeNoException;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.telephony.TelephonyManager;
-
-import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import java.util.List;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceTest {
-    static final String APP_TITLE = "CVE-2021-0642";
-    static final String PACKAGE_NAME = "com.android.phone";
-    static final int LAUNCH_TIMEOUT_MS = 20000;
-
-    @Test
-    public void testCVE_2021_0642() {
-        UiDevice device = UiDevice.getInstance(getInstrumentation());
-        Context context = getApplicationContext();
-        assertThat(context, notNullValue());
-        PackageManager packageManager = context.getPackageManager();
-        assertThat(packageManager, notNullValue());
-        assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
-        final Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        try {
-            context.startActivity(intent);
-        } catch (ActivityNotFoundException e) {
-            assumeNoException(e);
-        }
-
-        // Check if "com.android.phone" exists on the system
-        try {
-            packageManager.getPackageUid(PACKAGE_NAME, 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            assumeNoException(e);
-        }
-
-        // Wait for activity (which is part of package "com.android.phone") that
-        // handles ACTION_CONFIGURE_VOICEMAIL to get launched
-        boolean isVoicemailVisible =
-                device.wait(Until.hasObject(By.pkg(PACKAGE_NAME)), LAUNCH_TIMEOUT_MS);
-
-        // To check if PocActivity was launched
-        BySelector selector = By.enabled(true);
-        List<UiObject2> objects = device.findObjects(selector);
-        boolean isPocActivityVisible = false;
-        for (UiObject2 o : objects) {
-            String visibleText = o.getText();
-            if ((visibleText != null) && (visibleText.equalsIgnoreCase(APP_TITLE))) {
-                isPocActivityVisible = true;
-                break;
-            }
-        }
-        device.pressHome();
-
-        assumeTrue(isVoicemailVisible || isPocActivityVisible);
-
-        String outputMsg = "Device is vulnerable to b/185126149 "
-                + "hence sensitive Iccid could be sniffed by intercepting "
-                + "ACTION_CONFIGURE_VOICEMAIL implicit intent";
-        assertTrue(outputMsg, ((isVoicemailVisible) && (!isPocActivityVisible)));
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java
index 167a849..3b19485 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java
@@ -11,8 +11,6 @@
 
 import java.io.File;
 
-import static org.junit.Assume.assumeNoException;
-
 public class Trigger {
     private static final String TAG = "TAG_2021_0921.Trigger";
     private Context mContext;
@@ -26,8 +24,19 @@
       return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
     }
 
+    private static boolean isWear(Context context) {
+      PackageManager pm = context.getPackageManager();
+      return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
+
+    private static boolean isTv(Context context) {
+      PackageManager pm = context.getPackageManager();
+      return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION);
+    }
+
     public void accountSettings() {
         Log.d(TAG, "accountSettings() start");
+        String exitMessage = "accountSettings() end";
 
         //replaces intent.setAction(Intent.ACTION_REBOOT) in original Poc
         Intent arbitraryIntent = new Intent(mContext, TestActivity.class);
@@ -36,8 +45,19 @@
         Authenticator.mIntent = arbitraryIntent;
 
         Intent intent = new Intent();
-        String pkg = isCar(mContext) ? "com.android.car.settings" : "com.android.settings";
-        intent.setComponent(new ComponentName(pkg, pkg + ".accounts.AddAccountSettings"));
+        String pkg = "com.android.settings";
+        if (isCar(mContext)) {
+            pkg = "com.android.car.settings";
+            intent.setComponent(new ComponentName(pkg, pkg + ".accounts.AddAccountActivity"));
+        } else if (isTv(mContext)) {
+            pkg = "com.android.tv.settings";
+            intent.setComponent(new ComponentName(pkg, pkg + ".accounts.AddAccountWithTypeActivity"));
+        } else if (isWear(mContext)) {
+            pkg = "com.google.android.clockwork.home";
+            intent.setComponent(new ComponentName(pkg, pkg + ".accounts.SetupAccountReceiver"));
+        } else {
+            intent.setComponent(new ComponentName(pkg, pkg + ".accounts.AddAccountSettings"));
+        }
         intent.setAction(Intent.ACTION_RUN);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         String authTypes[] = {"android.security.cts"};
@@ -47,8 +67,9 @@
         try {
             mContext.startActivity(intent);
         } catch (ActivityNotFoundException e) {
-            assumeNoException(e);
+            // activity does not exist on this device
+            exitMessage = "accountSettings() failure: activity does not exist on this device";
         }
-        Log.d(TAG, "accountSettings() end");
+        Log.d(TAG, exitMessage);
     }
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
similarity index 88%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
index 50acd29..ea39e68 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
@@ -20,11 +20,13 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2021-0963",
     defaults: [
-        "cts_support_defaults",
+        "cts_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
@@ -33,5 +35,5 @@
         "androidx.test.rules",
         "androidx.test.uiautomator_uiautomator",
     ],
-    sdk_version: "current",
+    platform_apis: true,
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
new file mode 100644
index 0000000..ae0d416
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_0963">
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <application>
+        <activity android:name=".PocActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <receiver android:name=".PocDeviceAdminReceiver"
+            android:exported="true"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_policies" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+        <service android:name=".PocService" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2021_0963" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
similarity index 64%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
index 7460b96..6a14b4a 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
@@ -14,13 +14,9 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
+
+<resources>
+    <integer name="assumptionFailure">-1</integer>
+    <integer name="noException">0</integer>
+    <integer name="timeoutMs">10000</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
new file mode 100644
index 0000000..1da84fe
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="actionKeychainActivity">com.android.keychain.CHOOSER</string>
+    <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+    <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+    <string name="alias">Client</string>
+    <string name="callbackKey">callback</string>
+    <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+    <string name="certType">X.509</string>
+    <string name="dumpsysActivity">dumpsys activity %1$s</string>
+    <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command
+    </string>
+    <string name="errorMessage">Device is vulnerable to b/199754277 hence any app with
+    "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+    <string name="keyType">RSA</string>
+    <string name="mResumedTrue">mResumed=true</string>
+    <string name="messageKey">message</string>
+    <string name="overlayButtonText">OverlayButton</string>
+    <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+    <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+    <string name="statusKey">status</string>
+    <string name="vulActivityNotRunningError">The activity %1$s is not currently running
+    on the device</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
similarity index 64%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
rename to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
index 7460b96..a826e80 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
@@ -14,13 +14,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
+
+<device-admin>
+    <uses-policies>
+    </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
new file mode 100644
index 0000000..3d1c0df
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2022 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_0963;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private DevicePolicyManager mDevicePolicyManager;
+    private ComponentName mComponentName;
+    Context mContext;
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] PRIVATE_KEY =
+            new byte[] {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x76, (byte) 0x02,
+                    (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+                    (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+                    (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04,
+                    (byte) 0x82, (byte) 0x02, (byte) 0x60, (byte) 0x30, (byte) 0x82, (byte) 0x02,
+                    (byte) 0x5c, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81,
+                    (byte) 0x81, (byte) 0x00, (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8,
+                    (byte) 0xc4, (byte) 0x44, (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1,
+                    (byte) 0xb9, (byte) 0x1b, (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f,
+                    (byte) 0x06, (byte) 0xe7, (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8,
+                    (byte) 0xaa, (byte) 0x0a, (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b,
+                    (byte) 0xad, (byte) 0xfe, (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d,
+                    (byte) 0xc9, (byte) 0xf5, (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1,
+                    (byte) 0xcc, (byte) 0x3f, (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67,
+                    (byte) 0x6a, (byte) 0xe8, (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a,
+                    (byte) 0x53, (byte) 0xd9, (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90,
+                    (byte) 0xbb, (byte) 0x95, (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32,
+                    (byte) 0xce, (byte) 0xf8, (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19,
+                    (byte) 0x91, (byte) 0x29, (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1,
+                    (byte) 0xcb, (byte) 0xa7, (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a,
+                    (byte) 0x0c, (byte) 0x07, (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d,
+                    (byte) 0x08, (byte) 0xf4, (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66,
+                    (byte) 0x28, (byte) 0xcb, (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f,
+                    (byte) 0x7e, (byte) 0x83, (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83,
+                    (byte) 0x2d, (byte) 0xa0, (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68,
+                    (byte) 0x47, (byte) 0x31, (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e,
+                    (byte) 0x12, (byte) 0x1b, (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8,
+                    (byte) 0x84, (byte) 0x5f, (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03,
+                    (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80,
+                    (byte) 0x24, (byte) 0x95, (byte) 0xb8, (byte) 0xe1, (byte) 0xf4, (byte) 0x7b,
+                    (byte) 0xbc, (byte) 0x0c, (byte) 0x6d, (byte) 0x4d, (byte) 0x01, (byte) 0xe2,
+                    (byte) 0x42, (byte) 0xe2, (byte) 0x9a, (byte) 0xe4, (byte) 0xab, (byte) 0xe2,
+                    (byte) 0x9a, (byte) 0x8c, (byte) 0xd5, (byte) 0x93, (byte) 0xe8, (byte) 0x43,
+                    (byte) 0x77, (byte) 0x85, (byte) 0xfd, (byte) 0xf3, (byte) 0xd8, (byte) 0xd6,
+                    (byte) 0xe9, (byte) 0x02, (byte) 0xf3, (byte) 0xbf, (byte) 0x82, (byte) 0x65,
+                    (byte) 0xc3, (byte) 0x7c, (byte) 0x96, (byte) 0x09, (byte) 0x04, (byte) 0x16,
+                    (byte) 0x1d, (byte) 0x03, (byte) 0x3d, (byte) 0x82, (byte) 0xb8, (byte) 0xdc,
+                    (byte) 0xbb, (byte) 0xd6, (byte) 0xbf, (byte) 0x2a, (byte) 0x52, (byte) 0x83,
+                    (byte) 0x76, (byte) 0x5b, (byte) 0xae, (byte) 0x59, (byte) 0xf6, (byte) 0xee,
+                    (byte) 0x84, (byte) 0x44, (byte) 0x4a, (byte) 0xa7, (byte) 0x25, (byte) 0x50,
+                    (byte) 0x89, (byte) 0x63, (byte) 0x43, (byte) 0x0b, (byte) 0xc8, (byte) 0xd5,
+                    (byte) 0x17, (byte) 0x9d, (byte) 0x8b, (byte) 0x62, (byte) 0xd5, (byte) 0xf1,
+                    (byte) 0xde, (byte) 0x45, (byte) 0xe6, (byte) 0x35, (byte) 0x10, (byte) 0xba,
+                    (byte) 0x58, (byte) 0x18, (byte) 0x44, (byte) 0xc1, (byte) 0x6d, (byte) 0xb6,
+                    (byte) 0x1d, (byte) 0x2f, (byte) 0x53, (byte) 0xb6, (byte) 0x5a, (byte) 0xf1,
+                    (byte) 0x66, (byte) 0xbc, (byte) 0x0e, (byte) 0x63, (byte) 0xa7, (byte) 0x0f,
+                    (byte) 0x81, (byte) 0x4b, (byte) 0x07, (byte) 0x31, (byte) 0xa5, (byte) 0x70,
+                    (byte) 0xec, (byte) 0x30, (byte) 0x57, (byte) 0xc4, (byte) 0x14, (byte) 0xb2,
+                    (byte) 0x8b, (byte) 0x6f, (byte) 0x26, (byte) 0x7e, (byte) 0x55, (byte) 0x60,
+                    (byte) 0x63, (byte) 0x7d, (byte) 0x90, (byte) 0xd7, (byte) 0x5f, (byte) 0xef,
+                    (byte) 0x7d, (byte) 0xc1, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xfe,
+                    (byte) 0x92, (byte) 0xa9, (byte) 0xf1, (byte) 0x29, (byte) 0x1e, (byte) 0xd4,
+                    (byte) 0x72, (byte) 0xd3, (byte) 0x3f, (byte) 0x9d, (byte) 0xd6, (byte) 0x3d,
+                    (byte) 0xe9, (byte) 0xcf, (byte) 0x3e, (byte) 0x06, (byte) 0xdc, (byte) 0x65,
+                    (byte) 0x8f, (byte) 0xc0, (byte) 0x81, (byte) 0xc2, (byte) 0x66, (byte) 0xc1,
+                    (byte) 0x5c, (byte) 0x2c, (byte) 0xfa, (byte) 0x08, (byte) 0x65, (byte) 0xb6,
+                    (byte) 0x47, (byte) 0xc5, (byte) 0x14, (byte) 0x8d, (byte) 0x69, (byte) 0xe9,
+                    (byte) 0xaf, (byte) 0x42, (byte) 0x02, (byte) 0x53, (byte) 0x04, (byte) 0x63,
+                    (byte) 0x47, (byte) 0xaf, (byte) 0xcc, (byte) 0xae, (byte) 0x08, (byte) 0x31,
+                    (byte) 0xba, (byte) 0xea, (byte) 0x85, (byte) 0xda, (byte) 0xd6, (byte) 0xb2,
+                    (byte) 0xe7, (byte) 0x4c, (byte) 0xda, (byte) 0xad, (byte) 0x52, (byte) 0x76,
+                    (byte) 0x48, (byte) 0x16, (byte) 0xeb, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+                    (byte) 0xef, (byte) 0xc4, (byte) 0x7d, (byte) 0x69, (byte) 0x7b, (byte) 0xcb,
+                    (byte) 0xcb, (byte) 0xf7, (byte) 0x00, (byte) 0x2d, (byte) 0x05, (byte) 0x3c,
+                    (byte) 0xe4, (byte) 0xfd, (byte) 0x5c, (byte) 0xea, (byte) 0xcf, (byte) 0x40,
+                    (byte) 0x84, (byte) 0x10, (byte) 0xf1, (byte) 0xc0, (byte) 0xaf, (byte) 0xc7,
+                    (byte) 0xc8, (byte) 0x51, (byte) 0xac, (byte) 0x18, (byte) 0x25, (byte) 0x63,
+                    (byte) 0x75, (byte) 0xc7, (byte) 0x0e, (byte) 0xa9, (byte) 0xed, (byte) 0x9c,
+                    (byte) 0x78, (byte) 0x08, (byte) 0x28, (byte) 0x1d, (byte) 0x9e, (byte) 0xfa,
+                    (byte) 0x17, (byte) 0x0f, (byte) 0x7a, (byte) 0x6a, (byte) 0x78, (byte) 0x63,
+                    (byte) 0x6e, (byte) 0xb3, (byte) 0x6b, (byte) 0xd6, (byte) 0x43, (byte) 0x4b,
+                    (byte) 0x58, (byte) 0xb8, (byte) 0x77, (byte) 0x10, (byte) 0x07, (byte) 0x70,
+                    (byte) 0xa6, (byte) 0xa9, (byte) 0xae, (byte) 0x0d, (byte) 0x02, (byte) 0x41,
+                    (byte) 0x00, (byte) 0x92, (byte) 0x4c, (byte) 0x79, (byte) 0x0b, (byte) 0x95,
+                    (byte) 0xc5, (byte) 0x18, (byte) 0xf4, (byte) 0x90, (byte) 0x40, (byte) 0x8c,
+                    (byte) 0x15, (byte) 0x96, (byte) 0x69, (byte) 0x2a, (byte) 0xe7, (byte) 0x8b,
+                    (byte) 0x8b, (byte) 0xd7, (byte) 0x76, (byte) 0x00, (byte) 0x7c, (byte) 0xd1,
+                    (byte) 0xda, (byte) 0xb9, (byte) 0x9e, (byte) 0x9e, (byte) 0x5e, (byte) 0x66,
+                    (byte) 0xbb, (byte) 0x05, (byte) 0x41, (byte) 0x43, (byte) 0x9a, (byte) 0x67,
+                    (byte) 0x16, (byte) 0x89, (byte) 0xec, (byte) 0x65, (byte) 0x33, (byte) 0xee,
+                    (byte) 0xbf, (byte) 0xa3, (byte) 0xca, (byte) 0x8b, (byte) 0xd6, (byte) 0x45,
+                    (byte) 0xe1, (byte) 0x81, (byte) 0xaa, (byte) 0xd8, (byte) 0xa2, (byte) 0x6a,
+                    (byte) 0x3c, (byte) 0x5e, (byte) 0x7e, (byte) 0x1c, (byte) 0xa5, (byte) 0xc3,
+                    (byte) 0x5b, (byte) 0x93, (byte) 0x8c, (byte) 0x24, (byte) 0x57, (byte) 0x02,
+                    (byte) 0x40, (byte) 0x0a, (byte) 0x6d, (byte) 0x3f, (byte) 0x0e, (byte) 0xf1,
+                    (byte) 0x45, (byte) 0x41, (byte) 0x8f, (byte) 0x72, (byte) 0x40, (byte) 0x82,
+                    (byte) 0xf3, (byte) 0xcc, (byte) 0xf9, (byte) 0x7f, (byte) 0xaa, (byte) 0xee,
+                    (byte) 0x6c, (byte) 0x5d, (byte) 0xd1, (byte) 0xe6, (byte) 0xd1, (byte) 0x7c,
+                    (byte) 0x53, (byte) 0x71, (byte) 0xd0, (byte) 0xab, (byte) 0x6d, (byte) 0x39,
+                    (byte) 0x63, (byte) 0x03, (byte) 0xe2, (byte) 0x2e, (byte) 0x2f, (byte) 0x11,
+                    (byte) 0x98, (byte) 0x36, (byte) 0x58, (byte) 0x14, (byte) 0x76, (byte) 0x85,
+                    (byte) 0x4d, (byte) 0x56, (byte) 0xe7, (byte) 0x63, (byte) 0x69, (byte) 0x71,
+                    (byte) 0xe6, (byte) 0xd1, (byte) 0x0f, (byte) 0x98, (byte) 0x66, (byte) 0xee,
+                    (byte) 0xf2, (byte) 0x3d, (byte) 0xdf, (byte) 0x77, (byte) 0xbe, (byte) 0x08,
+                    (byte) 0xb4, (byte) 0xcb, (byte) 0x6a, (byte) 0xa1, (byte) 0x99, (byte) 0x02,
+                    (byte) 0x40, (byte) 0x52, (byte) 0x01, (byte) 0xde, (byte) 0x62, (byte) 0xc2,
+                    (byte) 0x25, (byte) 0xbf, (byte) 0x5d, (byte) 0x77, (byte) 0xe4, (byte) 0x6b,
+                    (byte) 0xb6, (byte) 0xd7, (byte) 0x8f, (byte) 0x89, (byte) 0x2c, (byte) 0xe6,
+                    (byte) 0x8d, (byte) 0xe5, (byte) 0xad, (byte) 0x39, (byte) 0x17, (byte) 0x54,
+                    (byte) 0x2b, (byte) 0x35, (byte) 0x53, (byte) 0xd1, (byte) 0xa1, (byte) 0xef,
+                    (byte) 0x48, (byte) 0xbc, (byte) 0x95, (byte) 0x48, (byte) 0xcf, (byte) 0x62,
+                    (byte) 0xf4, (byte) 0x33, (byte) 0xcf, (byte) 0x37, (byte) 0x78, (byte) 0xeb,
+                    (byte) 0x17, (byte) 0xb4, (byte) 0x0b, (byte) 0x83, (byte) 0x4f, (byte) 0xb6,
+                    (byte) 0xab, (byte) 0x7d, (byte) 0x67, (byte) 0x3e, (byte) 0x4e, (byte) 0x44,
+                    (byte) 0x4a, (byte) 0x55, (byte) 0x2e, (byte) 0x34, (byte) 0x12, (byte) 0x0b,
+                    (byte) 0x59, (byte) 0xb3, (byte) 0xb1, (byte) 0x1e, (byte) 0x3d};
+
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] USER_CERT =
+            {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xd8, (byte) 0x30, (byte) 0x82,
+                    (byte) 0x01, (byte) 0xc0, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+                    (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+                    (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+                    (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x0b, (byte) 0x05,
+                    (byte) 0x00, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+                    (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+                    (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13,
+                    (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+                    (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
+                    (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74,
+                    (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
+                    (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x06,
+                    (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65,
+                    (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x32,
+                    (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x30, (byte) 0x37,
+                    (byte) 0x32, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x5a, (byte) 0x17,
+                    (byte) 0x0d, (byte) 0x33, (byte) 0x32, (byte) 0x30, (byte) 0x33, (byte) 0x32,
+                    (byte) 0x32, (byte) 0x30, (byte) 0x37, (byte) 0x32, (byte) 0x30, (byte) 0x31,
+                    (byte) 0x32, (byte) 0x5a, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b,
+                    (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+                    (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31,
+                    (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+                    (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f,
+                    (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61,
+                    (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d,
+                    (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c,
+                    (byte) 0x06, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c,
+                    (byte) 0x65, (byte) 0x30, (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d,
+                    (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+                    (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+                    (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30,
+                    (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+                    (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8, (byte) 0xc4, (byte) 0x44,
+                    (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1, (byte) 0xb9, (byte) 0x1b,
+                    (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f, (byte) 0x06, (byte) 0xe7,
+                    (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8, (byte) 0xaa, (byte) 0x0a,
+                    (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b, (byte) 0xad, (byte) 0xfe,
+                    (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d, (byte) 0xc9, (byte) 0xf5,
+                    (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1, (byte) 0xcc, (byte) 0x3f,
+                    (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67, (byte) 0x6a, (byte) 0xe8,
+                    (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a, (byte) 0x53, (byte) 0xd9,
+                    (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90, (byte) 0xbb, (byte) 0x95,
+                    (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32, (byte) 0xce, (byte) 0xf8,
+                    (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19, (byte) 0x91, (byte) 0x29,
+                    (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1, (byte) 0xcb, (byte) 0xa7,
+                    (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a, (byte) 0x0c, (byte) 0x07,
+                    (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d, (byte) 0x08, (byte) 0xf4,
+                    (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66, (byte) 0x28, (byte) 0xcb,
+                    (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f, (byte) 0x7e, (byte) 0x83,
+                    (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83, (byte) 0x2d, (byte) 0xa0,
+                    (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68, (byte) 0x47, (byte) 0x31,
+                    (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e, (byte) 0x12, (byte) 0x1b,
+                    (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8, (byte) 0x84, (byte) 0x5f,
+                    (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00,
+                    (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30, (byte) 0x79, (byte) 0x30,
+                    (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13,
+                    (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00, (byte) 0x30, (byte) 0x2c,
+                    (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
+                    (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01, (byte) 0x0d, (byte) 0x04,
+                    (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f, (byte) 0x70, (byte) 0x65,
+                    (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c, (byte) 0x20, (byte) 0x47,
+                    (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72, (byte) 0x61, (byte) 0x74,
+                    (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43, (byte) 0x65, (byte) 0x72,
+                    (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69, (byte) 0x63, (byte) 0x61,
+                    (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d, (byte) 0x06, (byte) 0x03,
+                    (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16, (byte) 0x04,
+                    (byte) 0x14, (byte) 0xee, (byte) 0xec, (byte) 0x08, (byte) 0xcc, (byte) 0xdd,
+                    (byte) 0xa3, (byte) 0x29, (byte) 0x6e, (byte) 0x2b, (byte) 0x78, (byte) 0x23,
+                    (byte) 0xb3, (byte) 0xf0, (byte) 0xb8, (byte) 0x9d, (byte) 0x53, (byte) 0x41,
+                    (byte) 0x2e, (byte) 0x3c, (byte) 0x61, (byte) 0x30, (byte) 0x1f, (byte) 0x06,
+                    (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04, (byte) 0x18,
+                    (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0x86, (byte) 0xdb,
+                    (byte) 0xa5, (byte) 0x5e, (byte) 0x0e, (byte) 0x03, (byte) 0xbc, (byte) 0xe4,
+                    (byte) 0xc1, (byte) 0xc8, (byte) 0xf3, (byte) 0xed, (byte) 0x24, (byte) 0x48,
+                    (byte) 0xb1, (byte) 0x37, (byte) 0x3a, (byte) 0x52, (byte) 0x10, (byte) 0x57,
+                    (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+                    (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+                    (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82, (byte) 0x01,
+                    (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x5a, (byte) 0x5c, (byte) 0x08,
+                    (byte) 0xe4, (byte) 0x0e, (byte) 0x28, (byte) 0x4c, (byte) 0xa9, (byte) 0x0e,
+                    (byte) 0x35, (byte) 0xbe, (byte) 0xe3, (byte) 0xd5, (byte) 0xd1, (byte) 0xb4,
+                    (byte) 0x47, (byte) 0x87, (byte) 0x63, (byte) 0xd2, (byte) 0x5e, (byte) 0x7e,
+                    (byte) 0xf6, (byte) 0xd8, (byte) 0xce, (byte) 0xdf, (byte) 0x10, (byte) 0x15,
+                    (byte) 0x61, (byte) 0xc4, (byte) 0x9a, (byte) 0xf1, (byte) 0xba, (byte) 0x33,
+                    (byte) 0xf2, (byte) 0xc2, (byte) 0x01, (byte) 0x95, (byte) 0xa7, (byte) 0x74,
+                    (byte) 0x97, (byte) 0xc1, (byte) 0x43, (byte) 0x68, (byte) 0x92, (byte) 0xbe,
+                    (byte) 0x9a, (byte) 0x6f, (byte) 0x38, (byte) 0xcb, (byte) 0xa0, (byte) 0xcf,
+                    (byte) 0x1e, (byte) 0x5b, (byte) 0x03, (byte) 0xde, (byte) 0x45, (byte) 0x6d,
+                    (byte) 0xea, (byte) 0xf0, (byte) 0x46, (byte) 0x4d, (byte) 0xb6, (byte) 0x4b,
+                    (byte) 0x88, (byte) 0xc7, (byte) 0xb8, (byte) 0xe3, (byte) 0x9f, (byte) 0x58,
+                    (byte) 0x8b, (byte) 0x2d, (byte) 0xbf, (byte) 0x4b, (byte) 0x3f, (byte) 0x54,
+                    (byte) 0x2d, (byte) 0xa8, (byte) 0x27, (byte) 0x72, (byte) 0x5e, (byte) 0x36,
+                    (byte) 0x67, (byte) 0x5c, (byte) 0x6e, (byte) 0x9a, (byte) 0x67, (byte) 0x73,
+                    (byte) 0x44, (byte) 0xaf, (byte) 0x46, (byte) 0x7f, (byte) 0xd6, (byte) 0x2b,
+                    (byte) 0x9d, (byte) 0x28, (byte) 0xb1, (byte) 0xc4, (byte) 0xc4, (byte) 0x72,
+                    (byte) 0x3d, (byte) 0x6d, (byte) 0x7d, (byte) 0x28, (byte) 0x40, (byte) 0x62,
+                    (byte) 0x40, (byte) 0x21, (byte) 0x52, (byte) 0xb5, (byte) 0x0b, (byte) 0xf3,
+                    (byte) 0xcc, (byte) 0x36, (byte) 0x03, (byte) 0x10, (byte) 0x19, (byte) 0xe3,
+                    (byte) 0xc2, (byte) 0xfe, (byte) 0xe9, (byte) 0x08, (byte) 0x0d, (byte) 0xd4,
+                    (byte) 0x8b, (byte) 0x12, (byte) 0xd6, (byte) 0x3d, (byte) 0xc5, (byte) 0xb8,
+                    (byte) 0x8c, (byte) 0xbd, (byte) 0xa5, (byte) 0xcd, (byte) 0xb3, (byte) 0xe4,
+                    (byte) 0xd1, (byte) 0xd8, (byte) 0x4c, (byte) 0x32, (byte) 0x44, (byte) 0x3f,
+                    (byte) 0x63, (byte) 0x32, (byte) 0x09, (byte) 0xdb, (byte) 0x8b, (byte) 0x7b,
+                    (byte) 0x30, (byte) 0x58, (byte) 0xc7, (byte) 0xcf, (byte) 0xc3, (byte) 0x44,
+                    (byte) 0xd9, (byte) 0xff, (byte) 0x63, (byte) 0x91, (byte) 0x74, (byte) 0xd8,
+                    (byte) 0x62, (byte) 0x2b, (byte) 0x52, (byte) 0xc8, (byte) 0x82, (byte) 0x9f,
+                    (byte) 0xeb, (byte) 0x22, (byte) 0x5c, (byte) 0xa2, (byte) 0x26, (byte) 0xfe,
+                    (byte) 0x04, (byte) 0x31, (byte) 0x53, (byte) 0x09, (byte) 0xa7, (byte) 0x23,
+                    (byte) 0xe3, (byte) 0x0f, (byte) 0xf8, (byte) 0xe9, (byte) 0x99, (byte) 0xad,
+                    (byte) 0x4b, (byte) 0x23, (byte) 0x07, (byte) 0xfb, (byte) 0xfa, (byte) 0xc3,
+                    (byte) 0x55, (byte) 0x59, (byte) 0xdb, (byte) 0x6b, (byte) 0x71, (byte) 0xdf,
+                    (byte) 0x25, (byte) 0x0f, (byte) 0xaa, (byte) 0xa2, (byte) 0xfa, (byte) 0x28,
+                    (byte) 0x49, (byte) 0x65, (byte) 0x7e, (byte) 0x0b, (byte) 0x74, (byte) 0x30,
+                    (byte) 0xd9, (byte) 0x9a, (byte) 0xfe, (byte) 0x2c, (byte) 0x8c, (byte) 0x67,
+                    (byte) 0x50, (byte) 0x0c, (byte) 0x6d, (byte) 0x4c, (byte) 0xba, (byte) 0x34,
+                    (byte) 0x3b, (byte) 0x0d, (byte) 0x16, (byte) 0x45, (byte) 0x63, (byte) 0x73,
+                    (byte) 0xc2, (byte) 0x9f, (byte) 0xb4, (byte) 0xdd, (byte) 0x6f, (byte) 0xde,
+                    (byte) 0x9d, (byte) 0x71, (byte) 0xbf, (byte) 0x8d, (byte) 0x1b, (byte) 0x79,
+                    (byte) 0xa0, (byte) 0x0a, (byte) 0x66, (byte) 0x7e, (byte) 0x56, (byte) 0x83,
+                    (byte) 0x8f, (byte) 0x3f, (byte) 0x7d, (byte) 0x93, (byte) 0xf6, (byte) 0xc9,
+                    (byte) 0x42, (byte) 0xfc, (byte) 0xc5, (byte) 0xf2, (byte) 0x49, (byte) 0xec};
+
+    @After
+    public void tearDown() {
+        try {
+            mDevicePolicyManager.removeKeyPair(mComponentName, mContext.getString(R.string.alias));
+            mDevicePolicyManager.clearDeviceOwnerApp(mContext.getPackageName());
+        } catch (Exception e) {
+            // ignore all exceptions as the test is already complete
+        }
+    }
+
+    @Test
+    public void testOverlayButtonPresence() {
+        try {
+            /* Install key pair required to launch KeyChainActivity dialog */
+            mContext = getInstrumentation().getContext();
+            Resources resources = mContext.getResources();
+            KeyFactory kf = KeyFactory.getInstance(mContext.getString(R.string.keyType));
+            PrivateKey privKey = kf.generatePrivate(new PKCS8EncodedKeySpec(PRIVATE_KEY));
+            CertificateFactory cf =
+                    CertificateFactory.getInstance(mContext.getString(R.string.certType));
+            Certificate cert = cf.generateCertificate(new ByteArrayInputStream(USER_CERT));
+            mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+            mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(),
+                    PocDeviceAdminReceiver.class.getName());
+            assumeTrue(mDevicePolicyManager.installKeyPair(mComponentName, privKey, cert,
+                    mContext.getString(R.string.alias)));
+
+            /* Start the overlay service */
+            Intent intent = new Intent(mContext, PocService.class);
+            assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg),
+                    Settings.canDrawOverlays(mContext));
+            CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
+            RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+                PocStatus pocStatus =
+                        new PocStatus(result.getInt(mContext.getString(R.string.statusKey)),
+                                result.getString(mContext.getString(R.string.messageKey)));
+                callbackReturn.complete(pocStatus);
+            });
+            intent.putExtra(mContext.getString(R.string.callbackKey), cb);
+            mContext.startService(intent);
+            PocStatus result = callbackReturn.get(resources.getInteger(R.integer.timeoutMs),
+                    TimeUnit.MILLISECONDS);
+            assumeTrue(result.getErrorMessage(),
+                    result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
+
+            /* Wait for the overlay window */
+            Pattern overlayTextPattern = Pattern.compile(
+                    mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+            UiDevice device = UiDevice.getInstance(getInstrumentation());
+            assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+                    device.wait(Until.hasObject(By.text(overlayTextPattern)),
+                            mContext.getResources().getInteger(R.integer.timeoutMs)));
+
+            /* Start PocActivity which starts the vulnerable activity */
+            intent = new Intent(mContext, PocActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            CompletableFuture<PocStatus> pocActivityReturn = new CompletableFuture<>();
+            RemoteCallback pocActivityCb = new RemoteCallback((Bundle pocActivityResult) -> {
+                PocStatus pocStatus = new PocStatus(
+                        pocActivityResult.getInt(mContext.getString(R.string.statusKey)),
+                        pocActivityResult.getString(mContext.getString(R.string.messageKey)));
+                pocActivityReturn.complete(pocStatus);
+            });
+            intent.putExtra(mContext.getString(R.string.callbackKey), pocActivityCb);
+            mContext.startActivity(intent);
+            result = pocActivityReturn.get(resources.getInteger(R.integer.timeoutMs),
+                    TimeUnit.MILLISECONDS);
+            assumeTrue(result.getErrorMessage(),
+                    result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
+
+            /* Get the vulnerable activity name by using an alternative intent */
+            Intent vulIntent = new Intent(mContext.getString(R.string.actionKeychainActivity));
+            ResolveInfo ri = mContext.getPackageManager().resolveActivity(vulIntent,
+                    PackageManager.MATCH_DEFAULT_ONLY);
+            String vulnerableActivityName = ri.activityInfo.name;
+
+            /* Wait until the object of launcher activity is gone */
+            boolean overlayDisallowed = device.wait(Until.gone(By.pkg(mContext.getPackageName())),
+                    mContext.getResources().getInteger(R.integer.timeoutMs));
+
+            /* Check if the currently running activity is the vulnerable activity */
+            String activityDump = "";
+            activityDump = device.executeShellCommand(
+                    mContext.getString(R.string.dumpsysActivity, vulnerableActivityName));
+            Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
+                    Pattern.CASE_INSENSITIVE);
+            assumeTrue(
+                    mContext.getString(R.string.vulActivityNotRunningError, vulnerableActivityName),
+                    activityPattern.matcher(activityDump).find());
+
+            /* Failing the test as fix is not present */
+            assertTrue(mContext.getString(R.string.errorMessage, vulnerableActivityName),
+                    overlayDisallowed);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
new file mode 100644
index 0000000..ac8ea15
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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_0963;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.security.KeyChain;
+import android.security.KeyChainAliasCallback;
+
+import androidx.annotation.Nullable;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            KeyChainAliasCallback callback = new KeyChainAliasCallback() {
+                @Override
+                public void alias(@Nullable String alias) {}
+            };
+            KeyChain.choosePrivateKeyAlias(this, callback, null, null, null, -1, null);
+            sendTestResult(getResources().getInteger(R.integer.noException), "");
+        } catch (Exception e) {
+            sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+    }
+
+    void sendTestResult(int status, String message) {
+        try {
+            RemoteCallback cb =
+                    (RemoteCallback) getIntent().getExtras().get(getString(R.string.callbackKey));
+            Bundle res = new Bundle();
+            res.putString(getString(R.string.messageKey), message);
+            res.putInt(getString(R.string.statusKey), status);
+            cb.sendResult(res);
+        } catch (Exception e) {
+            // ignore all exceptions
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
similarity index 79%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
index 1a335c7..5592323 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0963;
 
-import android.app.Activity;
+import android.app.admin.DeviceAdminReceiver;
 
-public class PocActivity extends Activity {
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
new file mode 100644
index 0000000..b83e824
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 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_0963;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+    Button mButton;
+    WindowManager mWindowManager;
+    LayoutParams mLayoutParams;
+    Intent mIntent;
+
+    private static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    private static int getScreenHeight() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        try {
+            mIntent = intent;
+            mWindowManager = getSystemService(WindowManager.class);
+            mLayoutParams = new LayoutParams();
+            mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+            mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL |
+                    LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLayoutParams.format = PixelFormat.OPAQUE;
+            mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+            mLayoutParams.width = getScreenWidth();
+            mLayoutParams.height = getScreenHeight();
+            mLayoutParams.x = getScreenWidth() / 2;
+            mLayoutParams.y = getScreenHeight() / 2;
+            Context context = getApplicationContext();
+            mButton = new Button(context);
+            mButton.setText(context.getString(R.string.overlayButtonText));
+            mWindowManager.addView(mButton, mLayoutParams);
+            sendTestResult(getResources().getInteger(R.integer.noException), "");
+        } catch (Exception e) {
+            sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        try {
+            mWindowManager.removeView(mButton);
+        } catch (Exception e) {
+            sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+        super.onDestroy();
+    }
+
+    void sendTestResult(int status, String message) {
+        try {
+            RemoteCallback cb =
+                    (RemoteCallback) mIntent.getExtras().get(getString(R.string.callbackKey));
+            Bundle res = new Bundle();
+            res.putString(getString(R.string.messageKey), message);
+            res.putInt(getString(R.string.statusKey), status);
+            cb.sendResult(res);
+        } catch (Exception e) {
+            // ignore exception here
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
similarity index 62%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
index 1a335c7..de67f0f 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
@@ -14,9 +14,22 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0963;
 
-import android.app.Activity;
+public class PocStatus {
+    int statusCode;
+    String errorMessage;
 
-public class PocActivity extends Activity {
+    public PocStatus(int status, String message) {
+        statusCode = status;
+        errorMessage = message;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
similarity index 81%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
index 50acd29..db55729 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
@@ -20,18 +20,15 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2022-20475-target",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
-    static_libs: [
-        "androidx.test.core",
-        "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
-    ],
     sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml
new file mode 100644
index 0000000..60fb528
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20475_target">
+    <application android:allowTaskReparenting="true">
+        <activity android:name=".TargetActivity"
+            android:exported="true" />
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
similarity index 63%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
index 7460b96..c424970 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
@@ -14,13 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
+
+<resources>
+    <string name="bcastActionTarget">CVE_2022_20475_TargetActivity</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java
new file mode 100644
index 0000000..4b885c6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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_2022_20475_target;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class TargetActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            sendBroadcast(new Intent(getString(R.string.bcastActionTarget)));
+        } catch (Exception ignored) {
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        try {
+            super.onResume();
+            sendBroadcast(new Intent(getString(R.string.bcastActionTarget)));
+        } catch (Exception ignored) {
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
similarity index 89%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
index 50acd29..043de912 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
@@ -20,18 +20,19 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2022-20475-test",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
     static_libs: [
         "androidx.test.core",
         "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
     ],
     sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..2e35b65
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20475_test">
+    <application>
+        <activity android:name=".PocActivity" />
+        <activity android:name=".HijackActivity" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2022_20475_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml
new file mode 100644
index 0000000..bbeb2c5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="activityTarget">android.security.cts.CVE_2022_20475_target.TargetActivity</string>
+    <string name="pkgTarget">android.security.cts.CVE_2022_20475_target</string>
+    <string name="bcastActionHijack">CVE_2022_20475_HijackActivity</string>
+    <string name="bcastActionTarget">CVE_2022_20475_TargetActivity</string>
+    <string name="msgFail">Device is vulnerable to b/240663194 !!</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java
new file mode 100644
index 0000000..53e4c3e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 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_2022_20475_test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final int WAIT_MS = 5000;
+
+    @Test
+    public void testCVE_2022_20475() {
+        try {
+            // Registering a receiver here to wait for a broadcast from either HijackActivity or
+            // TargetActivity
+            Context context = getApplicationContext();
+            CompletableFuture<Boolean> hijackReturn = new CompletableFuture<>();
+            CompletableFuture<Boolean> targetReturn = new CompletableFuture<>();
+            final String bcastActionHijack = context.getString(R.string.bcastActionHijack);
+            final String bcastActionTarget = context.getString(R.string.bcastActionTarget);
+            BroadcastReceiver broadcastReceiver =
+                    new BroadcastReceiver() {
+                        @Override
+                        public void onReceive(Context context, Intent intent) {
+                            if (intent.getAction().equals(bcastActionHijack)) {
+                                hijackReturn.complete(true);
+                            } else if (intent.getAction().equals(bcastActionTarget)) {
+                                targetReturn.complete(true);
+                            }
+                        }
+                    };
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(bcastActionHijack);
+            filter.addAction(bcastActionTarget);
+            context.registerReceiver(broadcastReceiver, filter);
+
+            // Start PocActivity which in turn starts both TargetActivity and HijackActivity
+            Intent intent = new Intent(context, PocActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(intent);
+
+            // Waiting on callback from HijackActivity which is started last by PocActivity
+            hijackReturn.get(WAIT_MS, TimeUnit.MILLISECONDS);
+
+            // Start TargetActivity
+            Intent targetIntent = new Intent(Intent.ACTION_MAIN);
+            final String pkgTarget = context.getString(R.string.pkgTarget);
+            targetIntent.setClassName(pkgTarget, context.getString(R.string.activityTarget));
+            targetIntent.setFlags(
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            context.startActivity(targetIntent);
+
+            // Wait on callback from TargetActivity. On vulnerable device, TargetActivity would
+            // not start and HijackActivity would remain on screen so the test should fail due
+            // to timeout on callback.
+            try {
+                targetReturn.get(WAIT_MS, TimeUnit.MILLISECONDS);
+            } catch (TimeoutException e) {
+                throw new AssertionError(context.getString(R.string.msgFail));
+            }
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
similarity index 60%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
index 1a335c7..8ac03f6 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
@@ -14,9 +14,20 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2022_20475_test;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
 
-public class PocActivity extends Activity {
+public class HijackActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            sendBroadcast(new Intent(getString(R.string.bcastActionHijack)));
+        } catch (Exception ignored) {
+        }
+    }
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java
new file mode 100644
index 0000000..e1968a4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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_2022_20475_test;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            // Start TargetActivity
+            Intent targetIntent = new Intent(Intent.ACTION_MAIN);
+            targetIntent.setClassName(getString(R.string.pkgTarget),
+                    getString(R.string.activityTarget));
+            startActivity(targetIntent);
+
+            // Start HijackActivity. On vulnerable device, this will be parented by the task
+            // android.security.cts.CVE_2022_20475_target
+            startActivity(new Intent(this, HijackActivity.class));
+        } catch (Exception ignored) {
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/Android.bp
similarity index 90%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20501/Android.bp
index 50acd29..9498881 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/Android.bp
@@ -20,11 +20,13 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2022-20501",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
@@ -33,5 +35,5 @@
         "androidx.test.rules",
         "androidx.test.uiautomator_uiautomator",
     ],
-    sdk_version: "current",
+    platform_apis: true,
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/AndroidManifest.xml
new file mode 100644
index 0000000..5789b65
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20501">
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <application>
+        <service android:name=".PocService"
+            android:enabled="true" />
+    </application>
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2022_20501" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/res/values/strings.xml
new file mode 100644
index 0000000..2af8c0e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/res/values/strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+    <string name="activityNotFoundMsg">The activity with intent %1$s was not found</string>
+    <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+    <string name="cmdDumpsysActivity">dumpsys activity %1$s</string>
+    <string name="dumpsysActivityException">Could not execute dumpsys activity command</string>
+    <string name="overlayButtonText">CVE_2022_20501_OverlayButton</string>
+    <string name="overlayErrorMessage">Device is vulnerable to b/246933359 hence any app with
+    "SYSTEM_ALERT_WINDOW permission can overlay the %1$s screen</string>
+    <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+    <string name="mResumedTrue">mResumed=true</string>
+    <string name="telUri">tel:6505551212</string>
+    <string name="telecomPkgDefault">com.android.server.telecom</string>
+    <string name="vulClsName">.settings.EnableAccountPreferenceActivity</string>
+    <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+    </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/src/android/security/cts/CVE_2022_20501/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/src/android/security/cts/CVE_2022_20501/DeviceTest.java
new file mode 100644
index 0000000..d6f5198
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/src/android/security/cts/CVE_2022_20501/DeviceTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 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_2022_20501;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private Context mContext;
+
+    private void startOverlayService() {
+        Intent intent = new Intent(mContext, PocService.class);
+        assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg),
+                Settings.canDrawOverlays(mContext));
+        mContext.startService(intent);
+    }
+
+    private String getTelecomPkgName() {
+        PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+        UiAutomation ui = getInstrumentation().getUiAutomation();
+        String name = mContext.getString(R.string.telecomPkgDefault);
+        try {
+            ui.adoptShellPermissionIdentity(android.Manifest.permission.INTERACT_ACROSS_USERS);
+            Intent intent = new Intent(Intent.ACTION_CALL);
+            intent.setData(Uri.parse(mContext.getString(R.string.telUri)));
+            ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_SYSTEM_ONLY,
+                    UserHandle.USER_SYSTEM);
+            name = info.activityInfo.packageName;
+        } catch (Exception e) {
+            assumeNoException(e);
+        } finally {
+            ui.dropShellPermissionIdentity();
+        }
+        return name;
+    }
+
+    @Test
+    public void testOverlayButtonPresence() {
+        try {
+            mContext = getApplicationContext();
+            UiDevice device = UiDevice.getInstance(getInstrumentation());
+
+            // Start the overlay service
+            startOverlayService();
+
+            // Wait for the overlay window
+            Pattern overlayTextPattern = Pattern.compile(
+                    mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+            final long launchTimeoutMs = 20_000L;
+            assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+                    device.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs));
+
+            // Start the vulnerable activity
+            String pkg = getTelecomPkgName();
+            String cls = mContext.getString(R.string.vulClsName);
+            Intent intent = new Intent();
+            String vulActivity = pkg + cls;
+            intent.setClassName(pkg, vulActivity);
+            PackageManager pm = mContext.getPackageManager();
+            ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+            assumeNotNull(mContext.getString(R.string.activityNotFoundMsg, intent), ri);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(intent);
+
+            // Wait until overlay window is gone
+            boolean overlayDisallowed =
+                    device.wait(Until.gone(By.text(overlayTextPattern)), launchTimeoutMs);
+
+            // Check if the currently running activity is the vulnerable activity
+            String activityDump = device.executeShellCommand(
+                    mContext.getString(R.string.cmdDumpsysActivity, vulActivity));
+
+            Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
+                    Pattern.CASE_INSENSITIVE);
+            assumeTrue(mContext.getString(R.string.vulActivityNotRunningError, vulActivity),
+                    activityPattern.matcher(activityDump).find());
+
+            // Failing the test as overlay window is being allowed making code vulnerable
+            assertTrue(mContext.getString(R.string.overlayErrorMessage, vulActivity),
+                    overlayDisallowed);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/src/android/security/cts/CVE_2022_20501/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/src/android/security/cts/CVE_2022_20501/PocService.java
new file mode 100644
index 0000000..8e1c5d3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20501/src/android/security/cts/CVE_2022_20501/PocService.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 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_2022_20501;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+    private Button mButton;
+    private WindowManager mWindowManager;
+
+    @Override
+    public void onCreate() {
+        try {
+            super.onCreate();
+            mWindowManager = getSystemService(WindowManager.class);
+            LayoutParams layoutParams = new LayoutParams();
+            layoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+            layoutParams.flags =
+                    LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
+            layoutParams.format = PixelFormat.OPAQUE;
+            layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+            DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
+            layoutParams.width = displayMetrics.widthPixels;
+            layoutParams.height = displayMetrics.heightPixels;
+            layoutParams.x = displayMetrics.widthPixels / 2;
+            layoutParams.y = displayMetrics.heightPixels / 2;
+
+            // Show the floating window
+            mButton = new Button(this);
+            mButton.setText(getString(R.string.overlayButtonText));
+            mWindowManager.addView(mButton, layoutParams);
+        } catch (Exception ignored) {
+            // In case of occurrence of an exception overlay won't appear on display which results in
+            // assumption failure in device test. Hence ignoring this exception here.
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        try {
+            mWindowManager.removeView(mButton);
+        } catch (Exception ignored) {
+        }
+        super.onDestroy();
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
similarity index 79%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
index 50acd29..af4ad21 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
@@ -20,18 +20,16 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2023-20918-attacker",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
-    static_libs: [
-        "androidx.test.core",
-        "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
-    ],
-    sdk_version: "current",
+    // platform_apis set to true here to access hidden method setPendingIntentLaunchFlags
+    platform_apis: true,
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
similarity index 60%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
index 7460b96..bcc3ad1 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
   Copyright 2022 The Android Open Source Project
 
@@ -14,13 +13,11 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2023_20918_attacker">
+    <application>
+        <activity android:name=".ExploitActivity"
+            android:exported="true" />
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml
new file mode 100644
index 0000000..9523eca2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="bcastActionTestAssumeFail">CVE_2023_20918_assume_fail_action</string>
+    <string name="bcastActionTestFail">CVE_2023_20918_test_fail_action</string>
+    <string name="bcastActionTestPass">CVE_2023_20918_test_pass_action</string>
+    <string name="contentUri">content://authority_CVE_2023_20918_test/file_path/poc.txt</string>
+    <string name="expActivityExploit">Got an exception in ExploitActivity with message: %1$s
+    </string>
+    <string name="keyMsgAssumeFail">msg</string>
+    <string name="keyPendingIntent">pi</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java
new file mode 100644
index 0000000..1693cac
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 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_2023_20918_attacker;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class ExploitActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            Intent intent = getIntent();
+            final String keyPendingIntent = getString(R.string.keyPendingIntent);
+
+            // If intent contains 'keyPendingIntent', then this activity is launched again using
+            // the custom intent that the extra 'keyPendingIntent' holds.
+            if (intent.hasExtra(keyPendingIntent)) {
+                PendingIntent activity = intent.getParcelableExtra(keyPendingIntent);
+                ActivityOptions options = ActivityOptions.makeBasic();
+                options.setPendingIntentLaunchFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+                activity.send(this, 0, null, null, null, "", options.toBundle());
+            } else if (intent.getData() != null) {
+                // Control goes in this block when the activity is launched again. Attempting to
+                // open uri data received from the intent.
+                Uri data = intent.getData();
+                getContentResolver().openOutputStream(data);
+
+                // If control reaches here, then it means that openOutputStream() did not raise an
+                // exception, this indicates that FLAG_GRANT_WRITE_URI_PERMISSION has been granted
+                // so sending a broadcast to DeviceTest with the test_fail status.
+                sendBroadcastToTestApp(getString(R.string.bcastActionTestFail));
+            }
+        } catch (Exception e) {
+            if (e instanceof SecurityException
+                    && e.getMessage().contains(getString(R.string.keyPendingIntent))) {
+                // ignoring this exception since it occurs with fix
+                sendBroadcastToTestApp(getString(R.string.bcastActionTestPass));
+                return;
+            }
+
+            // Sending a broadcast to DeviceTest to indicate assumption failure status,
+            // since an exception was raised unrelated to the vulnerability
+            sendBroadcastToTestApp(getString(R.string.bcastActionTestAssumeFail),
+                    getString(R.string.expActivityExploit, e.getMessage()));
+        }
+    }
+
+    public void sendBroadcastToTestApp(String action) {
+        sendBroadcastToTestApp(action, null);
+    }
+
+    public void sendBroadcastToTestApp(String action, String assumeFailMsg) {
+        try {
+            Intent intent = new Intent(action);
+            if (assumeFailMsg != null) {
+                intent.putExtra(getString(R.string.keyMsgAssumeFail), assumeFailMsg);
+            }
+            sendBroadcast(intent);
+        } catch (Exception ignored) {
+            // ignore the exceptions
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
similarity index 82%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
index 50acd29..a32ae6c 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
@@ -20,18 +20,21 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2023-20918-test",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
     static_libs: [
         "androidx.test.core",
         "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
+        // including this to use androidx.core.content.FileProvider
+        "androidx.legacy_legacy-support-v4",
     ],
     sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..b95b6d7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2023_20918_test">
+    <application>
+        <provider android:name="androidx.core.content.FileProvider"
+            android:authorities="authority_CVE_2023_20918_test"
+            android:grantUriPermissions="true">
+            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_paths" />
+        </provider>
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2023_20918_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml
new file mode 100644
index 0000000..40b8d36
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="activityExploit">android.security.cts.CVE_2023_20918_attacker.ExploitActivity
+    </string>
+    <string name="bcastActionTestAssumeFail">CVE_2023_20918_assume_fail_action</string>
+    <string name="bcastActionTestFail">CVE_2023_20918_test_fail_action</string>
+    <string name="bcastActionTestPass">CVE_2023_20918_test_pass_action</string>
+    <string name="contentUri">content://authority_CVE_2023_20918_test/file_path/poc.txt</string>
+    <string name="fileContents">This is a read only file\n</string>
+    <string name="keyMsgAssumeFail">msg</string>
+    <string name="keyPendingIntent">pi</string>
+    <string name="msgAssumeFailDefault">Got an exception in DeviceTest.java</string>
+    <string name="msgFail">Device is vulnerable to b/243794108 !!</string>
+    <string name="pkgAttacker">android.security.cts.CVE_2023_20918_attacker</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
similarity index 63%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
index 7460b96..dd4259b 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
@@ -14,13 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
+
+<paths>
+    <files-path name="file_path" path="./" />
+</paths>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java
new file mode 100644
index 0000000..e677938
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 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_2023_20918_test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final long TIMEOUT_MS = 10_000L;
+    private String mAssumeFailMsg;
+
+    @Test
+    public void testCVE_2023_20918() {
+        try {
+            Context context = getApplicationContext();
+            mAssumeFailMsg = context.getString(R.string.msgAssumeFailDefault);
+            final CompletableFuture<Boolean> exploitActivityReturn = new CompletableFuture<>();
+            final String bcastActionFail = context.getString(R.string.bcastActionTestFail);
+            final String bcastActionPass = context.getString(R.string.bcastActionTestPass);
+            final String bcastActionAssumeFail =
+                    context.getString(R.string.bcastActionTestAssumeFail);
+
+            // Register a broadcast receiver to receive broadcast from ExploitActivity indicating
+            // presence of vulnerability
+            BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    try {
+                        if (intent.getAction().equals(bcastActionFail)) {
+                            exploitActivityReturn.complete(true);
+                        } else if (intent.getAction().equals(bcastActionPass)) {
+                            exploitActivityReturn.complete(false);
+                        } else if (intent.getAction().equals(bcastActionAssumeFail)) {
+                            // mAssumeFailMsg set here is used in assumeNoException() triggered
+                            // when exploitActivityReturn.get() raises a timeout exception
+                            mAssumeFailMsg = intent
+                                    .getStringExtra(context.getString(R.string.keyMsgAssumeFail));
+                        }
+                    } catch (Exception ignored) {
+                        // ignore the exceptions
+                    }
+                }
+            };
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(bcastActionFail);
+            filter.addAction(bcastActionPass);
+            filter.addAction(bcastActionAssumeFail);
+            context.registerReceiver(broadcastReceiver, filter);
+
+            // Write some data to the Uri content://authority/file_path/poc.txt
+            final String uriString = context.getString(R.string.contentUri);
+            try (OutputStream outputStream =
+                    context.getContentResolver().openOutputStream(Uri.parse(uriString));) {
+                outputStream.write(
+                        context.getString(R.string.fileContents).getBytes(StandardCharsets.UTF_8));
+            }
+
+            // Creating an intent to launch ExploitActivity
+            Intent intent = new Intent();
+            final String attackerPkg = context.getString(R.string.pkgAttacker);
+            final String exploitActivity = context.getString(R.string.activityExploit);
+            intent.setClassName(attackerPkg, exploitActivity);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Creating the inner intent for PendingIntent
+            Intent innerIntent = new Intent(Intent.ACTION_MAIN, Uri.parse(uriString));
+            innerIntent.setClassName(attackerPkg, exploitActivity);
+            innerIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            innerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Launch the ExploitActivity passing PendingIntent as data
+            intent.putExtra(context.getString(R.string.keyPendingIntent), PendingIntent
+                    .getActivity(context, 0, innerIntent, PendingIntent.FLAG_IMMUTABLE));
+            context.startActivity(intent);
+
+            // On vulnerable device, the PendingIntent launchIntentFlags will be added even though
+            // it is immutable, so the test should fail if the flags are found to take effect.
+            assertFalse(context.getString(R.string.msgFail),
+                    exploitActivityReturn.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        } catch (Exception e) {
+            assumeNoException(mAssumeFailMsg, e);
+        }
+    }
+}
diff --git a/hostsidetests/stagedinstall/Android.bp b/hostsidetests/stagedinstall/Android.bp
index 35850fe..e5d29ea 100644
--- a/hostsidetests/stagedinstall/Android.bp
+++ b/hostsidetests/stagedinstall/Android.bp
@@ -19,7 +19,7 @@
 java_test_host {
     name: "CtsStagedInstallHostTestCases",
     defaults: ["cts_defaults"],
-    srcs:  [
+    srcs: [
         "src/**/*.java",
         ":apex-info-list",
     ],
@@ -32,7 +32,7 @@
         "hamcrest-library",
     ],
     static_libs: ["cts-install-lib-host"],
-    data:   [
+    data: [
         ":StagedInstallTest",
         ":deapexer.zip",
     ],
@@ -45,9 +45,9 @@
 
 android_test_helper_app {
     name: "StagedInstallTest",
-    srcs:  ["app/src/**/*.java"],
-    manifest : "app/AndroidManifest.xml",
-    java_resources:  [
+    srcs: ["app/src/**/*.java"],
+    manifest: "app/AndroidManifest.xml",
+    java_resources: [
         ":ApexKeyRotationTestV2_SignedBob",
         ":ApexKeyRotationTestV2_SignedBobRot",
         ":ApexKeyRotationTestV2_SignedBobRotRollback",
@@ -87,25 +87,28 @@
 android_test_helper_app {
     name: "StagedInstallTestAppSamePackageNameAsApex",
 
-    srcs:   ["testdata/apk/src/**/*java"],
+    srcs: ["testdata/apk/src/**/*java"],
 
-    manifest:   "testdata/apk/StagedInstallTestAppSamePackageNameAsApex.xml",
+    manifest: "testdata/apk/StagedInstallTestAppSamePackageNameAsApex.xml",
 }
 
 prebuilt_apex {
     name: "ApexKeyRotationTestV2_SignedBob",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_signed_bob.apex",
@@ -116,16 +119,19 @@
     name: "ApexKeyRotationTestV2_SignedBobRot",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_signed_bob_rot.apex",
@@ -136,16 +142,19 @@
     name: "ApexKeyRotationTestV2_SignedBobRotRollback",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
@@ -156,16 +165,19 @@
     name: "ApexKeyRotationTestV3_SignedBob",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v3_signed_bob.apex",
@@ -176,16 +188,19 @@
     name: "ApexKeyRotationTestV3_SignedBobRot",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v3_signed_bob_rot.apex",
@@ -196,16 +211,19 @@
     name: "StagedInstallTestApexV1",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v1.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v1.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v1.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v1.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v1.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v1.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v1.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v1.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v1.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v1.apex",
@@ -216,16 +234,19 @@
     name: "StagedInstallTestApexV2",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2.apex",
@@ -236,16 +257,19 @@
     name: "StagedInstallTestApexV3",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v3.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v3.apex",
@@ -256,16 +280,19 @@
     name: "StagedInstallTestApexV2_AdditionalFile",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_file.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_file.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_file.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_additional_file.apex",
@@ -276,16 +303,19 @@
     name: "StagedInstallTestApexV2_AdditionalFolder",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_additional_folder.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_folder.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_additional_folder.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_additional_folder.apex",
@@ -296,16 +326,19 @@
     name: "StagedInstallTestApexV2_WithPostInstallHook",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_with_post_install_hook.apex",
@@ -316,16 +349,19 @@
     name: "StagedInstallTestApexV2_WithPreInstallHook",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_with_pre_install_hook.apex",
@@ -336,16 +372,19 @@
     name: "StagedInstallTestApexV2_WrongSha",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_wrong_sha.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_wrong_sha.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_wrong_sha.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_wrong_sha.apex",
@@ -356,16 +395,19 @@
     name: "StagedInstallTestApexV2_WithoutApkInApex",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_without_apk_in_apex.apex",
@@ -376,16 +418,19 @@
     name: "StagedInstallTestApexV1_NotPreInstalled",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim_not_pre_installed.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim_not_pre_installed.apex",
         },
     },
     filename: "com.android.apex.cts.shim_not_pre_installed.apex",
@@ -396,16 +441,19 @@
     name: "StagedInstallTestApexV2_DifferentCertificate",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_certificate.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_certificate.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_certificate.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_different_certificate.apex",
@@ -416,16 +464,19 @@
     name: "StagedInstallTestApexV2_DifferentPackageName",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_package_name.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_different_package_name.apex",
@@ -436,16 +487,19 @@
     name: "StagedInstallTestApexV2_NoHashtree",
     arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_no_hashtree.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex",
         },
     },
     filename: "com.android.apex.cts.shim.v2_no_hashtree.apex",
@@ -453,171 +507,188 @@
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestApexV2_SdkTargetP",
-  arch: {
+    name: "StagedInstallTestApexV2_SdkTargetP",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_sdk_target_p.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex",
         },
     },
-  filename: "com.android.apex.cts.shim.v2_sdk_target_p.apex",
-  installable: false,
+    filename: "com.android.apex.cts.shim.v2_sdk_target_p.apex",
+    installable: false,
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestApexV2_ApkInApexSdkTargetP",
-  arch: {
+    name: "StagedInstallTestApexV2_ApkInApexSdkTargetP",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
         },
     },
-  filename: "com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
-  installable: false,
+    filename: "com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex",
+    installable: false,
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestCorruptedApex_b146895998",
-  src: "testdata/apex/corrupted_b146895998.apex",
-  filename: "corrupted_b146895998.apex",
-  installable: false,
+    name: "StagedInstallTestCorruptedApex_b146895998",
+    src: "testdata/apex/corrupted_b146895998.apex",
+    filename: "corrupted_b146895998.apex",
+    installable: false,
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestApexV2_NoApkSignature",
-  arch: {
+    name: "StagedInstallTestApexV2_NoApkSignature",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
         },
     },
-  filename: "com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
-  installable: false,
+    filename: "com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
+    installable: false,
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestApexV2_UnsignedPayload",
-  arch: {
+    name: "StagedInstallTestApexV2_UnsignedPayload",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_payload.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex",
         },
     },
-  filename: "com.android.apex.cts.shim.v2_unsigned_payload.apex",
-  installable: false,
+    filename: "com.android.apex.cts.shim.v2_unsigned_payload.apex",
+    installable: false,
 }
 
-ApexFilenameSigningPayloadWithDifferentKey =
-  "com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
+ApexFilenameSigningPayloadWithDifferentKey = "com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
 prebuilt_apex {
-  name: "StagedInstallTestApexV2_SignPayloadWithDifferentKey",
-  arch: {
+    name: "StagedInstallTestApexV2_SignPayloadWithDifferentKey",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/" + ApexFilenameSigningPayloadWithDifferentKey,
+            src: "testdata/apex/arm/" + ApexFilenameSigningPayloadWithDifferentKey,
         },
         arm64: {
-              src: "testdata/apex/arm/" + ApexFilenameSigningPayloadWithDifferentKey,
+            src: "testdata/apex/arm/" + ApexFilenameSigningPayloadWithDifferentKey,
         },
         x86: {
-              src: "testdata/apex/x86/" + ApexFilenameSigningPayloadWithDifferentKey,
+            src: "testdata/apex/x86/" + ApexFilenameSigningPayloadWithDifferentKey,
         },
         x86_64: {
-              src: "testdata/apex/x86/" + ApexFilenameSigningPayloadWithDifferentKey,
+            src: "testdata/apex/x86/" + ApexFilenameSigningPayloadWithDifferentKey,
         },
     },
-  filename: ApexFilenameSigningPayloadWithDifferentKey,
-  installable: false,
+    filename: ApexFilenameSigningPayloadWithDifferentKey,
+    installable: false,
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestApexV2_Rebootless",
-  arch: {
+    name: "StagedInstallTestApexV2_Rebootless",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v2_rebootless.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v2_rebootless.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v2_rebootless.apex",
         },
     },
-  filename: "com.android.apex.cts.shim.v2_rebootless.apex",
-  installable: false,
+    filename: "com.android.apex.cts.shim.v2_rebootless.apex",
+    installable: false,
 }
 
 prebuilt_apex {
-  name: "StagedInstallTestApexV3_Rebootless",
-  arch: {
+    name: "StagedInstallTestApexV3_Rebootless",
+    arch: {
         arm: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex",
         },
         arm64: {
-              src: "testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex",
+            src: "testdata/apex/arm/com.android.apex.cts.shim.v3_rebootless.apex",
+        },
+        riscv64: {
+            src: "testdata/apex/riscv64/com.android.apex.cts.shim.v3_rebootless.apex",
         },
         x86: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex",
         },
         x86_64: {
-              src: "testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex",
+            src: "testdata/apex/x86/com.android.apex.cts.shim.v3_rebootless.apex",
         },
     },
-  filename: "com.android.apex.cts.shim.v3_rebootless.apex",
-  installable: false,
+    filename: "com.android.apex.cts.shim.v3_rebootless.apex",
+    installable: false,
 }
 
 // collects deapexer and its dependency modules (libc++ and debugfs_static) to the zip file.
 genrule {
-  name: "deapexer.zip",
-  tools: [
-      "blkid",
-      "deapexer",
-      "debugfs_static",
-      "fsck.erofs",
-      "soong_zip",
-  ],
-  cmd: "rm -rf mkdir $(genDir)/deapexer && mkdir $(genDir)/deapexer && " +
-       "cp $(location deapexer) $(genDir)/deapexer && " +
-       "cp $(location debugfs_static) $(genDir)/deapexer && " +
-       "cp $(location blkid) $(genDir)/deapexer && " +
-       "cp $(location fsck.erofs) $(genDir)/deapexer && " +
-       "HOST_OUT_SHARED_LIBRARIES=$$(dirname $(location deapexer))/../lib64 && " +
-       "cp $${HOST_OUT_SHARED_LIBRARIES}/libc++.* $(genDir)/deapexer && " +
-       "$(location soong_zip) -o $(out) -C $(genDir)/deapexer -D $(genDir)/deapexer",
-  out: ["deapexer.zip"],
+    name: "deapexer.zip",
+    tools: [
+        "blkid",
+        "deapexer",
+        "debugfs_static",
+        "fsck.erofs",
+        "soong_zip",
+    ],
+    cmd: "rm -rf mkdir $(genDir)/deapexer && mkdir $(genDir)/deapexer && " +
+        "cp $(location deapexer) $(genDir)/deapexer && " +
+        "cp $(location debugfs_static) $(genDir)/deapexer && " +
+        "cp $(location blkid) $(genDir)/deapexer && " +
+        "cp $(location fsck.erofs) $(genDir)/deapexer && " +
+        "HOST_OUT_SHARED_LIBRARIES=$$(dirname $(location deapexer))/../lib64 && " +
+        "cp $${HOST_OUT_SHARED_LIBRARIES}/libc++.* $(genDir)/deapexer && " +
+        "$(location soong_zip) -o $(out) -C $(genDir)/deapexer -D $(genDir)/deapexer",
+    out: ["deapexer.zip"],
 }
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 c2dc28f..1274c4b 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 880ab4a..2369c77 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 8c84cd5..2cca9dd 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 b519bbe..af85a7d 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 38e2339..35cb546 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_apk_in_apex_upgrades.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
index 3d7bf51..713a82d 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.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 f4bc7e8..feffcca 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 59e9fe1..f5ca900 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_install_constraints_empty.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_empty.apex
new file mode 100644
index 0000000..83aca07
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_empty.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex
new file mode 100644
index 0000000..c8dde26
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_no_value.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_no_value.apex
new file mode 100644
index 0000000..7c47384
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_install_constraints_no_value.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 353949b..fdb6dc9 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 c39b790..1254cff 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 da25328..d998bbc 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 3eaf372..568de83 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 6f38273..c33182a 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 1969746..e3c1fcf 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 be642bf..3dd9ac2 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_apk_container.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
index b8444ba..370b3d7 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.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 7bebb77..7af5095 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 8006022..62a0a32 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 3465dbb..7052ce3 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 67743a9..e0a89c9 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 aa1c10c..0a1cec4 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 b345bca..a9dc78f 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
index c3bab7c..e71e3f2 100644
--- 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
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 4733bad..984272f 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 6972daa..4e97e20 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 4cda1c6..deb1d5e 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/riscv64/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v1.apex
new file mode 100644
index 0000000..1984240
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2.apex
new file mode 100644
index 0000000..637abc0
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_file.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_file.apex
new file mode 100644
index 0000000..ea9dbbd
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_folder.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_folder.apex
new file mode 100644
index 0000000..efac704
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
new file mode 100644
index 0000000..ade5ad1
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
new file mode 100644
index 0000000..08785ca
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_certificate.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_certificate.apex
new file mode 100644
index 0000000..4c109f0
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_package_name.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_package_name.apex
new file mode 100644
index 0000000..45f60a5
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_empty.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_empty.apex
new file mode 100644
index 0000000..6cd415b
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_empty.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex
new file mode 100644
index 0000000..430e8c6
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex
new file mode 100644
index 0000000..0e26797
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_install_constraints_no_value.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_no_hashtree.apex
new file mode 100644
index 0000000..ef6212f
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_rebootless.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_rebootless.apex
new file mode 100644
index 0000000..eb8292a
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_rebootless.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_sdk_target_p.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_sdk_target_p.apex
new file mode 100644
index 0000000..c2a48dc
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
new file mode 100644
index 0000000..46d091f
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob.apex
new file mode 100644
index 0000000..e7072f2
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot.apex
new file mode 100644
index 0000000..328727c
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
new file mode 100644
index 0000000..cfef97d
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
new file mode 100644
index 0000000..39fcd46
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_payload.apex
new file mode 100644
index 0000000..2c2f241
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_post_install_hook.apex
new file mode 100644
index 0000000..d8854ae
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
new file mode 100644
index 0000000..0d3e037
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
new file mode 100644
index 0000000..e71c663
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_wrong_sha.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_wrong_sha.apex
new file mode 100644
index 0000000..450c743
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3.apex
new file mode 100644
index 0000000..47d022f
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_rebootless.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_rebootless.apex
new file mode 100644
index 0000000..ec35273
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_rebootless.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob.apex
new file mode 100644
index 0000000..784b55c
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob_rot.apex
new file mode 100644
index 0000000..6dde66f
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim_not_pre_installed.apex b/hostsidetests/stagedinstall/testdata/apex/riscv64/com.android.apex.cts.shim_not_pre_installed.apex
new file mode 100644
index 0000000..0c76bca
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/riscv64/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 030c53b..758b0279 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 b090a96..1437186 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 c498b32..23368d4 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 e83ec07..45f5234 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 4545b1c..67fd560 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_apk_in_apex_upgrades.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
index 298fd85..b9c48e6 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.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 d911fe0..c0542ec 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 053df91a..cc00cd0 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_install_constraints_empty.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_empty.apex
new file mode 100644
index 0000000..5b91151
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_empty.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex
new file mode 100644
index 0000000..977e217
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_invalid_fingerprint.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_no_value.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_no_value.apex
new file mode 100644
index 0000000..39ed540
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_install_constraints_no_value.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 65a5473..e2e974d 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 9f94684..d8d0427 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 8fd510c..3a92d62 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 baae3e3..40fef27 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 1e80788..f640f86 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 c064928..a7aff9d 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 685f347..9cee267 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_apk_container.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
index 07b8a6f..995a16d 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.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 f2329ae..dcc7f77 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 bb2d96e..4651714 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 fd00bd5..8f51e35 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 e7da653..8c72ec1 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 32bf141..ac93bd8 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 1bd8b1b..d76c6d2 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
index 2f7a2e5..faf38cc 100644
--- 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
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 38fe019..9d9e490 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 68505d5..f76aa01 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 7fd07b5..128fb8f 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 3d01f0e..bbdc41e 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/riscv64/CtsShimTargetPSdk.apk b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/riscv64/CtsShimTargetPSdk.apk
new file mode 100644
index 0000000..bbdc41e
--- /dev/null
+++ b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/riscv64/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 3d01f0e..bbdc41e 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/statsdatom/Android.bp b/hostsidetests/statsdatom/Android.bp
index 2856626..0bf408a 100644
--- a/hostsidetests/statsdatom/Android.bp
+++ b/hostsidetests/statsdatom/Android.bp
@@ -42,6 +42,7 @@
         "src/**/net/*.java",
         "src/**/notification/*.java",
         "src/**/perfetto/*.java",
+        "src/**/performancehintmanager/*.java",
         "src/**/permissionstate/*.java",
         "src/**/settingsstats/*.java",
         "src/**/sizecompatrestartbutton/*.java",
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index 05954a6..772e9a9 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -20,6 +20,8 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertNotNull;
+
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.app.ActivityManager;
@@ -62,6 +64,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.PerformanceHintManager;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
@@ -1182,4 +1185,18 @@
         GameManager gameManager = context.getSystemService(GameManager.class);
         gameManager.setGameState(new GameState(true, GameState.MODE_CONTENT, 1, 2));
     }
+
+    @Test
+    public void testCreateHintSession() throws Exception {
+        final long targetNs = 16666666L;
+        Context context = InstrumentationRegistry.getContext();
+        PerformanceHintManager phm = context.getSystemService(PerformanceHintManager.class);
+
+        assertNotNull(phm);
+
+        PerformanceHintManager.Session session =
+                phm.createHintSession(new int[]{Process.myPid()}, targetNs);
+
+        assertNotNull(session);
+    }
 }
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/performancehintmanager/PerformanceHintManagerStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/performancehintmanager/PerformanceHintManagerStatsTests.java
new file mode 100644
index 0000000..fe1378d
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/performancehintmanager/PerformanceHintManagerStatsTests.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2022 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.cts.statsdatom.performancehintmanager;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.cts.statsdatom.lib.AtomTestUtils;
+import android.cts.statsdatom.lib.ConfigUtils;
+import android.cts.statsdatom.lib.DeviceUtils;
+import android.cts.statsdatom.lib.ReportUtils;
+
+import com.android.os.AtomsProto;
+import com.android.os.StatsLog;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.util.List;
+
+/**
+ * Test for Performance Hint Manager stats.
+ * This test is mainly to test ADPF data collection
+ *
+ *  <p>Build/Install/Run:
+ *  atest CtsStatsdAtomHostTestCases:PerformanceHintManagerStatsTests
+ */
+public class PerformanceHintManagerStatsTests extends DeviceTestCase implements IBuildReceiver {
+    private IBuildInfo mCtsBuild;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        assertThat(mCtsBuild).isNotNull();
+        ConfigUtils.removeConfig(getDevice());
+        ReportUtils.clearReports(getDevice());
+        DeviceUtils.installStatsdTestApp(getDevice(), mCtsBuild);
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        ConfigUtils.removeConfig(getDevice());
+        ReportUtils.clearReports(getDevice());
+        DeviceUtils.uninstallStatsdTestApp(getDevice());
+        super.tearDown();
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    public void testCreateHintSessionStatsd() throws Exception {
+        if (Boolean.parseBoolean(
+                DeviceUtils.getProperty(getDevice(), "debug.hwui.use_hint_manager"))) {
+            ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
+                    AtomsProto.Atom.PERFORMANCE_HINT_SESSION_REPORTED_FIELD_NUMBER);
+            DeviceUtils.runDeviceTestsOnStatsdApp(getDevice(),
+                    ".AtomTests", "testCreateHintSession");
+            Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+            List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+            assertThat(data.size()).isAtLeast(1);
+            AtomsProto.PerformanceHintSessionReported a0 =
+                    data.get(0).getAtom().getPerformanceHintSessionReported();
+            assertThat(a0.getPackageUid()).isGreaterThan(10000);  // Not a system service UID.
+            assertThat(a0.getSessionId()).isNotEqualTo(0);
+            assertThat(a0.getTargetDurationNs()).isEqualTo(16666666L);
+            assertThat(a0.getTidCount()).isEqualTo(1);
+        }
+    }
+
+    public void testAdpfSystemComponentStatsd() throws Exception {
+        final boolean isSurfaceFlingerCpuHintEnabled = Boolean.parseBoolean(
+                DeviceUtils.getProperty(getDevice(), "debug.sf.enable_adpf_cpu_hint"));
+        final boolean isHwuiHintEnabled = Boolean.parseBoolean(
+                DeviceUtils.getProperty(getDevice(), "debug.hwui.use_hint_manager"));
+        ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
+                AtomsProto.Atom.ADPF_SYSTEM_COMPONENT_INFO_FIELD_NUMBER);
+        AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+
+        List<AtomsProto.Atom> data = ReportUtils.getGaugeMetricAtoms(getDevice());
+        assertThat(data.size()).isAtLeast(1);
+        AtomsProto.ADPFSystemComponentInfo a0 = data.get(0).getAdpfSystemComponentInfo();
+        assertThat(a0.getSurfaceflingerCpuHintEnabled()).isEqualTo(isSurfaceFlingerCpuHintEnabled);
+        assertThat(a0.getHwuiHintEnabled()).isEqualTo(isHwuiHintEnabled);
+    }
+}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/OWNERS
index 7710944..6601b06 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/OWNERS
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/wifi/OWNERS
@@ -1,3 +1,5 @@
 narcisaam@google.com
 dorindrimus@google.com
 vtrifonov@google.com
+afaraone@google.com
+leoneljeronimo@google.com
diff --git a/hostsidetests/sustainedperf/shadertoy_android/jni/shadertoy_renderer.cpp b/hostsidetests/sustainedperf/shadertoy_android/jni/shadertoy_renderer.cpp
index 7718784..a4bafdd 100644
--- a/hostsidetests/sustainedperf/shadertoy_android/jni/shadertoy_renderer.cpp
+++ b/hostsidetests/sustainedperf/shadertoy_android/jni/shadertoy_renderer.cpp
@@ -90,7 +90,6 @@
   static double previous_time = 0;

   static float angle = 0.0f;

   static double elapsed_time_sum = 0;

-  static double gpu_timer_elapsed_sum = 0;

   static double start_time = NowInMs();

 

   // After how many frames to report the avg frame time.

@@ -103,7 +102,6 @@
 

     frame_count = 0;

     elapsed_time_sum = 0;

-    gpu_timer_elapsed_sum = 0;

   }

 

   double current_time = NowInMs();

diff --git a/libs/json/Android.bp b/libs/json/Android.bp
index 0dc0090..e96b486 100644
--- a/libs/json/Android.bp
+++ b/libs/json/Android.bp
@@ -23,6 +23,8 @@
     host_supported: true,
     srcs: ["src/**/*.java"],
     sdk_version: "current",
+    // b/267831518: Pin tradefed and dependencies to Java 11.
+    java_version: "11",
 }
 
 // Compatibility version of host library
diff --git a/libs/testserver/OWNERS b/libs/testserver/OWNERS
new file mode 100644
index 0000000..649a01d
--- /dev/null
+++ b/libs/testserver/OWNERS
@@ -0,0 +1 @@
+file:platform/external/cronet:master:/OWNERS
diff --git a/libs/testserver/src/android/webkit/cts/CtsTestServer.java b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
index 0d3292b..f004a7c 100644
--- a/libs/testserver/src/android/webkit/cts/CtsTestServer.java
+++ b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
@@ -103,6 +103,8 @@
     public static final String USERAGENT_PATH = "/useragent.html";
 
     public static final String TEST_DOWNLOAD_PATH = "/download.html";
+    public static final String CACHEABLE_TEST_DOWNLOAD_PATH =
+            "/cacheable-download.html";
     private static final String DOWNLOAD_ID_PARAMETER = "downloadId";
     private static final String NUM_BYTES_PARAMETER = "numBytes";
 
@@ -113,6 +115,7 @@
     private static final String APPCACHE_MANIFEST_PATH = "/appcache.manifest";
     private static final String REDIRECT_PREFIX = "/redirect";
     private static final String QUERY_REDIRECT_PATH = "/alt_redirect";
+    private static final String ECHO_HEADERS_PREFIX = "/echo_headers";
     private static final String DELAY_PREFIX = "/delayed";
     private static final String BINARY_PREFIX = "/binary";
     private static final String SET_COOKIE_PREFIX = "/setcookie";
@@ -122,6 +125,8 @@
     public static final String NOLENGTH_POSTFIX = "nolength";
     private static final int DELAY_MILLIS = 2000;
 
+    public static final String ECHOED_RESPONSE_HEADER_PREFIX = "x-request-header-";
+
     public static final String AUTH_REALM = "Android CTS";
     public static final String AUTH_USER = "cts";
     public static final String AUTH_PASS = "secret";
@@ -364,6 +369,14 @@
     }
 
     /**
+     * Return an absolute URL that refers to an endpoint which will send received headers back to
+     * the sender with a prefix.
+     */
+    public String getEchoHeadersUrl() {
+        return getBaseUri() + ECHO_HEADERS_PREFIX;
+    }
+
+    /**
      * Return an absolute URL that indirectly refers to the given asset.
      * When a client fetches this URL, the server will respond with a temporary redirect (302)
      * referring to the absolute URL of the given asset.
@@ -507,6 +520,21 @@
     }
 
     /**
+     * @param downloadId used to differentiate the files created for each test
+     * @param numBytes of the content that the CTS server should send back
+     * @return url to get the file from
+     */
+    public String getCacheableTestDownloadUrl(String downloadId, int numBytes) {
+        return Uri.parse(getBaseUri())
+                .buildUpon()
+                .path(CACHEABLE_TEST_DOWNLOAD_PATH)
+                .appendQueryParameter(DOWNLOAD_ID_PARAMETER, downloadId)
+                .appendQueryParameter(NUM_BYTES_PARAMETER, Integer.toString(numBytes))
+                .build()
+                .toString();
+    }
+
+    /**
      * Returns true if the resource identified by url has been requested since
      * the server was started or the last call to resetRequestState().
      *
@@ -618,6 +646,14 @@
         URI uri = URI.create(uriString);
         String path = uri.getPath();
         String query = uri.getQuery();
+
+        if (path.startsWith(ECHO_HEADERS_PREFIX)) {
+            response = createResponse(HttpStatus.SC_OK);
+            for (Header header : request.getAllHeaders()) {
+                response.addHeader(
+                        ECHOED_RESPONSE_HEADER_PREFIX + header.getName(), header.getValue());
+            }
+        }
         if (path.equals(FAVICON_PATH)) {
             path = FAVICON_ASSET_PATH;
         }
@@ -715,10 +751,23 @@
             Log.i(TAG, "Redirecting to: " + location);
             response.addHeader("Location", location);
         } else if (path.equals(QUERY_REDIRECT_PATH)) {
-            String location = Uri.parse(uriString).getQueryParameter("dest");
+            Uri androidUri = Uri.parse(uriString);
+            String location = androidUri.getQueryParameter("dest");
+
+            int statusCode = HttpStatus.SC_MOVED_TEMPORARILY;
+            String statusCodeParam = androidUri.getQueryParameter("statusCode");
+            if (statusCodeParam != null) {
+                try {
+                    int parsedStatusCode = Integer.parseInt(statusCodeParam);
+                    if (300 <= parsedStatusCode && parsedStatusCode < 400) {
+                        statusCode = parsedStatusCode;
+                    }
+                } catch (NumberFormatException ignored) { }
+            }
+
             if (location != null) {
                 Log.i(TAG, "Redirecting to: " + location);
-                response = createResponse(HttpStatus.SC_MOVED_TEMPORARILY);
+                response = createResponse(statusCode);
                 response.addHeader("Location", location);
             }
         } else if (path.startsWith(COOKIE_PREFIX)) {
@@ -773,6 +822,8 @@
             response.setEntity(createPage(agent, agent));
         } else if (path.equals(TEST_DOWNLOAD_PATH)) {
             response = createTestDownloadResponse(mContext, Uri.parse(uriString));
+        } else if (path.equals(CACHEABLE_TEST_DOWNLOAD_PATH)) {
+            response = createCacheableTestDownloadResponse(mContext, Uri.parse(uriString));
         } else if (path.equals(APPCACHE_PATH)) {
             response = createResponse(HttpStatus.SC_OK);
             response.setEntity(createEntity("<!DOCTYPE HTML>" +
@@ -885,6 +936,13 @@
         return response;
     }
 
+    private static HttpResponse createCacheableTestDownloadResponse(Context context, Uri uri)
+            throws IOException {
+        HttpResponse response = createTestDownloadResponse(context, uri);
+        response.setHeader("Cache-Control", "max-age=300");
+        return response;
+    }
+
     private static FileEntity createFileEntity(Context context, String downloadId, int numBytes)
             throws IOException {
         String storageState = Environment.getExternalStorageState();
@@ -1136,13 +1194,21 @@
                     HttpResponse response = mServer.getResponse(mRequest);
                     mConnection.sendResponseHeader(response);
                     mConnection.sendResponseEntity(response);
-                    mConnection.close();
+                } catch (Exception e) {
+                    Log.e(TAG, "Error handling request:", e);
+                } finally {
+                    try {
+                        mConnection.close();
+                    } catch (IOException e) {
+                        Log.e(TAG, "Failed to close http connection", e);
+                    }
 
+                    // mConnection.close() closes mSocket.
+                    // mConnection only throws an IOException when the socket.close() call fails, at
+                    // which point, there is not much that can be done anyways.
                     synchronized(mLock) {
                         ServerThread.this.mSockets.remove(mSocket);
                     }
-                } catch (Exception e) {
-                    Log.e(TAG, "Error handling request:", e);
                 }
             }
         }
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index 5789a60..b7fc539 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -19,6 +19,7 @@
 import static android.app.job.JobInfo.NETWORK_TYPE_ANY;
 import static android.app.job.JobInfo.NETWORK_TYPE_NONE;
 import static android.jobscheduler.cts.TestAppInterface.TEST_APP_PACKAGE;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
 import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
 
 import static com.android.compatibility.common.util.TestUtils.waitUntil;
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index e3a3a41..7644c40 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -52,6 +52,7 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -279,6 +280,7 @@
     }
 
     @Test
+    @Ignore("Ignored in Android T becauase this changed between T and U")
     public void testUriAccessWithInvalidProjection() throws Exception {
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
 
@@ -290,8 +292,8 @@
         final ContentResolver resolver = mContext.getContentResolver();
 
         assertThrows(IllegalArgumentException.class, () -> resolver.query(
-                        clipData.getItemAt(0).getUri(),
-                        new String[] {MediaStore.MediaColumns.RELATIVE_PATH}, null, null));
+            clipData.getItemAt(0).getUri(),
+            new String[] {MediaStore.MediaColumns.RELATIVE_PATH}, null, null));
     }
 
     @Test
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
index d20dcd6..7ffe3e3 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
@@ -46,8 +46,7 @@
      */
     public static List<UiObject> findItemList(int itemCount) throws Exception {
         final List<UiObject> itemList = new ArrayList<>();
-        final UiSelector gridList = new UiSelector().className(
-                "androidx.recyclerview.widget.RecyclerView").resourceIdMatches(
+        final UiSelector gridList = new UiSelector().resourceIdMatches(
                 REGEX_PACKAGE_NAME + ":id/picker_tab_recyclerview");
 
         // Wait for the first item to appear
diff --git a/tests/accessibilityservice/Android.bp b/tests/accessibilityservice/Android.bp
index 876da5a..9e891ee 100644
--- a/tests/accessibilityservice/Android.bp
+++ b/tests/accessibilityservice/Android.bp
@@ -27,6 +27,7 @@
         "platform-test-annotations",
         "CtsAccessibilityCommon",
         "CtsInputMethodServiceCommon",
+        "sts-device-util",
     ],
     libs: [
         "android.test.runner",
@@ -37,10 +38,12 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     sdk_version: "test_current",
     per_testcase_directory: true,
     data: [
         ":CtsInputMethod1",
+        ":CtsAccessibilityMultipleServicesApp",
         ":CtsAccessibilityWidgetProvider"],
 }
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 3bde0fd..ad7994e 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -27,6 +27,8 @@
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
 
+    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
+
     <application android:theme="@android:style/Theme.Holo.NoActionBar"
          android:requestLegacyExternalStorage="true">
 
diff --git a/tests/accessibilityservice/AndroidTest.xml b/tests/accessibilityservice/AndroidTest.xml
index 48aea2c..8096d29 100644
--- a/tests/accessibilityservice/AndroidTest.xml
+++ b/tests/accessibilityservice/AndroidTest.xml
@@ -24,6 +24,11 @@
         <option name="run-command" value="cmd accessibility set-bind-instant-service-allowed true" />
         <option name="teardown-command" value="cmd accessibility set-bind-instant-service-allowed false" />
     </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="CtsAccessibilityMultipleServicesApp.apk"
+            value="/data/local/tmp/cts/content/CtsAccessibilityMultipleServicesApp.apk" />
+    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAccessibilityServiceTestCases.apk" />
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 5f9733c..52fb4c37 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -17,7 +17,9 @@
 package android.accessibilityservice.cts;
 
 import static android.Manifest.permission.POST_NOTIFICATIONS;
+import static android.accessibility.cts.common.InstrumentedAccessibilityService.TIMEOUT_SERVICE_ENABLE;
 import static android.accessibility.cts.common.InstrumentedAccessibilityService.enableService;
+import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
 import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterForEventType;
 import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterForEventTypeWithAction;
 import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterForEventTypeWithResource;
@@ -76,7 +78,9 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
 import android.util.Log;
@@ -99,6 +103,9 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.CtsMouseUtil;
+import com.android.compatibility.common.util.ShellUtils;
+import com.android.compatibility.common.util.TestUtils;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
 
 import org.junit.After;
 import org.junit.AfterClass;
@@ -120,7 +127,7 @@
  * are generated and their correct dispatch verified.
  */
 @RunWith(AndroidJUnit4.class)
-public class AccessibilityEndToEndTest {
+public class AccessibilityEndToEndTest extends StsExtraBusinessLogicTestCase {
 
     private static final String LOG_TAG = "AccessibilityEndToEndTest";
 
@@ -1013,6 +1020,71 @@
         }
     }
 
+    @AsbSecurityTest(cveBugId = {243378132})
+    @Test
+    public void testUninstallPackage_DisablesMultipleServices() throws Exception {
+        final String apkPath =
+                "/data/local/tmp/cts/content/CtsAccessibilityMultipleServicesApp.apk";
+        final String packageName = "foo.bar.multipleservices";
+        final ComponentName service1 = ComponentName.createRelative(packageName, ".StubService1");
+        final ComponentName service2 = ComponentName.createRelative(packageName, ".StubService2");
+        // Match AccessibilityManagerService#COMPONENT_NAME_SEPARATOR
+        final String componentNameSeparator = ":";
+
+        final String originalEnabledServicesSetting = getEnabledServicesSetting();
+
+        try {
+            // Install the apk in this test method, instead of as part of the target preparer, to
+            // allow repeated --iterations of the test.
+            com.google.common.truth.Truth.assertThat(
+                    ShellUtils.runShellCommand("pm install " + apkPath)).startsWith("Success");
+
+            // Enable the two services and wait until AccessibilityManager reports them as enabled.
+            final String servicesToEnable = getEnabledServicesSetting() + componentNameSeparator
+                    + service1.flattenToShortString() + componentNameSeparator
+                    + service2.flattenToShortString();
+            ShellCommandBuilder.create(sInstrumentation)
+                    .putSecureSetting(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                            servicesToEnable)
+                    .putSecureSetting(Settings.Secure.ACCESSIBILITY_ENABLED, "1")
+                    .run();
+            TestUtils.waitUntil("Failed to enable 2 services from package " + packageName,
+                    (int) TIMEOUT_SERVICE_ENABLE / 1000,
+                    () -> getEnabledServices().stream().filter(
+                            info -> info.getId().startsWith(packageName)).count() == 2);
+
+            // Uninstall the package that contains the services.
+            com.google.common.truth.Truth.assertThat(
+                    ShellUtils.runShellCommand("pm uninstall " + packageName)).startsWith(
+                    "Success");
+
+            // Ensure the uninstall removed the services from the secure setting.
+            TestUtils.waitUntil(
+                    "Failed to disable services after uninstalling package " + packageName,
+                    (int) TIMEOUT_SERVICE_ENABLE / 1000,
+                    () -> !getEnabledServicesSetting().contains(packageName));
+        } finally {
+            ShellCommandBuilder.create(sInstrumentation)
+                    .putSecureSetting(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                            originalEnabledServicesSetting)
+                    .run();
+            ShellUtils.runShellCommand("pm uninstall " + packageName);
+        }
+    }
+
+    private List<AccessibilityServiceInfo> getEnabledServices() {
+        return ((AccessibilityManager) sInstrumentation.getContext().getSystemService(
+                Context.ACCESSIBILITY_SERVICE)).getEnabledAccessibilityServiceList(
+                FEEDBACK_ALL_MASK);
+    }
+
+    private String getEnabledServicesSetting() {
+        final String result = Settings.Secure.getString(
+                sInstrumentation.getContext().getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+        return result != null ? result : "";
+    }
+
     private static void assertPackageName(AccessibilityNodeInfo node, String packageName) {
         if (node == null) {
             return;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
index e36d1ee..64cc0f1 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
@@ -90,9 +91,10 @@
 
     @Test
     public void testGestureDetectionListener_whenAuthenticationStartsAndStops_calledBack() {
-        if (!mFingerprintGestureController.isGestureDetectionAvailable()) {
-            return;
-        }
+        assumeTrue("Fingerprint gesture detection is not available",
+                mFingerprintGestureController.isGestureDetectionAvailable());
+        assumeTrue("No enrolled fingerprints; cannot open fingerprint prompt",
+                mFingerprintManager.hasEnrolledFingerprints());
         // Launch an activity to make sure we're in the foreground
         mActivityRule.launchActivity(null);
         mFingerprintGestureController.registerFingerprintGestureCallback(
diff --git a/tests/accessibilityservice/test-apps/MultipleServicesApp/Android.bp b/tests/accessibilityservice/test-apps/MultipleServicesApp/Android.bp
new file mode 100644
index 0000000..d8fdbce
--- /dev/null
+++ b/tests/accessibilityservice/test-apps/MultipleServicesApp/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2022 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"],
+}
+
+android_test_helper_app {
+    name: "CtsAccessibilityMultipleServicesApp",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    sdk_version: "test_current",
+}
diff --git a/tests/accessibilityservice/test-apps/MultipleServicesApp/AndroidManifest.xml b/tests/accessibilityservice/test-apps/MultipleServicesApp/AndroidManifest.xml
new file mode 100644
index 0000000..649478e
--- /dev/null
+++ b/tests/accessibilityservice/test-apps/MultipleServicesApp/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="foo.bar.multipleservices"
+     android:targetSandboxVersion="2">
+    <application>
+        <service android:name="foo.bar.multipleservices.StubService1"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService"/>
+            </intent-filter>
+            <meta-data android:name="android.accessibilityservice"
+                android:resource="@xml/stub_service"/>
+        </service>
+        <service android:name="foo.bar.multipleservices.StubService2"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService"/>
+            </intent-filter>
+            <meta-data android:name="android.accessibilityservice"
+                android:resource="@xml/stub_service"/>
+        </service>
+    </application>
+</manifest>
diff --git a/tests/accessibilityservice/test-apps/MultipleServicesApp/res/xml/stub_service.xml b/tests/accessibilityservice/test-apps/MultipleServicesApp/res/xml/stub_service.xml
new file mode 100644
index 0000000..0cbd139
--- /dev/null
+++ b/tests/accessibilityservice/test-apps/MultipleServicesApp/res/xml/stub_service.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/accessibilityservice/test-apps/MultipleServicesApp/src/foo/bar/multipleservices/StubService1.java
similarity index 60%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/accessibilityservice/test-apps/MultipleServicesApp/src/foo/bar/multipleservices/StubService1.java
index 1a335c7..022f6e1 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/accessibilityservice/test-apps/MultipleServicesApp/src/foo/bar/multipleservices/StubService1.java
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package foo.bar.multipleservices;
 
-import android.app.Activity;
+import android.accessibilityservice.AccessibilityService;
+import android.view.accessibility.AccessibilityEvent;
 
-public class PocActivity extends Activity {
+/** A stub accessibility service for testing package uninstall. */
+public class StubService1 extends AccessibilityService {
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {}
+
+    @Override
+    public void onInterrupt() {}
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/accessibilityservice/test-apps/MultipleServicesApp/src/foo/bar/multipleservices/StubService2.java
similarity index 60%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/accessibilityservice/test-apps/MultipleServicesApp/src/foo/bar/multipleservices/StubService2.java
index 1a335c7..28353c2 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/accessibilityservice/test-apps/MultipleServicesApp/src/foo/bar/multipleservices/StubService2.java
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package foo.bar.multipleservices;
 
-import android.app.Activity;
+import android.accessibilityservice.AccessibilityService;
+import android.view.accessibility.AccessibilityEvent;
 
-public class PocActivity extends Activity {
+/** A stub accessibility service for testing package uninstall. */
+public class StubService2 extends AccessibilityService {
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {}
+
+    @Override
+    public void onInterrupt() {}
 }
diff --git a/tests/app/src/android/app/cts/NotificationTemplateTest.kt b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
index cd1de26..f654724 100644
--- a/tests/app/src/android/app/cts/NotificationTemplateTest.kt
+++ b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
@@ -300,9 +300,6 @@
         checkViews(builder.createBigContentView()) {
             val pictureView = requireViewByIdName<ImageView>("big_picture")
             assertThat(pictureView.visibility).isEqualTo(View.VISIBLE)
-            assertThat(pictureView.width.toFloat())
-                    .isWithin(1f)
-                    .of((pictureView.height * 4 / 3).toFloat())
             assertThat(pictureView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
         }
     }
diff --git a/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt b/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt
index 452530e..1b03bd0 100644
--- a/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt
+++ b/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt
@@ -92,7 +92,7 @@
     }
 
     @Test
-    @Ignore("b/236292909")
+    @Ignore("b/252781795")
     fun closeToSender_displaysChip() {
         statusBarManager.updateMediaTapToTransferReceiverDisplay(
             StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER,
@@ -108,7 +108,7 @@
     }
 
     @Test
-    @Ignore("b/236292909")
+    @Ignore("b/252781795")
     fun farFromSender_hidesChip() {
         // First, make sure we display the chip
         statusBarManager.updateMediaTapToTransferReceiverDisplay(
diff --git a/tests/aslr/TEST_MAPPING b/tests/aslr/TEST_MAPPING
index ee44915..2bbf9d2 100644
--- a/tests/aslr/TEST_MAPPING
+++ b/tests/aslr/TEST_MAPPING
@@ -3,5 +3,16 @@
     {
       "name": "CtsAslrMallocTestCases"
     }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "CtsAslrMallocTestCases",
+      "options": [
+        {
+          // TODO(b/254683164)
+          "exclude-filter": "AslrMallocTest#testMallocRandomization"
+        }
+      ]
+    }
   ]
 }
diff --git a/tests/autofillservice/Android.bp b/tests/autofillservice/Android.bp
index 76c65d4..17786d9 100644
--- a/tests/autofillservice/Android.bp
+++ b/tests/autofillservice/Android.bp
@@ -27,7 +27,7 @@
         "ctsdeviceutillegacy-axt",
         "ctstestrunner-axt",
         "truth-prebuilt",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
         "CtsMockInputMethodLib",
         // TODO: remove once Android migrates to JUnit 4.12,
         // which provides assertThrows
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index 0d19090..fb31163 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -159,6 +159,7 @@
             </intent-filter>
         </activity>
         <activity android:name=".activities.FadeInActivity"/>
+        <activity android:name=".activities.MultipleStepsSignInActivity"/>
         <activity android:name=".activities.FieldsNoPasswordActivity"/>
         <activity android:name=".activities.AugmentedAuthActivity" />
         <activity android:name=".activities.SimpleAfterLoginActivity"/>
diff --git a/tests/autofillservice/res/layout/multiple_steps_activity.xml b/tests/autofillservice/res/layout/multiple_steps_activity.xml
new file mode 100644
index 0000000..df00cfa
--- /dev/null
+++ b/tests/autofillservice/res/layout/multiple_steps_activity.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/status"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <LinearLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="200dp"
+        android:orientation="horizontal">
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/prev"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="PREV" />
+
+        <Button
+            android:id="@+id/next"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="NEXT" />
+
+        <Button
+            android:id="@+id/finish"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="FINISH" />
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/autofillservice/res/layout/password.xml b/tests/autofillservice/res/layout/password.xml
new file mode 100644
index 0000000..39d60d6
--- /dev/null
+++ b/tests/autofillservice/res/layout/password.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal" >
+
+    <TextView
+        android:id="@+id/password_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Password" />
+
+    <EditText
+        android:id="@+id/password"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:inputType="textPassword"
+        android:textCursorDrawable="@android:color/transparent"
+        android:imeOptions="flagNoFullscreen" />
+
+</LinearLayout>
diff --git a/tests/autofillservice/res/layout/scrollable_login_activity.xml b/tests/autofillservice/res/layout/scrollable_login_activity.xml
new file mode 100644
index 0000000..dfa5227
--- /dev/null
+++ b/tests/autofillservice/res/layout/scrollable_login_activity.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2023 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:orientation="vertical" >
+
+    <ScrollView android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <include layout="@layout/login_activity" />
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/tests/autofillservice/res/layout/username.xml b/tests/autofillservice/res/layout/username.xml
new file mode 100644
index 0000000..a77a1d3
--- /dev/null
+++ b/tests/autofillservice/res/layout/username.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal" >
+
+    <TextView
+        android:id="@+id/username_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Username" />
+
+    <EditText
+        android:id="@+id/username"
+        android:minEms="2"
+        android:maxEms="5"
+        android:maxLength="25"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textCursorDrawable="@android:color/transparent"
+        android:imeOptions="flagNoFullscreen" />
+
+</LinearLayout>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginWithCustomHighlightActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginWithCustomHighlightActivityTest.java
index f1a06ae..1d64f6f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginWithCustomHighlightActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginWithCustomHighlightActivityTest.java
@@ -26,9 +26,10 @@
 import android.autofillservice.cts.testcore.CannedFillResponse.CannedDataset;
 import android.autofillservice.cts.testcore.MyDrawable;
 import android.graphics.Rect;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java b/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java
index ce37c23..545a917 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java
@@ -36,11 +36,12 @@
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.FillRequest;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.SaveRequest;
 import android.service.autofill.FillContext;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.autofill.AutofillId;
 import android.widget.EditText;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.List;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 6dd4d1a..e8a58bd 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -55,13 +55,12 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.autofill.AutofillValue;
-import android.view.View;
+
+import androidx.test.uiautomator.UiObject2;
 
 import com.android.compatibility.common.util.Timeout;
 
@@ -543,10 +542,9 @@
         // It works fine for portrait but for the platforms that the default orientation
         // is landscape, e.g. automotive. Depending on the height of the IME, the ID_LOGIN
         // button may not be visible.
-        // In order to avoid that,
-        // generate back key event to hide IME before pressing ID_LOGIN button.
-        mUiBot.pressBack();
 
+        // In order to avoid that, scroll until the ID_LOGIN button appears.
+        mUiBot.scrollToTextObject(ID_LOGIN);
         mUiBot.selectByRelativeId(ID_LOGIN);
         mUiBot.assertSaveShowing(SAVE_DATA_TYPE_USERNAME);
 
@@ -565,4 +563,4 @@
                 ID_USERNAME);
         assertTextAndValue(username, "dude");
     }
-}
\ No newline at end of file
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractAutoFillActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractAutoFillActivity.java
index 70e04b7..af30990 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractAutoFillActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractAutoFillActivity.java
@@ -28,6 +28,7 @@
 import android.os.Bundle;
 import android.view.PixelCopy;
 import android.view.View;
+import android.view.WindowInsets;
 import android.view.autofill.AutofillManager;
 
 import androidx.annotation.NonNull;
@@ -183,4 +184,11 @@
     public void clearFocus() {
         throw new UnsupportedOperationException("Not implemented by " + getClass());
     }
+
+    /**
+     * Get insets of the root window
+     */
+    public WindowInsets getRootWindowInsets() {
+        return getWindow().getDecorView().getRootWindowInsets();
+    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractWebViewActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractWebViewActivity.java
index 277af4f..cbcc1e3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractWebViewActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/AbstractWebViewActivity.java
@@ -17,10 +17,11 @@
 
 import android.autofillservice.cts.testcore.UiBot;
 import android.os.SystemClock;
-import android.support.test.uiautomator.UiObject2;
 import android.view.KeyEvent;
 import android.widget.EditText;
 
+import androidx.test.uiautomator.UiObject2;
+
 public abstract class AbstractWebViewActivity extends AbstractAutoFillActivity {
 
     public static final String FAKE_DOMAIN = "y.u.no.real.server";
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
index fae0587..f05529f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
@@ -28,7 +28,6 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.view.WindowInsets;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.EditText;
@@ -398,13 +397,6 @@
     }
 
     /**
-     * Get insets of the root window
-     */
-    public WindowInsets getRootWindowInsets() {
-        return mUsernameLabel.getRootWindowInsets();
-    }
-
-    /**
      * Request to hide soft input
      */
     public void hideSoftInput() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/MultipleStepsSignInActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/MultipleStepsSignInActivity.java
new file mode 100644
index 0000000..3bf4f87
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/MultipleStepsSignInActivity.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 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.autofillservice.cts.activities;
+
+import android.autofillservice.cts.R;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.autofill.AutofillManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MultipleStepsSignInActivity extends AbstractAutoFillActivity {
+
+    private static final String TAG = "AbstractMultipleStepsActivity";
+    private static final String MESSAGE_STEP = "Showing step ";
+    private static final String MESSAGE_FINISH = "Finished";
+
+    private static MultipleStepsSignInActivity sCurrentActivity;
+
+    /**
+     * Gests the latest instance.
+     *
+     * <p>Typically used in test cases that rotates the activity
+     */
+    @SuppressWarnings("unchecked") // Its up to caller to make sure it's setting the right one
+    public static <T extends MultipleStepsSignInActivity> T getCurrentActivity() {
+        return (T) sCurrentActivity;
+    }
+
+    private TextView mStatus;
+    private ViewGroup mContainer;
+
+    private Button mPrevButton;
+    private Button mNextButton;
+    private Button mFinishButton;
+
+    private int mCurrentStep;
+    private boolean mFinished;
+
+    protected List<LinearLayout> mSteps;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        sCurrentActivity = this;
+        mCurrentStep = 0;
+
+        setContentView(R.layout.multiple_steps_activity);
+
+        mStatus = findViewById(R.id.status);
+        mContainer = findViewById(R.id.container);
+        mPrevButton = findViewById(R.id.prev);
+        mNextButton = findViewById(R.id.next);
+        mFinishButton = findViewById(R.id.finish);
+
+        View.OnClickListener onClickListener = (v) -> {
+            if (v == mPrevButton) {
+                showStep(mCurrentStep - 1);
+            } else if (v == mNextButton) {
+                showStep(mCurrentStep + 1);
+            } else {
+                finishSelf();
+            }
+        };
+        mPrevButton.setOnClickListener(onClickListener);
+        mNextButton.setOnClickListener(onClickListener);
+        mFinishButton.setOnClickListener(onClickListener);
+
+        mSteps = getStepsMap();
+
+        showStep(0);
+    }
+
+    public void nextPage() {
+        runOnUiThread(() -> mNextButton.performClick());
+    }
+
+    public void prevPage() {
+        runOnUiThread(() -> mPrevButton.performClick());
+    }
+
+    public void hideSoftInput() {
+        final InputMethodManager imm = getSystemService(InputMethodManager.class);
+        imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
+    }
+
+    private void showStep(int i) {
+        if (mFinished || i < 0 || i >= mSteps.size()) {
+            Log.w(TAG, String.format("Invalid step: %d (finished=%b, range=[%d,%d])",
+                    i, mFinished, 0, mSteps.size() - 1));
+            return;
+        }
+
+        View step = mSteps.get(i);
+        mStatus.setText(MESSAGE_STEP + i);
+        Log.d(TAG, "Showing step " + i);
+
+        if (mContainer.getChildCount() > 0) {
+            mContainer.removeViewAt(0);
+        }
+        mContainer.addView(step);
+        mCurrentStep = i;
+
+        mPrevButton.setEnabled(mCurrentStep != 0);
+        mNextButton.setEnabled(mCurrentStep != mSteps.size() - 1);
+    }
+
+    private void finishSelf() {
+        mStatus.setText(MESSAGE_FINISH);
+        mContainer.removeAllViews();
+        mFinished = true;
+        AutofillManager afm = getSystemService(AutofillManager.class);
+        if (afm != null) {
+            afm.commit();
+        }
+    }
+
+    protected List<LinearLayout> getStepsMap() {
+        List<LinearLayout> steps = new ArrayList<>(2);
+        steps.add(newStep(R.layout.username));
+        steps.add(newStep(R.layout.password));
+        return ImmutableList.copyOf(steps);
+    }
+
+    private LinearLayout newStep(int resId) {
+        final LayoutInflater inflater = LayoutInflater.from(this);
+        return (LinearLayout) inflater.inflate(resId, null);
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
index 4cab12c..ca91090 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
@@ -41,7 +41,7 @@
         Log.i(TAG, "onCreate(" + savedInstanceState + ")");
         super.onCreate(savedInstanceState);
 
-        setContentView(R.layout.login_activity);
+        setContentView(R.layout.scrollable_login_activity);
 
         findViewById(R.id.login).setOnClickListener((v) -> finish());
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/SecondActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/SecondActivity.java
index 71ff7ed..d3c1a61 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/SecondActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/SecondActivity.java
@@ -20,10 +20,11 @@
 import android.autofillservice.cts.R;
 import android.autofillservice.cts.testcore.UiBot;
 import android.os.Bundle;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.widget.TextView;
 
+import androidx.test.uiautomator.UiObject2;
+
 /**
  * Activity that is used to test restored mechanism will work while running below steps:
  * 1. Taps span on the save UI to start the ViewActionActivity.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/ViewActionActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/ViewActionActivity.java
index 29d853a..bac52aa 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/ViewActionActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/ViewActionActivity.java
@@ -22,10 +22,11 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.widget.TextView;
 
+import androidx.test.uiautomator.UiObject2;
+
 /**
  * Activity that handles VIEW action.
  */
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewActivity.java
index d795209..8262ed4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewActivity.java
@@ -23,7 +23,6 @@
 import android.autofillservice.cts.testcore.UiBot;
 import android.content.Context;
 import android.os.Bundle;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.View;
 import android.webkit.WebResourceRequest;
@@ -33,6 +32,8 @@
 import android.widget.EditText;
 import android.widget.LinearLayout;
 
+import androidx.test.uiautomator.UiObject2;
+
 import com.android.compatibility.common.util.RetryableException;
 
 import java.io.IOException;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewMultiScreenLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewMultiScreenLoginActivity.java
index 56684ab..c3f4c42 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewMultiScreenLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/WebViewMultiScreenLoginActivity.java
@@ -22,13 +22,14 @@
 import android.autofillservice.cts.R;
 import android.autofillservice.cts.testcore.UiBot;
 import android.os.Bundle;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.webkit.WebResourceRequest;
 import android.webkit.WebResourceResponse;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
+import androidx.test.uiautomator.UiObject2;
+
 import com.android.compatibility.common.util.RetryableException;
 
 import java.io.IOException;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/WelcomeActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/WelcomeActivity.java
index 4113db3..4d3ffde 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/WelcomeActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/WelcomeActivity.java
@@ -24,12 +24,12 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.os.Bundle;
-import android.support.test.uiautomator.UiObject2;
 import android.text.TextUtils;
 import android.util.Log;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
+import androidx.test.uiautomator.UiObject2;
 
 /**
  * Activity that displays a "Welcome USER" message after login.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java
index 47db989..537a1fe 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java
@@ -59,7 +59,6 @@
 import android.os.CancellationSignal;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.uiautomator.UiObject2;
 import android.util.ArraySet;
 import android.view.View;
 import android.view.autofill.AutofillId;
@@ -68,6 +67,7 @@
 import android.widget.EditText;
 
 import androidx.test.filters.FlakyTest;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/augmented/DisableAutofillTest.java b/tests/autofillservice/src/android/autofillservice/cts/augmented/DisableAutofillTest.java
index 4d4b186..0f94bf4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/augmented/DisableAutofillTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/augmented/DisableAutofillTest.java
@@ -26,11 +26,12 @@
 import android.autofillservice.cts.testcore.CannedFillResponse;
 import android.autofillservice.cts.testcore.CtsAugmentedAutofillService.AugmentedFillRequest;
 import android.platform.test.annotations.AppModeFull;
-import android.support.test.uiautomator.UiObject2;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.widget.EditText;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 @AppModeFull(reason = "AugmentedLoginActivityTest is enough")
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractLoginNotImportantForAutofillTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractLoginNotImportantForAutofillTestCase.java
index eb5b87a..f3b4b69 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractLoginNotImportantForAutofillTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractLoginNotImportantForAutofillTestCase.java
@@ -23,12 +23,13 @@
 import android.autofillservice.cts.activities.LoginNotImportantForAutofillActivity;
 import android.autofillservice.cts.testcore.CannedAugmentedFillResponse;
 import android.autofillservice.cts.testcore.CtsAugmentedAutofillService.AugmentedFillRequest;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.widget.EditText;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 public abstract class AbstractLoginNotImportantForAutofillTestCase<A extends
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/CustomDescriptionWithLinkTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/CustomDescriptionWithLinkTestCase.java
index 774fa5a..eecbbc2 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/CustomDescriptionWithLinkTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/CustomDescriptionWithLinkTestCase.java
@@ -27,12 +27,12 @@
 import android.autofillservice.cts.testcore.UiBot;
 import android.content.Intent;
 import android.service.autofill.CustomDescription;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
 import android.widget.RemoteViews;
 
 import androidx.annotation.NonNull;
 import androidx.test.filters.FlakyTest;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
index 70d7a08..3635c77 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
@@ -46,9 +46,10 @@
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.FillRequest;
 import android.content.Intent;
 import android.service.autofill.FillEventHistory;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.List;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dialog/MultipleStepsSignInActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dialog/MultipleStepsSignInActivityTest.java
new file mode 100644
index 0000000..cd942b6
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/dialog/MultipleStepsSignInActivityTest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2022 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.autofillservice.cts.dialog;
+
+import static android.autofillservice.cts.testcore.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.testcore.Helper.ID_PASSWORD_LABEL;
+import static android.autofillservice.cts.testcore.Helper.ID_USERNAME;
+import static android.autofillservice.cts.testcore.Helper.ID_USERNAME_LABEL;
+import static android.autofillservice.cts.testcore.Helper.assertHasFlags;
+import static android.autofillservice.cts.testcore.Helper.assertMockImeStatus;
+import static android.autofillservice.cts.testcore.Helper.enableFillDialogFeature;
+import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
+
+import android.autofillservice.cts.activities.MultipleStepsSignInActivity;
+import android.autofillservice.cts.commontests.AutoFillServiceTestCase;
+import android.autofillservice.cts.testcore.CannedFillResponse;
+import android.autofillservice.cts.testcore.InstrumentedAutoFillService;
+import android.content.Intent;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Test;
+
+
+/**
+ * The tests for showing fill dialog for an Activity that only updates the content for login
+ * steps, the app doesn't go to the new activty.
+ */
+public class MultipleStepsSignInActivityTest extends AutoFillServiceTestCase.ManualActivityLaunch {
+    MultipleStepsSignInActivity mActivity;
+    @After
+    public void teardown() {
+        if (mActivity != null) {
+            mActivity.finish();
+        }
+        mActivity = null;
+    }
+    @Test
+    public void testShowFillDialog_contentChanged_shownFillDialog() throws Exception {
+        // Enable feature and test service
+        enableFillDialogFeature(sContext);
+        enableService();
+
+        // Set response
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setPresentation(createPresentation("Menu Username"))
+                        .setDialogPresentation(createPresentation("Dialog Username"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_USERNAME);
+        sReplier.addResponse(builder.build());
+
+        // Start activity
+        mActivity = startMultipleStepsSignInActivity();
+
+        // Check onFillRequest has the flag: FLAG_SUPPORTS_FILL_DIALOG
+        final InstrumentedAutoFillService.FillRequest fillRequest = sReplier.getNextFillRequest();
+        assertHasFlags(fillRequest.flags, FLAG_SUPPORTS_FILL_DIALOG);
+
+        // Click on username field to trigger fill dialog
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdleSync();
+
+        // Verify fill dialog shown
+        mUiBot.assertFillDialogDatasets("Dialog Username");
+
+        // Do nothing for fill dialog. Click outside to hide fill dialog and IME
+        hideFillDialogAndIme(mActivity);
+
+        // Set response for second page
+        final CannedFillResponse.Builder builder2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Menu Password"))
+                        .setDialogPresentation(createPresentation("Dialog Password"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_PASSWORD);
+        sReplier.addResponse(builder2.build());
+
+        mActivity.nextPage();
+
+        mUiBot.assertShownByRelativeId(ID_PASSWORD_LABEL);
+
+        // Check onFillRequest has the flag: FLAG_SUPPORTS_FILL_DIALOG
+        final InstrumentedAutoFillService.FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertHasFlags(fillRequest2.flags, FLAG_SUPPORTS_FILL_DIALOG);
+
+        // Click on password field to trigger fill dialog
+        mUiBot.selectByRelativeId(ID_PASSWORD);
+        mUiBot.waitForIdleSync();
+
+        // Verify fill dialog shown
+        mUiBot.assertFillDialogDatasets("Dialog Password");
+    }
+
+    @Test
+    public void testShowFillDialog_backPrevPage_notShownFillDialog() throws Exception {
+        // Enable feature and test service
+        enableFillDialogFeature(sContext);
+        enableService();
+
+        // Set response
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setPresentation(createPresentation("Menu Username"))
+                        .setDialogPresentation(createPresentation("Dialog Username"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_USERNAME);
+        sReplier.addResponse(builder.build());
+
+        // Start activity
+        mActivity = startMultipleStepsSignInActivity();
+
+        Log.e("tymtest", "autofill etst 1");
+        // Check onFillRequest has the flag: FLAG_SUPPORTS_FILL_DIALOG
+        final InstrumentedAutoFillService.FillRequest fillRequest = sReplier.getNextFillRequest();
+        assertHasFlags(fillRequest.flags, FLAG_SUPPORTS_FILL_DIALOG);
+        Log.e("tymtest", "autofill etst 2");
+        // Set response for second page
+        final CannedFillResponse.Builder builder2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Menu Password"))
+                        .setDialogPresentation(createPresentation("Dialog Password"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_PASSWORD);
+        sReplier.addResponse(builder2.build());
+
+        // Do nothing on the 1st page and go to next page
+        mActivity.nextPage();
+
+        mUiBot.assertShownByRelativeId(ID_PASSWORD_LABEL);
+
+        // Check onFillRequest has the flag: FLAG_SUPPORTS_FILL_DIALOG
+        final InstrumentedAutoFillService.FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertHasFlags(fillRequest2.flags, FLAG_SUPPORTS_FILL_DIALOG);
+
+        // Click on password field to trigger fill dialog
+        mUiBot.selectByRelativeId(ID_PASSWORD);
+        mUiBot.waitForIdleSync();
+
+        // Verify fill dialog shown
+        mUiBot.assertFillDialogDatasets("Dialog Password");
+
+        // Go back previous page
+        mActivity.prevPage();
+
+        mUiBot.assertShownByRelativeId(ID_USERNAME_LABEL);
+
+        // Verify there is no any fill request because response already exists
+        sReplier.assertNoUnhandledFillRequests();
+
+        // Click on username field to trigger menu UI
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdleSync();
+
+        // Verify fill menu shown
+        mUiBot.assertDatasets("Menu Username");
+    }
+
+    @Test
+    public void testShowFillDialog_doNothingThenBackPrevPage_notShownFillDialog() throws Exception {
+        // Enable feature and test service
+        enableFillDialogFeature(sContext);
+        enableService();
+
+        // Set response
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setPresentation(createPresentation("Menu Username"))
+                        .setDialogPresentation(createPresentation("Dialog Username"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_USERNAME);
+        sReplier.addResponse(builder.build());
+
+        // Start activity
+        mActivity = startMultipleStepsSignInActivity();
+
+        // Check onFillRequest has the flag: FLAG_SUPPORTS_FILL_DIALOG
+        final InstrumentedAutoFillService.FillRequest fillRequest = sReplier.getNextFillRequest();
+        assertHasFlags(fillRequest.flags, FLAG_SUPPORTS_FILL_DIALOG);
+
+        // Set response for second page
+        final CannedFillResponse.Builder builder2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Menu Password"))
+                        .setDialogPresentation(createPresentation("Dialog Password"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_PASSWORD);
+        sReplier.addResponse(builder2.build());
+
+        // Do nothing on the 1st page and go to next page
+        mActivity.nextPage();
+
+        mUiBot.assertShownByRelativeId(ID_PASSWORD_LABEL);
+
+        // Check onFillRequest has the flag: FLAG_SUPPORTS_FILL_DIALOG
+        final InstrumentedAutoFillService.FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertHasFlags(fillRequest2.flags, FLAG_SUPPORTS_FILL_DIALOG);
+
+        // Do nothing and go back previous page
+        mActivity.prevPage();
+
+        mUiBot.assertShownByRelativeId(ID_USERNAME_LABEL);
+
+        // Verify there is no any fill request because response already exists
+        sReplier.assertNoUnhandledFillRequests();
+
+        // Click on username field to trigger menu UI
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdleSync();
+
+        // Verify fill menu shown
+        mUiBot.assertDatasets("Menu Username");
+    }
+
+    private void hideFillDialogAndIme(MultipleStepsSignInActivity activity) throws Exception {
+        // Hide fill dialog via touch outside, the ime will appear.
+        mUiBot.touchOutsideDialog();
+        mUiBot.waitForIdleSync();
+
+        assertMockImeStatus(activity, /* expectedImeShow= */ true);
+
+        // Hide the IME before the next test.
+        activity.hideSoftInput();
+
+        assertMockImeStatus(activity, /* expectedImeShow= */ false);
+    }
+
+    private MultipleStepsSignInActivity startMultipleStepsSignInActivity() throws Exception {
+        final Intent intent = new Intent(mContext, MultipleStepsSignInActivity.class)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        mContext.startActivity(intent);
+        mUiBot.assertShownByRelativeId(ID_USERNAME_LABEL);
+        return MultipleStepsSignInActivity.getCurrentActivity();
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/AuthenticationTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/AuthenticationTest.java
index d9a84fd..4a6bf6c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/AuthenticationTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/AuthenticationTest.java
@@ -43,10 +43,11 @@
 import android.os.Bundle;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 import android.view.autofill.AutofillValue;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.concurrent.CountDownLatch;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
index 008e807..dbd2910 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
@@ -63,8 +63,6 @@
 import android.service.autofill.CustomDescription;
 import android.service.autofill.FillContext;
 import android.service.autofill.ImageTransformation;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.widget.ArrayAdapter;
@@ -76,6 +74,9 @@
 import android.widget.Spinner;
 import android.widget.TimePicker;
 
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Ignore;
 import org.junit.Test;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/DialogLauncherActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/DialogLauncherActivityTest.java
index cc04c0c..5182e2e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/DialogLauncherActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/DialogLauncherActivityTest.java
@@ -26,9 +26,10 @@
 import android.autofillservice.cts.testcore.CannedFillResponse.CannedDataset;
 import android.autofillservice.cts.testcore.Helper;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.FillRequest;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 public class DialogLauncherActivityTest
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java
index bbb30dc..74b94ce 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java
@@ -43,10 +43,11 @@
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.FillEventHistory.Event;
 import android.service.autofill.FillResponse;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 import android.view.autofill.AutofillId;
 
+import androidx.test.uiautomator.UiObject2;
+
 import com.google.common.collect.ImmutableMap;
 
 import org.junit.Test;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java
index 175b4f8..d728e90 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java
@@ -105,7 +105,6 @@
 import android.platform.test.annotations.Presubmit;
 import android.service.autofill.FillContext;
 import android.service.autofill.SaveInfo;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
@@ -119,6 +118,7 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.FlakyTest;
+import androidx.test.uiautomator.UiObject2;
 
 import com.android.compatibility.common.util.RetryableException;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/VirtualContainerActivityTest.java
index fc32cfc..e3e5702 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/VirtualContainerActivityTest.java
@@ -52,11 +52,12 @@
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
 import android.service.autofill.SaveInfo;
-import android.support.test.uiautomator.UiObject2;
 import android.text.InputType;
 import android.view.ViewGroup;
 import android.view.autofill.AutofillManager;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Ignore;
 import org.junit.Test;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java
index 0be57ea..456613e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java
@@ -37,11 +37,12 @@
 import android.autofillservice.cts.testcore.MyAutofillCallback;
 import android.autofillservice.cts.testcore.OneTimeTextWatcher;
 import android.platform.test.annotations.AppModeFull;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.ViewStructure.HtmlInfo;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Assume;
 import org.junit.Ignore;
 import org.junit.Test;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedWebViewActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedWebViewActivityTest.java
index 9c9e3ab..3519faf 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedWebViewActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAugmentedWebViewActivityTest.java
@@ -33,13 +33,13 @@
 import android.autofillservice.cts.testcore.Helper;
 import android.autofillservice.cts.testcore.InlineUiBot;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.FillRequest;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
 import androidx.test.filters.FlakyTest;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 import org.junit.rules.TestRule;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
index 1cfb700..a64d08b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
@@ -39,7 +39,8 @@
 import android.platform.test.annotations.Presubmit;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.FillEventHistory.Event;
-import android.support.test.uiautomator.UiObject2;
+
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 import org.junit.rules.TestRule;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
index 85d86bb..6aa4a02 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
@@ -51,10 +51,10 @@
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
 import android.service.autofill.FillContext;
-import android.support.test.uiautomator.Direction;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.Direction;
 
 import com.android.cts.mockime.ImeEventStream;
 import com.android.cts.mockime.MockImeSession;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
index 75c28e2..695bd58 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
@@ -33,9 +33,9 @@
 import android.autofillservice.cts.testcore.InlineUiBot;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.uiautomator.UiObject2;
 
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 import org.junit.rules.TestRule;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineWebViewActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineWebViewActivityTest.java
index 79180e1..bcf3a79 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineWebViewActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineWebViewActivityTest.java
@@ -35,12 +35,12 @@
 import android.autofillservice.cts.testcore.InlineUiBot;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.FillRequest;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.SaveRequest;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.ViewStructure.HtmlInfo;
 
 import androidx.test.filters.FlakyTest;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Assume;
 import org.junit.Test;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionDateTest.java b/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionDateTest.java
index faabab9..629a059 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionDateTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionDateTest.java
@@ -34,11 +34,12 @@
 import android.service.autofill.CustomDescription;
 import android.service.autofill.DateTransformation;
 import android.service.autofill.DateValueSanitizer;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
 import android.view.autofill.AutofillId;
 import android.widget.RemoteViews;
 
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.Calendar;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionTest.java b/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionTest.java
index ed7da54..f136d84 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/saveui/CustomDescriptionTest.java
@@ -39,14 +39,14 @@
 import android.service.autofill.RegexValidator;
 import android.service.autofill.TextValueSanitizer;
 import android.service.autofill.Validator;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 import android.view.autofill.AutofillId;
 import android.widget.RemoteViews;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/saveui/OnClickActionTest.java b/tests/autofillservice/src/android/autofillservice/cts/saveui/OnClickActionTest.java
index 2d764bc..649e68c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/saveui/OnClickActionTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/saveui/OnClickActionTest.java
@@ -43,10 +43,11 @@
 import android.service.autofill.FillContext;
 import android.service.autofill.OnClickAction;
 import android.service.autofill.VisibilitySetterAction;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 import android.view.autofill.AutofillId;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.regex.Pattern;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/saveui/PreSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/saveui/PreSimpleSaveActivityTest.java
index 1f7d79e..62fe73a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/saveui/PreSimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/saveui/PreSimpleSaveActivityTest.java
@@ -43,12 +43,13 @@
 import android.service.autofill.CustomDescription;
 import android.service.autofill.RegexValidator;
 import android.service.autofill.Validator;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
 import android.view.View;
 import android.view.autofill.AutofillId;
 import android.widget.RemoteViews;
 
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+
 import java.util.regex.Pattern;
 
 public class PreSimpleSaveActivityTest
diff --git a/tests/autofillservice/src/android/autofillservice/cts/saveui/SimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/saveui/SimpleSaveActivityTest.java
index 9762456..75000ce 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/saveui/SimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/saveui/SimpleSaveActivityTest.java
@@ -75,8 +75,6 @@
 import android.service.autofill.SaveInfo;
 import android.service.autofill.TextValueSanitizer;
 import android.service.autofill.Validator;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.style.URLSpan;
@@ -84,6 +82,9 @@
 import android.view.autofill.AutofillId;
 import android.widget.RemoteViews;
 
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 import org.junit.rules.RuleChain;
 import org.junit.rules.TestRule;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenDifferentActivitiesTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenDifferentActivitiesTest.java
index 3f08397..f1e84df 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenDifferentActivitiesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenDifferentActivitiesTest.java
@@ -34,7 +34,8 @@
 import android.content.ComponentName;
 import android.platform.test.annotations.AppModeFull;
 import android.service.autofill.SaveInfo;
-import android.support.test.uiautomator.UiObject2;
+
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Test;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenLoginTest.java
index 325e22d..ac2fc26 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/MultiScreenLoginTest.java
@@ -44,10 +44,11 @@
 import android.platform.test.annotations.AppModeFull;
 import android.service.autofill.CharSequenceTransformation;
 import android.service.autofill.SaveInfo;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.autofill.AutofillId;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.regex.Pattern;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/SettingsIntentTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/SettingsIntentTest.java
index 73cbd450..bf1bd2a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/SettingsIntentTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/SettingsIntentTest.java
@@ -33,7 +33,8 @@
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.support.test.uiautomator.UiObject2;
+
+import androidx.test.uiautomator.UiObject2;
 
 import com.android.compatibility.common.util.FeatureUtil;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/WebViewMultiScreenLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/WebViewMultiScreenLoginActivityTest.java
index 94a88c4..ba3935d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/WebViewMultiScreenLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/WebViewMultiScreenLoginActivityTest.java
@@ -44,11 +44,12 @@
 import android.content.ComponentName;
 import android.service.autofill.CharSequenceTransformation;
 import android.service.autofill.SaveInfo;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.autofill.AutofillId;
 
+import androidx.test.uiautomator.UiObject2;
+
 import org.junit.Test;
 
 import java.util.concurrent.atomic.AtomicReference;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/AugmentedUiBot.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/AugmentedUiBot.java
index 825db8f..9d91f32 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/AugmentedUiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/AugmentedUiBot.java
@@ -23,10 +23,10 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.autofillservice.cts.R;
-import android.support.test.uiautomator.UiObject2;
 import android.view.autofill.AutofillId;
 
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
 
 import com.google.common.base.Preconditions;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index c462baf..fc34db6 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -39,7 +39,7 @@
 import android.app.assist.AssistStructure.ViewNode;
 import android.app.assist.AssistStructure.WindowNode;
 import android.autofillservice.cts.R;
-import android.autofillservice.cts.activities.LoginActivity;
+import android.autofillservice.cts.activities.AbstractAutoFillActivity;
 import android.content.AutofillOptions;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -1705,7 +1705,7 @@
     /**
      * Asserts whether mock IME is showing
      */
-    public static void assertMockImeStatus(LoginActivity activity,
+    public static void assertMockImeStatus(AbstractAutoFillActivity activity,
             boolean expectedImeShow) throws Exception {
         Timeouts.MOCK_IME_TIMEOUT.run("assertMockImeStatus(" + expectedImeShow + ")",
                 () -> {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
index 5f184cf..66ad8af 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
@@ -23,12 +23,13 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.Direction;
+import androidx.test.uiautomator.UiObject2;
+
 import com.android.compatibility.common.util.RequiredFeatureRule;
 import com.android.cts.mockime.MockIme;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java
index 50ef382..b2ff6aa 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java
@@ -50,18 +50,6 @@
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.service.autofill.SaveInfo;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.Configurator;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.SearchCondition;
-import android.support.test.uiautomator.StaleObjectException;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiScrollable;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
 import android.text.Html;
 import android.text.Spanned;
 import android.text.style.URLSpan;
@@ -77,6 +65,18 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.Configurator;
+import androidx.test.uiautomator.Direction;
+import androidx.test.uiautomator.SearchCondition;
+import androidx.test.uiautomator.StaleObjectException;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
 
 import com.android.compatibility.common.util.RetryableException;
 import com.android.compatibility.common.util.Timeout;
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index e18c2d3..447326f 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -40,8 +40,8 @@
 import static android.hardware.camera2.cts.RobustnessTest.MaxStreamSizes.VGA;
 import static android.hardware.camera2.cts.RobustnessTest.MaxStreamSizes.YUV;
 
-import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.eq;
@@ -78,7 +78,6 @@
 import android.media.Image;
 import android.media.ImageReader;
 import android.media.ImageWriter;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Size;
@@ -95,12 +94,11 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
-import java.util.Iterator;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.LinkedBlockingQueue;
 
 /**
  * Tests exercising edge cases in camera setup, configuration, and usage.
@@ -217,28 +215,6 @@
      * Test for making sure the mandatory stream combinations work as expected.
      */
     private void testMandatoryOutputCombinations(boolean maxResolution) throws Exception {
-        final int AVAILABILITY_TIMEOUT_MS = 10;
-        final LinkedBlockingQueue<Pair<String, String>> unavailablePhysicalCamEventQueue =
-                new LinkedBlockingQueue<>();
-        CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
-             @Override
-            public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
-                unavailablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
-            }
-        };
-
-        mCameraManager.registerAvailabilityCallback(ac, mHandler);
-        Set<Pair<String, String>> unavailablePhysicalCameras = new HashSet<Pair<String, String>>();
-        Pair<String, String> candidatePhysicalIds =
-                unavailablePhysicalCamEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
-                java.util.concurrent.TimeUnit.MILLISECONDS);
-        while (candidatePhysicalIds != null) {
-            unavailablePhysicalCameras.add(candidatePhysicalIds);
-            candidatePhysicalIds =
-                unavailablePhysicalCamEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
-                java.util.concurrent.TimeUnit.MILLISECONDS);
-        }
-        mCameraManager.unregisterAvailabilityCallback(ac);
         CameraCharacteristics.Key<MandatoryStreamCombination []> ck =
                 CameraCharacteristics.SCALER_MANDATORY_STREAM_COMBINATIONS;
 
@@ -276,22 +252,10 @@
                 if (mStaticInfo.isLogicalMultiCamera()) {
                     Set<String> physicalCameraIds =
                             mStaticInfo.getCharacteristics().getPhysicalCameraIds();
-                    boolean skipTest = false;
                     for (String physicalId : physicalCameraIds) {
                         if (Arrays.asList(mCameraIdsUnderTest).contains(physicalId)) {
                             // If physicalId is advertised in camera ID list, do not need to test
                             // its stream combination through logical camera.
-                            skipTest = true;
-                        }
-                        for (Pair<String, String> unavailPhysicalCam : unavailablePhysicalCameras) {
-                            if (unavailPhysicalCam.first.equals(id) ||
-                                    unavailPhysicalCam.second.equals(physicalId)) {
-                                // This particular physical camera isn't available. Skip.
-                                skipTest = true;
-                                break;
-                            }
-                        }
-                        if (skipTest) {
                             continue;
                         }
                         StaticMetadata physicalStaticInfo = mAllStaticInfo.get(physicalId);
diff --git a/tests/devicestate/OWNERS b/tests/devicestate/OWNERS
index 8150657..3ba5f26 100644
--- a/tests/devicestate/OWNERS
+++ b/tests/devicestate/OWNERS
@@ -1,7 +1,8 @@
-# Bug component: 943781
+# Bug component: 1333988
 
 ogunwale@google.com
 akulian@google.com
-darryljohnson@google.com
 santoscordon@google.com
 michaelwr@google.com
+kennethford@google.com
+jiamingliu@google.com
diff --git a/tests/framework/base/biometrics/Android.bp b/tests/framework/base/biometrics/Android.bp
index 1ec7d5b..2d0bcb2 100644
--- a/tests/framework/base/biometrics/Android.bp
+++ b/tests/framework/base/biometrics/Android.bp
@@ -41,7 +41,7 @@
         "mockito-target-minus-junit4",
         "platform-test-annotations",
         "platformprotosnano",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
     ],
     srcs: ["src/**/*.java"],
     data: [
diff --git a/tests/framework/base/biometrics/OWNERS b/tests/framework/base/biometrics/OWNERS
index fbd1d59..95749d0 100644
--- a/tests/framework/base/biometrics/OWNERS
+++ b/tests/framework/base/biometrics/OWNERS
@@ -5,4 +5,3 @@
 jaggies@google.com
 jbolinger@google.com
 joshmccloskey@google.com
-jeffpu@google.com
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
index 30af1e7..bcd9a5f 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -38,9 +38,10 @@
 import android.hardware.biometrics.SensorProperties;
 import android.os.CancellationSignal;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 
+import androidx.test.uiautomator.UiObject2;
+
 import com.android.server.biometrics.nano.SensorStateProto;
 
 import org.junit.Ignore;
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
index fa05e86..92de787 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
@@ -51,13 +51,13 @@
 import android.server.wm.TestJournalProvider.TestJournal;
 import android.server.wm.UiDeviceUtils;
 import android.server.wm.WindowManagerState;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import com.android.server.biometrics.nano.BiometricServiceStateProto;
 
@@ -529,7 +529,6 @@
         //the enrollent
         //TODO(b/217275524)
         Thread.sleep(200);
-
         session.finishEnroll(userId);
         mInstrumentation.waitForIdleSync();
         Utils.waitForIdleService(this::getSensorStates);
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/fingerprint/FingerprintServiceTest.java b/tests/framework/base/biometrics/src/android/server/biometrics/fingerprint/FingerprintServiceTest.java
index 620430c..36e9209 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/fingerprint/FingerprintServiceTest.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/fingerprint/FingerprintServiceTest.java
@@ -47,15 +47,15 @@
 import android.server.wm.TestJournalProvider.TestJournal;
 import android.server.wm.TestJournalProvider.TestJournalContainer;
 import android.server.wm.UiDeviceUtils;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
 
 import com.android.server.biometrics.nano.SensorServiceStateProto;
 import com.android.server.biometrics.nano.SensorStateProto;
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 855d928..bce0513 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -305,7 +305,7 @@
              android:exported="true"/>
         <activity android:name=".ShowWhenLockedDialogActivity"
              android:exported="true"
-             android:theme="@android:style/Theme.Material.Dialog"/>
+             android:theme="@style/ShowWhenLockedDialogTheme"/>
         <activity android:name=".ShowWhenLockedTranslucentActivity"
              android:exported="true"
              android:theme="@android:style/Theme.Translucent"/>
@@ -336,10 +336,11 @@
              android:exported="true"
              android:configChanges="uiMode"/>
         <activity android:name=".FontScaleActivity"
+             android:configChanges="screenSize|screenLayout"
              android:exported="true"/>
         <activity android:name=".FontScaleNoRelaunchActivity"
              android:exported="true"
-             android:configChanges="fontScale"/>
+             android:configChanges="fontScale|screenSize|screenLayout"/>
         <activity android:name=".DisplayAccessCheckEmbeddingActivity"
              android:allowEmbedded="true"
              android:exported="true"/>
diff --git a/tests/framework/base/windowmanager/app/res/values-watch/styles.xml b/tests/framework/base/windowmanager/app/res/values-watch/styles.xml
new file mode 100644
index 0000000..14da321
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/res/values-watch/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <style name="ShowWhenLockedDialogTheme" parent="@android:style/Theme.Material.Dialog">
+        <!-- Wear dialog theme has been converted to non-floating, but this breaks occluding -->
+        <item name="@android:windowIsFloating">true</item>
+        <!-- Likewise, for the purpose of CTS, make this non-swipeable, as there are visibility
+             implications there as well -->
+        <item name="@android:windowSwipeToDismiss">false</item>
+    </style>
+</resources>
diff --git a/tests/framework/base/windowmanager/app/res/values/styles.xml b/tests/framework/base/windowmanager/app/res/values/styles.xml
index 43f60eb..d0e35c0 100644
--- a/tests/framework/base/windowmanager/app/res/values/styles.xml
+++ b/tests/framework/base/windowmanager/app/res/values/styles.xml
@@ -101,4 +101,7 @@
         <item name="android:windowLayoutInDisplayCutoutMode">always</item>
         <item name="android:windowSoftInputMode">stateHidden</item>
     </style>
+    <style name="ShowWhenLockedDialogTheme" parent="@android:style/Theme.Material.Dialog">
+        <!-- no-op except on Wear, where dialog theme has been converted to non-floating -->
+    </style>
 </resources>
diff --git a/tests/framework/base/windowmanager/jetpack/Android.bp b/tests/framework/base/windowmanager/jetpack/Android.bp
index 1ab377f..59e195d 100644
--- a/tests/framework/base/windowmanager/jetpack/Android.bp
+++ b/tests/framework/base/windowmanager/jetpack/Android.bp
@@ -83,8 +83,8 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "compatibility-device-util-axt",
-        "cts-wm-util",
         "platform-test-annotations",
+        "cts-wm-util",
         "cts_window-sidecar",
         "cts_window-extensions",
         "cts_window-extensions-core",
diff --git a/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml b/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
index 2cc72fa..b692bd1 100644
--- a/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
@@ -19,6 +19,8 @@
           package="android.server.wm.jetpack"
           android:targetSandboxVersion="2">
 
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+
     <application android:label="CtsWindowManagerJetpackTestCases">
         <uses-library android:name="android.test.runner" />
         <uses-library android:name="androidx.window.extensions"
@@ -27,6 +29,7 @@
                       android:required="false" />
         <activity android:name="android.server.wm.jetpack.utils.TestActivity" />
         <activity android:name="android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity"
+                  android:supportsPictureInPicture="true"
                   android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"
         />
         <activity android:name="android.server.wm.jetpack.utils.TestGetWindowLayoutInfoActivity" />
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java
index 57a9fd5..2397a37 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java
@@ -23,6 +23,7 @@
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplit;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertNotVisible;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitForFillsTask;
+import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
 
 import static org.junit.Assert.assertTrue;
 
@@ -227,6 +228,6 @@
         }
         return primaryActivityId.equals(((TestActivityWithId) activityIntentPair.first).getId())
                 && secondaryActivityId.equals(activityIntentPair.second.getStringExtra(
-                        ACTIVITY_ID_LABEL));
+                KEY_ACTIVITY_ID));
     }
 }
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java
index f4fa70c..e017d65 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java
@@ -97,8 +97,7 @@
         SplitPairRule splitPairRule = createWildcardSplitPairRule();
         mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));
 
-        TestActivity primaryActivity = (TestActivityWithId)
-                startActivityNewTask(TestActivityWithId.class);
+        TestActivity primaryActivity = startActivityNewTask(TestActivityWithId.class);
         TestActivity secondaryActivity = (TestActivity) startActivityAndVerifySplit(primaryActivity,
                 TestActivityWithId.class, splitPairRule, "secondaryActivity", mSplitInfoConsumer);
 
@@ -359,8 +358,8 @@
             mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));
 
             // Launch the two activities
-            TestActivity primaryActivity = (TestActivity)
-                    startActivityNewTask(TestConfigChangeHandlingActivity.class);
+            TestActivity primaryActivity = startActivityNewTask(
+                    TestConfigChangeHandlingActivity.class);
             TestActivity secondaryActivity;
             if (mShouldPreventSideBySideActivities) {
                 secondaryActivity = startActivityAndVerifyNotSplit(primaryActivity);
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingIntegrationTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingIntegrationTests.java
index 0d9a510..5751177 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingIntegrationTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingIntegrationTests.java
@@ -19,10 +19,12 @@
 import static android.server.wm.jetpack.signed.Components.SIGNED_EMBEDDING_ACTIVITY;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.EMBEDDED_ACTIVITY_ID;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createSplitPairRuleBuilderWithJava8Predicate;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifyNoCallback;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplit;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumed;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeHasDisplayFeatures;
+import static android.server.wm.jetpack.utils.ExtensionUtil.assumeVendorApiLevelAtLeast;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutComponent;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutInfo;
 
@@ -75,8 +77,8 @@
      */
     @Test
     public void testDisplayFeaturesWithEmbedding() throws Exception {
-        TestConfigChangeHandlingActivity primaryActivity = (TestConfigChangeHandlingActivity)
-                startActivityNewTask(TestConfigChangeHandlingActivity.class);
+        TestConfigChangeHandlingActivity primaryActivity = startActivityNewTask(
+                TestConfigChangeHandlingActivity.class);
         WindowLayoutInfo windowLayoutInfo = getExtensionWindowLayoutInfo(primaryActivity);
         assumeHasDisplayFeatures(windowLayoutInfo);
 
@@ -117,6 +119,33 @@
     }
 
     /**
+     * Tests that clearing the split info consumer stops notifying unregistered consumer.
+     */
+    @Test
+    public void testClearSplitInfoCallback() throws Exception {
+        assumeVendorApiLevelAtLeast(2); // TODO(b/244450254): harden the requirement in U.
+        mActivityEmbeddingComponent.clearSplitInfoCallback();
+        TestConfigChangeHandlingActivity primaryActivity = startActivityNewTask(
+                TestConfigChangeHandlingActivity.class);
+
+        // Launch a second activity in a split. Use a very small split ratio, so that the secondary
+        // activity occupies most of the screen.
+        SplitPairRule splitPairRule = createSplitPairRuleBuilderWithJava8Predicate(
+                activityActivityPair -> true,
+                activityIntentPair -> true,
+                windowMetrics -> true
+        )
+                .setSplitRatio(0.1f)
+                .build();
+        mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));
+
+        startActivityAndVerifyNoCallback(primaryActivity,
+                TestActivityWithId.class,
+                "secondaryActivity" /* secondActivityId */,
+                mSplitInfoConsumer);
+    }
+
+    /**
      * Tests that display features are still reported when using ActivityEmbedding. Same as above,
      * but using different packages for the host and embedded activities.
      * Fixed in CL: If2dbc337c4b8cb909914cc28ae4db28a82ff9de3
@@ -124,8 +153,8 @@
     @Test
     public void testDisplayFeaturesWithEmbedding_differentPackage() throws Exception {
         // Start an activity to collect the window layout info.
-        TestConfigChangeHandlingActivity initialActivity = (TestConfigChangeHandlingActivity)
-                startActivityNewTask(TestConfigChangeHandlingActivity.class);
+        TestConfigChangeHandlingActivity initialActivity = startActivityNewTask(
+                TestConfigChangeHandlingActivity.class);
         WindowLayoutInfo windowLayoutInfo = getExtensionWindowLayoutInfo(initialActivity);
         assumeHasDisplayFeatures(windowLayoutInfo);
 
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLifecycleTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLifecycleTests.java
index e2fc36b..605bfbd 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLifecycleTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLifecycleTests.java
@@ -22,7 +22,6 @@
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplit;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertNotVisible;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumed;
-import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
 import static android.server.wm.lifecycle.LifecycleConstants.ON_CREATE;
 import static android.server.wm.lifecycle.LifecycleConstants.ON_DESTROY;
 import static android.server.wm.lifecycle.LifecycleConstants.ON_PAUSE;
@@ -41,7 +40,6 @@
 import android.app.Application;
 import android.net.Uri;
 import android.os.Bundle;
-import android.server.wm.jetpack.utils.JavaConsumerAdapter;
 import android.server.wm.jetpack.utils.TestActivityWithId;
 import android.server.wm.jetpack.utils.TestActivityWithId2;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
@@ -82,13 +80,7 @@
     public void setUp() {
         super.setUp();
         mSplitInfoConsumer = new SplitInfoLifecycleConsumer<>();
-        if (getWindowExtensions().getVendorApiLevel() >= 2) {
-            mActivityEmbeddingComponent.setSplitInfoCallback(mSplitInfoConsumer);
-        } else {
-            mActivityEmbeddingComponent.setSplitInfoCallback(
-                    new JavaConsumerAdapter<>(mSplitInfoConsumer)
-            );
-        }
+        mActivityEmbeddingComponent.setSplitInfoCallback(mSplitInfoConsumer);
 
         mEventLogClient = EventLogClient.create(TEST_OWNER, mInstrumentation.getTargetContext(),
                 Uri.parse("content://android.server.wm.jetpack.logprovider"));
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java
index 0a105cf..a9e622a 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java
@@ -22,6 +22,7 @@
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertFinishing;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertNotResumed;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumed;
+import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
 
 import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
 
@@ -319,7 +320,7 @@
         public SplitPlaceholderRule build() {
             // Create placeholder activity intent
             Intent placeholderIntent = new Intent(mContext, TestActivityWithId.class);
-            placeholderIntent.putExtra(ACTIVITY_ID_LABEL, mPlaceholderActivityId);
+            placeholderIntent.putExtra(KEY_ACTIVITY_ID, mPlaceholderActivityId);
 
             // Create {@link SplitPlaceholderRule} that launches the placeholder in a split with the
             // target primary activity.
@@ -329,7 +330,8 @@
                                     && mPrimaryActivityId.equals(((TestActivityWithId) activity)
                                     .getId()) /* activityPredicate */,
                             intent -> mPrimaryActivityId.equals(
-                                    intent.getStringExtra(ACTIVITY_ID_LABEL)) /* intentPredicate */,
+                                    intent.getStringExtra(KEY_ACTIVITY_ID)
+                            )/* intentPredicate */,
                     mParentWindowMetricsPredicate)
                     .setSplitRatio(DEFAULT_SPLIT_RATIO);
 
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPolicyTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPolicyTests.java
index 8bdc309..5956402 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPolicyTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPolicyTests.java
@@ -16,6 +16,8 @@
 
 package android.server.wm.jetpack;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.server.wm.jetpack.second.Components.SECOND_UNTRUSTED_EMBEDDING_ACTIVITY;
 import static android.server.wm.jetpack.signed.Components.SIGNED_EMBEDDING_ACTIVITY;
 import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createWildcardSplitPairRule;
@@ -23,7 +25,6 @@
 import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.EXTRA_EMBED_ACTIVITY;
 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.startActivityFromActivity;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.startActivityNewTask;
 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.startActivityOnDisplaySingleTop;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -43,6 +44,7 @@
 import android.server.wm.NestedShellPermission;
 import android.server.wm.WindowManagerState;
 import android.server.wm.jetpack.utils.TestActivityKnownEmbeddingCerts;
+import android.server.wm.jetpack.utils.TestActivityLauncher;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
 
 import androidx.annotation.NonNull;
@@ -51,6 +53,8 @@
 import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
 import androidx.window.extensions.embedding.SplitPairRule;
 
+import com.android.compatibility.common.util.ApiTest;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -94,6 +98,8 @@
      * Verifies that all input is dropped for activities that are embedded and being animated with
      * untrusted embedding.
      */
+    @ApiTest(apis = {"com.android.server.wm.ActivityRecord#setDropInputForAnimation",
+            "androidx.window.extensions.embedding.ActivityEmbeddingComponent#setEmbeddingRules"})
     @Test
     public void testInputDuringAnimationIsNotAllowed_untrustedEmbedding() {
         // TODO(b/207070762): remove the test when cleanup legacy app transition
@@ -101,8 +107,11 @@
         // to app.
         assumeFalse(ENABLE_SHELL_TRANSITIONS);
 
-        Activity primaryActivity = startActivityNewTask(mContext, mInstrumentation,
-                TestConfigChangeHandlingActivity.class, null /* activityId */);
+        Activity primaryActivity = new TestActivityLauncher<>(mContext,
+                TestConfigChangeHandlingActivity.class)
+                .addIntentFlag(FLAG_ACTIVITY_NEW_TASK)
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .launch(mInstrumentation);
 
         SplitPairRule splitPairRule = createWildcardSplitPairRule(true /* shouldClearTop */);
         mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionRearDisplayTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionRearDisplayTest.java
index 1e3a85f..d479e6e 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionRearDisplayTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionRearDisplayTest.java
@@ -118,7 +118,7 @@
         mDeviceStateManager.registerCallback(Runnable::run, this);
         mWindowAreaComponent.addRearDisplayStatusListener(mStatusListener);
         unlockDeviceIfNeeded();
-        mActivity = (TestRearDisplayActivity) startActivityNewTask(TestRearDisplayActivity.class);
+        mActivity = startActivityNewTask(TestRearDisplayActivity.class);
         waitAndAssert(() -> mWindowAreaStatus != null);
     }
 
@@ -192,12 +192,14 @@
             "androidx.window.extensions.area.WindowAreaComponent#startRearDisplaySession",
             "androidx.window.extensions.area.WindowAreaComponent#endRearDisplaySession"})
     @Test
-    public void testStartAndEndRearDisplaySession() {
+    public void testStartAndEndRearDisplaySession() throws Throwable {
         assumeTrue(mWindowAreaStatus == WindowAreaComponent.STATUS_AVAILABLE);
         assumeTrue(mCurrentDeviceState != mRearDisplayState);
 
         mActivity.mConfigurationChanged = false;
-        mWindowAreaComponent.startRearDisplaySession(mActivity, mSessionStateListener);
+        // Running with CONTROL_DEVICE_STATE permission to bypass educational overlay
+        DeviceStateUtils.runWithControlDeviceStatePermission(() ->
+                mWindowAreaComponent.startRearDisplaySession(mActivity, mSessionStateListener));
         waitAndAssert(() -> mActivity.mConfigurationChanged);
         assertTrue(mWindowAreaSessionState != null
                         && mWindowAreaSessionState == WindowAreaComponent.SESSION_STATE_ACTIVE);
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
index f20d1d4..11f904a 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
@@ -18,11 +18,14 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.server.wm.jetpack.utils.ExtensionUtil.EXTENSION_VERSION_2;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assertEqualWindowLayoutInfo;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeHasDisplayFeatures;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutInfo;
+import static android.server.wm.jetpack.utils.ExtensionUtil.isExtensionVersionAtLeast;
 import static android.server.wm.jetpack.utils.SidecarUtil.assumeSidecarSupportedDevice;
 import static android.server.wm.jetpack.utils.SidecarUtil.getSidecarInterface;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static androidx.window.extensions.layout.FoldingFeature.STATE_FLAT;
 import static androidx.window.extensions.layout.FoldingFeature.STATE_HALF_OPENED;
@@ -33,17 +36,28 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
 
+import android.content.Context;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.platform.test.annotations.Presubmit;
+import android.server.wm.IgnoreOrientationRequestSession;
 import android.server.wm.jetpack.utils.TestActivity;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
 import android.server.wm.jetpack.utils.TestValueCountJavaConsumer;
 import android.server.wm.jetpack.utils.WindowExtensionTestRule;
 import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
+import android.view.Display;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 import androidx.window.extensions.layout.DisplayFeature;
 import androidx.window.extensions.layout.FoldingFeature;
@@ -52,6 +66,8 @@
 import androidx.window.sidecar.SidecarDisplayFeature;
 import androidx.window.sidecar.SidecarInterface;
 
+import com.android.compatibility.common.util.ApiTest;
+
 import com.google.common.collect.BoundType;
 import com.google.common.collect.Range;
 
@@ -78,7 +94,6 @@
 @RunWith(AndroidJUnit4.class)
 public class ExtensionWindowLayoutComponentTest extends WindowManagerJetpackTestBase {
 
-    private TestActivity mActivity;
     private WindowLayoutComponent mWindowLayoutComponent;
     private WindowLayoutInfo mWindowLayoutInfo;
 
@@ -92,16 +107,41 @@
         super.setUp();
         mWindowLayoutComponent =
                 (WindowLayoutComponent) mWindowExtensionTestRule.getExtensionComponent();
-        mActivity = (TestActivity) startActivityNewTask(TestActivity.class);
+        assumeNotNull(mWindowLayoutComponent);
+    }
+
+    private Context createContextWithNonActivityWindow() {
+        Display defaultDisplay = mContext.getSystemService(DisplayManager.class).getDisplay(
+                DEFAULT_DISPLAY);
+        Context windowContext = mContext.createWindowContext(defaultDisplay,
+                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, null /* options */);
+
+        mInstrumentation.runOnMainSync(() -> {
+            final View view = new View(windowContext);
+            WindowManager wm = windowContext.getSystemService(WindowManager.class);
+            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
+            wm.addView(view, params);
+        });
+        return windowContext;
+    }
+
+    private void assumeExtensionVersionSupportsWindowContextLayout() {
+        assumeTrue("This test should only be run on devices with version: ",
+                isExtensionVersionAtLeast(EXTENSION_VERSION_2));
     }
 
     /**
      * Test adding and removing a window layout change listener.
      */
     @Test
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener"})
     public void testWindowLayoutComponent_onWindowLayoutChangeListener() throws Exception {
+        TestActivity activity = (TestActivity) startFullScreenActivityNewTask(TestActivity.class,
+                null /* activityId */);
         // Set activity to portrait
-        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+        setActivityOrientationActivityDoesNotHandleOrientationChanges(activity,
                 ORIENTATION_PORTRAIT);
 
         // Create the callback, onWindowLayoutChanged should only be called twice in this
@@ -109,40 +149,51 @@
         // removed.
         TestValueCountJavaConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
                 new TestValueCountJavaConsumer<>();
-        windowLayoutInfoConsumer.setCount(2);
+        windowLayoutInfoConsumer.setCount(1);
 
         // Add window layout listener for mWindowToken - onWindowLayoutChanged should be called
-        mWindowLayoutComponent.addWindowLayoutInfoListener(mActivity, windowLayoutInfoConsumer);
+        mWindowLayoutComponent.addWindowLayoutInfoListener(activity, windowLayoutInfoConsumer);
+        // Initial registration invokes a consumer callback synchronously, clear the queue to
+        // make sure there's no residual value or from the first orientation change.
+        windowLayoutInfoConsumer.clearQueue();
 
         // Change the activity orientation - onWindowLayoutChanged should be called
-        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+        setActivityOrientationActivityDoesNotHandleOrientationChanges(activity,
                 ORIENTATION_LANDSCAPE);
 
+        // Check we have received exactly one layout update.
+        assertNotNull(windowLayoutInfoConsumer.waitAndGet());
+
         // Remove the listener
         mWindowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
+        windowLayoutInfoConsumer.clearQueue();
 
         // Change the activity orientation - onWindowLayoutChanged should NOT be called
-        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+        setActivityOrientationActivityDoesNotHandleOrientationChanges(activity,
                 ORIENTATION_PORTRAIT);
-
-        // Check that the countdown is zero
         WindowLayoutInfo lastValue = windowLayoutInfoConsumer.waitAndGet();
-        assertNotNull(lastValue);
+        assertNull(lastValue);
     }
 
     @Test
-    public void testWindowLayoutComponent_WindowLayoutInfoListener() {
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener"})
+    public void testWindowLayoutComponent_windowLayoutInfoListener() {
+        TestActivity activity = (TestActivity) startFullScreenActivityNewTask(TestActivity.class,
+                null /* activityId */);
         TestValueCountJavaConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
                 new TestValueCountJavaConsumer<>();
         // Test that adding and removing callback succeeds
-        mWindowLayoutComponent.addWindowLayoutInfoListener(mActivity, windowLayoutInfoConsumer);
+        mWindowLayoutComponent.addWindowLayoutInfoListener(activity, windowLayoutInfoConsumer);
         mWindowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
     }
 
+    @ApiTest(apis = {"androidx.window.extensions.layout.WindowLayoutInfo#getDisplayFeatures"})
     @Test
-    public void testDisplayFeatures()
+    public void testWindowLayoutComponent_providesWindowLayoutFromActivity()
             throws ExecutionException, InterruptedException, TimeoutException {
-        mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
+        TestActivity activity = (TestActivity) startActivityNewTask(TestActivity.class);
+        mWindowLayoutInfo = getExtensionWindowLayoutInfo(activity);
         assumeHasDisplayFeatures(mWindowLayoutInfo);
         for (DisplayFeature displayFeature : mWindowLayoutInfo.getDisplayFeatures()) {
             // Check that the feature bounds are valid
@@ -152,7 +203,7 @@
             // The feature cannot have zero area
             assertNotBothDimensionsZero(featureRect);
             // The feature cannot be outside the activity bounds
-            assertTrue(getActivityBounds(mActivity).contains(featureRect));
+            assertTrue(getActivityBounds(activity).contains(featureRect));
 
             if (displayFeature instanceof FoldingFeature) {
                 // Check that the folding feature has a valid type and state
@@ -170,57 +221,204 @@
     }
 
     @Test
-    public void testGetWindowLayoutInfo_configChanged_windowLayoutUpdates()
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutInfo#getDisplayFeatures"})
+    public void testWindowLayoutComponent_providesWindowLayoutFromWindowContext()
             throws ExecutionException, InterruptedException, TimeoutException {
-        mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
+        assumeExtensionVersionSupportsWindowContextLayout();
+        Context windowContext = createContextWithNonActivityWindow();
+
+        mWindowLayoutInfo = getExtensionWindowLayoutInfo(windowContext);
         assumeHasDisplayFeatures(mWindowLayoutInfo);
 
-        TestConfigChangeHandlingActivity configHandlingActivity
-                = (TestConfigChangeHandlingActivity) startActivityNewTask(
-                TestConfigChangeHandlingActivity.class);
+        // Verify that window layouts and metrics are reasonable.
+        WindowManager mWm = windowContext.getSystemService(WindowManager.class);
+        final WindowMetrics currentMetrics = mWm.getCurrentWindowMetrics();
 
-        setActivityOrientationActivityHandlesOrientationChanges(configHandlingActivity,
-                ORIENTATION_PORTRAIT);
-        final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(
-                configHandlingActivity);
-        final Rect portraitBounds = getActivityBounds(configHandlingActivity);
-        final Rect portraitMaximumBounds = getMaximumActivityBounds(configHandlingActivity);
-
-        setActivityOrientationActivityHandlesOrientationChanges(configHandlingActivity,
-                ORIENTATION_LANDSCAPE);
-        final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(
-                configHandlingActivity);
-        final Rect landscapeBounds = getActivityBounds(configHandlingActivity);
-        final Rect landscapeMaximumBounds = getMaximumActivityBounds(configHandlingActivity);
-
-        final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
-                portraitMaximumBounds, landscapeMaximumBounds);
-        assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
-                portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+        for (DisplayFeature displayFeature : mWindowLayoutInfo.getDisplayFeatures()) {
+            final Rect featureRect = displayFeature.getBounds();
+            assertHasNonNegativeDimensions(featureRect);
+            assertNotBothDimensionsZero(featureRect);
+            assertTrue(currentMetrics.getBounds().contains(featureRect));
+        }
     }
 
     @Test
-    public void testGetWindowLayoutInfo_windowRecreated_windowLayoutUpdates()
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener"})
+    public void testWindowLayoutComponent_windowLayoutMatchesBetweenActivityAndWindowContext()
             throws ExecutionException, InterruptedException, TimeoutException {
-        mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
+        assumeExtensionVersionSupportsWindowContextLayout();
+        TestConfigChangeHandlingActivity activity =
+                (TestConfigChangeHandlingActivity) startFullScreenActivityNewTask(
+                        TestConfigChangeHandlingActivity.class, null /* activityId */);
+        Context windowContext = createContextWithNonActivityWindow();
+
+        WindowLayoutInfo windowLayoutInfoFromContext = getExtensionWindowLayoutInfo(windowContext);
+        WindowLayoutInfo windowLayoutInfoFromActivity = getExtensionWindowLayoutInfo(activity);
+
+        assertEquals(windowLayoutInfoFromContext, windowLayoutInfoFromActivity);
+    }
+
+    @ApiTest(apis = {"androidx.window.extensions.layout.WindowLayoutInfo#getDisplayFeatures"})
+    @Test
+    public void testGetWindowLayoutInfo_configChanged_windowLayoutUpdates()
+            throws InterruptedException {
+        assumeSupportsRotation();
+
+        final TestConfigChangeHandlingActivity activity = startFullScreenActivityNewTask(
+                TestConfigChangeHandlingActivity.class, null /* activityId */);
+        mWindowLayoutInfo = getExtensionWindowLayoutInfo(activity);
         assumeHasDisplayFeatures(mWindowLayoutInfo);
 
-        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
-                ORIENTATION_PORTRAIT);
-        final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
-        final Rect portraitBounds = getActivityBounds(mActivity);
-        final Rect portraitMaximumBounds = getMaximumActivityBounds(mActivity);
+        try (IgnoreOrientationRequestSession session =
+                     new IgnoreOrientationRequestSession(false /* enable */)) {
+            setActivityOrientationActivityHandlesOrientationChanges(activity,
+                    ORIENTATION_PORTRAIT);
+            final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(
+                    activity);
+            final Rect portraitBounds = getActivityBounds(activity);
+            final Rect portraitMaximumBounds = getMaximumActivityBounds(activity);
 
-        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
-                ORIENTATION_LANDSCAPE);
-        final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
-        final Rect landscapeBounds = getActivityBounds(mActivity);
-        final Rect landscapeMaximumBounds = getMaximumActivityBounds(mActivity);
+            setActivityOrientationActivityHandlesOrientationChanges(activity,
+                    ORIENTATION_LANDSCAPE);
+            final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(
+                    activity);
+            final Rect landscapeBounds = getActivityBounds(activity);
+            final Rect landscapeMaximumBounds = getMaximumActivityBounds(activity);
 
-        final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
-                portraitMaximumBounds, landscapeMaximumBounds);
-        assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
-                portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+            final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
+                    portraitMaximumBounds, landscapeMaximumBounds);
+            assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
+                    portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+        }
+    }
+
+    @ApiTest(apis = {"androidx.window.extensions.layout.WindowLayoutInfo#getDisplayFeatures"})
+    @Test
+    public void testGetWindowLayoutInfo_enterExitPip_windowLayoutInfoMatches()
+            throws InterruptedException {
+        TestConfigChangeHandlingActivity configHandlingActivity = startActivityNewTask(
+                        TestConfigChangeHandlingActivity.class, null);
+        mWindowLayoutInfo = getExtensionWindowLayoutInfo(configHandlingActivity);
+        assumeHasDisplayFeatures(mWindowLayoutInfo);
+
+        final WindowLayoutInfo initialInfo = getExtensionWindowLayoutInfo(
+                configHandlingActivity);
+
+        enterPipActivityHandlesConfigChanges(configHandlingActivity);
+        exitPipActivityHandlesConfigChanges(configHandlingActivity);
+
+        final WindowLayoutInfo updatedInfo = getExtensionWindowLayoutInfo(
+                configHandlingActivity);
+
+        assertEquals(initialInfo, updatedInfo);
+    }
+
+    /*
+     * Similar to #testGetWindowLayoutInfo_configChanged_windowLayoutUpdates, here we trigger
+     * a rotation with a full screen activity on one Display Area, verify that WindowLayoutInfo
+     * from both Activity and WindowContext are updated with callbacks.
+     */
+    @FlakyTest(bugId = 254056760)
+    @Test
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener",
+            "androidx.window.extensions.layout.WindowLayoutComponent#removeWindowLayoutInfoListener"
+    })
+    public void testWindowLayoutComponent_updatesWindowLayoutFromContextAfterRotation()
+            throws InterruptedException {
+        assumeExtensionVersionSupportsWindowContextLayout();
+        assumeSupportsRotation();
+
+        final TestConfigChangeHandlingActivity activity = startFullScreenActivityNewTask(
+                TestConfigChangeHandlingActivity.class, null /* activityId */);
+
+        try (IgnoreOrientationRequestSession session =
+                     new IgnoreOrientationRequestSession(false /* enable */)) {
+            // Fix the device orientation before the test begins.
+            setActivityOrientationActivityHandlesOrientationChanges(activity,
+                    ORIENTATION_PORTRAIT);
+
+            // Here we make an assumption that the full-screen activity and the APPLICATION_OVERLAY
+            // Window are located in the same area on Display.
+            Context windowContext = createContextWithNonActivityWindow();
+            WindowLayoutInfo firstWindowLayoutContext = getExtensionWindowLayoutInfo(windowContext);
+            Rect windowContextBounds = windowContext.getSystemService(
+                    WindowManager.class).getCurrentWindowMetrics().getBounds();
+
+            final Rect firstBounds = getActivityBounds(activity);
+            final Rect firstMaximumBounds = getMaximumActivityBounds(activity);
+            WindowLayoutInfo firstWindowLayoutActivity = getExtensionWindowLayoutInfo(
+                    activity);
+            boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
+                    firstMaximumBounds, windowContextBounds);
+            assertEqualWindowLayoutInfo(firstWindowLayoutActivity, firstWindowLayoutContext,
+                    firstBounds, windowContextBounds, doesDisplayRotateForOrientation);
+
+            // Trigger a rotation to the Display via Activity orientation request.
+            setActivityOrientationActivityHandlesOrientationChanges(activity,
+                    ORIENTATION_LANDSCAPE);
+
+            WindowLayoutInfo secondWindowLayoutActivity = getExtensionWindowLayoutInfo(
+                    activity);
+            final Rect secondBounds = getActivityBounds(activity);
+            final Rect secondMaximumBounds = getMaximumActivityBounds(activity);
+
+            // We assume after rotation both the Activity and the OVERLAY window are still located
+            // in the same area, so their Display Features are still the same.
+            WindowLayoutInfo secondWindowLayoutContext = getExtensionWindowLayoutInfo(
+                    windowContext);
+            Rect secondWindowContextBounds = windowContext.getSystemService(
+                            WindowManager.class).getCurrentWindowMetrics()
+                    .getBounds();
+            assertEqualWindowLayoutInfo(secondWindowLayoutActivity, secondWindowLayoutContext,
+                    secondBounds, secondWindowContextBounds,
+                    doesDisplayRotateForOrientation(secondMaximumBounds,
+                            secondWindowContextBounds));
+
+            // Verify Activity Display Feature is consistent regardless of rotation.
+            doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
+                    firstMaximumBounds, secondMaximumBounds);
+            assertEqualWindowLayoutInfo(firstWindowLayoutActivity, secondWindowLayoutActivity,
+                    firstBounds, secondBounds, doesDisplayRotateForOrientation);
+        }
+    }
+
+    @Test
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener"})
+    public void testGetWindowLayoutInfo_windowRecreated_windowLayoutUpdates()
+            throws  InterruptedException {
+        assumeSupportsRotation();
+
+        final TestActivity activity = startFullScreenActivityNewTask(TestActivity.class,
+                null /* activityId */);
+
+        try (IgnoreOrientationRequestSession session =
+                     new IgnoreOrientationRequestSession(false /* enable */)) {
+            mWindowLayoutInfo = getExtensionWindowLayoutInfo(activity);
+            assumeHasDisplayFeatures(mWindowLayoutInfo);
+
+            setActivityOrientationActivityDoesNotHandleOrientationChanges(activity,
+                    ORIENTATION_PORTRAIT);
+            final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(
+                    activity);
+            final Rect portraitBounds = getActivityBounds(activity);
+            final Rect portraitMaximumBounds = getMaximumActivityBounds(activity);
+
+            setActivityOrientationActivityDoesNotHandleOrientationChanges(activity,
+                    ORIENTATION_LANDSCAPE);
+            final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(
+                    activity);
+            final Rect landscapeBounds = getActivityBounds(activity);
+            final Rect landscapeMaximumBounds = getMaximumActivityBounds(activity);
+
+            final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
+                    portraitMaximumBounds, landscapeMaximumBounds);
+            assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
+                    portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+        }
     }
 
     /**
@@ -230,8 +428,10 @@
     @Test
     public void testSidecarHasSameDisplayFeatures()
             throws ExecutionException, InterruptedException, TimeoutException {
-        assumeSidecarSupportedDevice(mActivity);
-        mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
+        TestActivity activity = (TestActivity) startFullScreenActivityNewTask(TestActivity.class,
+                null /* activityId */);
+        assumeSidecarSupportedDevice(activity);
+        mWindowLayoutInfo = getExtensionWindowLayoutInfo(activity);
         assumeHasDisplayFeatures(mWindowLayoutInfo);
 
         // Retrieve and sort the extension folding features
@@ -244,9 +444,9 @@
 
         // Retrieve and sort the sidecar display features in the same order as the extension
         // display features
-        final SidecarInterface sidecarInterface = getSidecarInterface(mActivity);
+        final SidecarInterface sidecarInterface = getSidecarInterface(activity);
         final List<SidecarDisplayFeature> sidecarDisplayFeatures = sidecarInterface
-                .getWindowLayoutInfo(getActivityWindowToken(mActivity)).displayFeatures;
+                .getWindowLayoutInfo(getActivityWindowToken(activity)).displayFeatures;
 
         // Check that the display features are the same
         assertEquals(extensionFoldingFeatures.size(), sidecarDisplayFeatures.size());
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SidecarTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SidecarTest.java
index ddd63a7..f30a7d4 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SidecarTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SidecarTest.java
@@ -174,8 +174,7 @@
 
         // The value is verified inside TestGetWindowLayoutInfoActivity
         TestGetWindowLayoutInfoActivity.resetResumeCounter();
-        TestGetWindowLayoutInfoActivity testGetWindowLayoutInfoActivity
-                = (TestGetWindowLayoutInfoActivity) startActivityNewTask(
+        TestGetWindowLayoutInfoActivity testGetWindowLayoutInfoActivity = startActivityNewTask(
                         TestGetWindowLayoutInfoActivity.class);
 
         // Make sure the activity has gone through all states.
@@ -187,8 +186,7 @@
     public void testGetWindowLayoutInfo_configChanged_windowLayoutUpdates() {
         assumeHasDisplayFeatures(mSidecarInterface, mWindowToken);
 
-        TestConfigChangeHandlingActivity configHandlingActivity
-                = (TestConfigChangeHandlingActivity) startActivityNewTask(
+        TestConfigChangeHandlingActivity configHandlingActivity = startActivityNewTask(
                 TestConfigChangeHandlingActivity.class);
         SidecarInterface sidecar = getSidecarInterface(configHandlingActivity);
         assertThat(sidecar).isNotNull();
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/WindowExtensionsImplTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/WindowExtensionsImplTest.java
index fce9ac2..fd14846 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/WindowExtensionsImplTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/WindowExtensionsImplTest.java
@@ -16,7 +16,7 @@
 
 package android.server.wm.jetpack;
 
-import static android.server.wm.jetpack.utils.ExtensionUtil.MINIMUM_STABLE_EXTENSION_VERSION;
+import static android.server.wm.jetpack.utils.ExtensionUtil.EXTENSION_VERSION_1;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionVersion;
 
@@ -46,6 +46,6 @@
     @Test
     public void testVerifiesExtensionVendorApiLevel() {
         assumeExtensionSupportedDevice();
-        assertTrue(getExtensionVersion().compareTo(MINIMUM_STABLE_EXTENSION_VERSION) >= 0);
+        assertTrue(getExtensionVersion().compareTo(EXTENSION_VERSION_1) >= 0);
     }
 }
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
index aeb1cbf..84873b2 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
@@ -27,6 +27,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
@@ -178,6 +179,21 @@
         return secondaryActivity;
     }
 
+    public static void startActivityAndVerifyNoCallback(@NonNull Activity activityLaunchingFrom,
+            @NonNull Class secondActivityClass, @NonNull String secondaryActivityId,
+            @NonNull TestValueCountConsumer<List<SplitInfo>> splitInfoConsumer) throws Exception {
+        // We expect the actual count to be 0. Set to 1 to trigger the timeout and verify no calls.
+        splitInfoConsumer.setCount(1);
+
+        // Start second activity
+        startActivityFromActivity(activityLaunchingFrom, secondActivityClass, secondaryActivityId);
+
+        // A split info callback should occur after the new activity is launched because the split
+        // states have changed.
+        List<SplitInfo> activeSplitStates = splitInfoConsumer.waitAndGet();
+        assertNull("Received SplitInfo value but did not expect none.", activeSplitStates);
+    }
+
     public static Activity startActivityAndVerifySplit(@NonNull Activity primaryActivity,
             @NonNull Class secondActivityClass, @NonNull SplitPairRule splitPairRule,
             @NonNull String secondActivityId, int expectedCallbackCount,
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/Condition.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/Condition.java
new file mode 100644
index 0000000..e696c84
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/Condition.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.utils;
+
+import static android.server.wm.jetpack.utils.StateLogger.logAlways;
+import static android.server.wm.jetpack.utils.StateLogger.logE;
+
+import android.os.SystemClock;
+
+import java.util.concurrent.TimeUnit;
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * The utility class to wait a condition with customized options.
+ * The default retry policy is 5 times with interval 1 second.
+ *
+ * @param <T> The type of the object to validate.
+ *
+ * <p>Sample:</p>
+ * <pre>
+ * // Simple case.
+ * if (Condition.waitFor("true value", () -> true)) {
+ *     println("Success");
+ * }
+ * // Wait for customized result with customized validation.
+ * String result = Condition.waitForResult(new Condition<String>("string comparison")
+ *         .setResultSupplier(() -> "Result string")
+ *         .setResultValidator(str -> str.equals("Expected string"))
+ *         .setRetryIntervalMs(500)
+ *         .setRetryLimit(3)
+ *         .setOnFailure(str -> println("Failed on " + str)));
+ * </pre>
+ */
+public class Condition<T> {
+    private final String mMessage;
+
+    // TODO(b/112837428): Implement a incremental retry policy to reduce the unnecessary constant
+    // time, currently keep the default as 5*1s because most of the original code uses it, and some
+    // tests might be sensitive to the waiting interval.
+    private long mRetryIntervalMs = TimeUnit.SECONDS.toMillis(1);
+    private int mRetryLimit = 5;
+    private boolean mReturnLastResult;
+
+    /** It decides whether this condition is satisfied. */
+    private BooleanSupplier mSatisfier;
+    /**
+     * It is used when the condition is not a simple boolean expression, such as the caller may want
+     * to get the validated product as the return value.
+     */
+    private Supplier<T> mResultSupplier;
+    /** It validates the result from {@link #mResultSupplier}. */
+    private Predicate<T> mResultValidator;
+    private Consumer<T> mOnFailure;
+    private Runnable mOnRetry;
+    private T mLastResult;
+    private T mValidatedResult;
+
+    /**
+     * When using this constructor, it is expected that the condition will be configured with
+     * {@link #setResultSupplier} and {@link #setResultValidator}.
+     */
+    public Condition(String message) {
+        this(message, null /* satisfier */);
+    }
+
+    /**
+     * Constructs with a simple boolean condition.
+     *
+     * @param message The message to show what is waiting for.
+     * @param satisfier If it returns true, that means the condition is satisfied.
+     */
+    public Condition(String message, BooleanSupplier satisfier) {
+        mMessage = message;
+        mSatisfier = satisfier;
+    }
+
+    /** Set the supplier which provides the result object to validate. */
+    public Condition<T> setResultSupplier(Supplier<T> supplier) {
+        mResultSupplier = supplier;
+        return this;
+    }
+
+    /** Set the validator which tests the object provided by the supplier. */
+    public Condition<T> setResultValidator(Predicate<T> validator) {
+        mResultValidator = validator;
+        return this;
+    }
+
+    /**
+     * If true, when using {@link #waitForResult(Condition)}, the method will return the last result
+     * provided by {@link #mResultSupplier} even it is not valid (by {@link #mResultValidator}).
+     */
+    public Condition<T> setReturnLastResult(boolean returnLastResult) {
+        mReturnLastResult = returnLastResult;
+        return this;
+    }
+
+    /**
+     * Executes the action when the condition does not satisfy within the time limit. The passed
+     * object to the consumer will be the last result from the supplier.
+     */
+    public Condition<T> setOnFailure(Consumer<T> onFailure) {
+        mOnFailure = onFailure;
+        return this;
+    }
+
+    public Condition<T> setOnRetry(Runnable onRetry) {
+        mOnRetry = onRetry;
+        return this;
+    }
+
+    public Condition<T> setRetryIntervalMs(long millis) {
+        mRetryIntervalMs = millis;
+        return this;
+    }
+
+    public Condition<T> setRetryLimit(int limit) {
+        mRetryLimit = limit;
+        return this;
+    }
+
+    /** Build the condition by {@link #mResultSupplier} and {@link #mResultValidator}. */
+    private void prepareSatisfier() {
+        if (mResultSupplier == null || mResultValidator == null) {
+            throw new IllegalArgumentException("No specified condition");
+        }
+
+        mSatisfier = () -> {
+            final T result = mResultSupplier.get();
+            mLastResult = result;
+            if (mResultValidator.test(result)) {
+                mValidatedResult = result;
+                return true;
+            }
+            return false;
+        };
+    }
+
+    /**
+     * @see #waitFor(Condition)
+     * @see #Condition(String, BooleanSupplier)
+     */
+    public static boolean waitFor(String message, BooleanSupplier satisfier) {
+        return waitFor(new Condition<>(message, satisfier));
+    }
+
+    /** @return {@code false} if the condition does not satisfy within the time limit. */
+    public static <T> boolean waitFor(Condition<T> condition) {
+        if (condition.mSatisfier == null) {
+            condition.prepareSatisfier();
+        }
+
+        final long startTime = SystemClock.elapsedRealtime();
+        for (int i = 1; i <= condition.mRetryLimit; i++) {
+            if (condition.mSatisfier.getAsBoolean()) {
+                return true;
+            } else {
+                SystemClock.sleep(condition.mRetryIntervalMs);
+                logAlways("***Waiting for " + condition.mMessage + " ... retry=" + i
+                        + " elapsed=" + (SystemClock.elapsedRealtime() - startTime) + "ms");
+                if (condition.mOnRetry != null && i < condition.mRetryLimit) {
+                    condition.mOnRetry.run();
+                }
+            }
+        }
+        if (condition.mSatisfier.getAsBoolean()) {
+            return true;
+        }
+
+        if (condition.mOnFailure == null) {
+            logE("Condition is not satisfied: " + condition.mMessage);
+        } else {
+            condition.mOnFailure.accept(condition.mLastResult);
+        }
+        return false;
+    }
+
+    /** @see #waitForResult(Condition) */
+    public static <T> T waitForResult(String message, Consumer<Condition<T>> setup) {
+        final Condition<T> condition = new Condition<>(message);
+        setup.accept(condition);
+        return waitForResult(condition);
+    }
+
+    /**
+     * @return {@code null} if the condition does not satisfy within the time limit or the result
+     *         supplier returns {@code null}.
+     */
+    public static <T> T waitForResult(Condition<T> condition) {
+        condition.mLastResult = condition.mValidatedResult = null;
+        condition.prepareSatisfier();
+        waitFor(condition);
+        if (condition.mValidatedResult != null) {
+            return condition.mValidatedResult;
+        }
+        return condition.mReturnLastResult ? condition.mLastResult : null;
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
index 02846a7..245052e 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
@@ -23,11 +23,13 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.app.Activity;
+import android.content.Context;
 import android.graphics.Rect;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.UiContext;
 import androidx.window.extensions.WindowExtensions;
 import androidx.window.extensions.WindowExtensionsProvider;
 import androidx.window.extensions.area.WindowAreaComponent;
@@ -37,8 +39,6 @@
 import androidx.window.extensions.layout.WindowLayoutInfo;
 
 import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
 import java.util.stream.Collectors;
 
 /**
@@ -50,7 +50,9 @@
 
     private static final String EXTENSION_TAG = "Extension";
 
-    public static final Version MINIMUM_STABLE_EXTENSION_VERSION = new Version(1, 0, 0, "");
+    public static final Version EXTENSION_VERSION_1 = new Version(1, 0, 0, "");
+
+    public static final Version EXTENSION_VERSION_2 = new Version(1, 1, 0, "");
 
     @NonNull
     public static Version getExtensionVersion() {
@@ -68,10 +70,29 @@
         return Version.UNKNOWN;
     }
 
+    public static boolean isExtensionVersionAtLeast(Version targetVersion) {
+        final Version version = getExtensionVersion();
+        return version.compareTo(targetVersion) >= 0;
+    }
+
+    /**
+     * If called on a device with the vendor api level less than the bound then the test will be
+     * ignored.
+     * @param vendorApiLevel minimum {@link WindowExtensions#getVendorApiLevel()} for a test to
+     *                       succeed
+     */
+    public static void assumeVendorApiLevelAtLeast(int vendorApiLevel) {
+        final Version version = getExtensionVersion();
+        assumeTrue(
+                "Needs vendorApiLevel " + vendorApiLevel + " but has " + version.getMajor(),
+                version.getMajor() >= vendorApiLevel
+        );
+    }
+
     public static boolean isExtensionVersionValid() {
         final Version version = getExtensionVersion();
         // Check that the extension version on the device is at least the minimum valid version.
-        return version.compareTo(MINIMUM_STABLE_EXTENSION_VERSION) >= 0;
+        return version.compareTo(EXTENSION_VERSION_1) >= 0;
     }
 
     @Nullable
@@ -91,7 +112,7 @@
         assumeTrue("Device does not support extensions", extensionNotNull);
         // If extensions are on the device, make sure that the version is valid.
         assertTrue("Extension version is invalid, must be at least "
-                + MINIMUM_STABLE_EXTENSION_VERSION.toString(), isExtensionVersionValid());
+                + EXTENSION_VERSION_1.toString(), isExtensionVersionValid());
     }
 
     @Nullable
@@ -103,9 +124,15 @@
         return extension.getWindowLayoutComponent();
     }
 
+    /**
+     * Publishes a WindowLayoutInfo update to a test consumer. In EXTENSION_VERSION_1, only type
+     * Activity can be the listener to WindowLayoutInfo changes. This method should be called at
+     * most once for each given Activity because addWindowLayoutInfoListener implementation
+     * assumes a 1-1 mapping between the activity and consumer.
+     */
     @Nullable
     public static WindowLayoutInfo getExtensionWindowLayoutInfo(Activity activity)
-            throws ExecutionException, InterruptedException, TimeoutException {
+            throws InterruptedException {
         WindowLayoutComponent windowLayoutComponent = getExtensionWindowLayoutComponent();
         if (windowLayoutComponent == null) {
             return null;
@@ -113,12 +140,46 @@
         TestValueCountJavaConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
                 new TestValueCountJavaConsumer<>();
         windowLayoutComponent.addWindowLayoutInfoListener(activity, windowLayoutInfoConsumer);
-        return windowLayoutInfoConsumer.waitAndGet();
+        WindowLayoutInfo info = windowLayoutInfoConsumer.waitAndGet();
+
+        // The default implementation only allows a single listener per activity. Since we are using
+        // a local windowLayoutInfoConsumer within this function, we must remember to clean up.
+        // Otherwise, subsequent calls to addWindowLayoutInfoListener with the same activity will
+        // fail to have its callback registered.
+        windowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
+        return info;
+    }
+
+    /**
+     * Publishes a WindowLayoutInfo update to a test consumer. In EXTENSION_VERSION_2 both type
+     * WindowContext and Activity can be listeners. This method should be called at most once for
+     * each given Context because addWindowLayoutInfoListener implementation assumes a 1-1
+     * mapping between the context and consumer.
+     */
+    @Nullable
+    public static WindowLayoutInfo getExtensionWindowLayoutInfo(@UiContext Context context)
+            throws InterruptedException {
+        assertTrue(isExtensionVersionAtLeast(EXTENSION_VERSION_2));
+        WindowLayoutComponent windowLayoutComponent = getExtensionWindowLayoutComponent();
+        if (windowLayoutComponent == null) {
+            return null;
+        }
+        TestValueCountConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
+                new TestValueCountConsumer<>();
+        windowLayoutComponent.addWindowLayoutInfoListener(context, windowLayoutInfoConsumer);
+        WindowLayoutInfo info = windowLayoutInfoConsumer.waitAndGet();
+
+        // The default implementation only allows a single listener per context. Since we are using
+        // a local windowLayoutInfoConsumer within this function, we must remember to clean up.
+        // Otherwise, subsequent calls to addWindowLayoutInfoListener with the same context will
+        // fail to have its callback registered.
+        windowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
+        return info;
     }
 
     @NonNull
     public static int[] getExtensionDisplayFeatureTypes(Activity activity)
-            throws ExecutionException, InterruptedException, TimeoutException {
+            throws InterruptedException {
         WindowLayoutInfo windowLayoutInfo = getExtensionWindowLayoutInfo(activity);
         if (windowLayoutInfo == null) {
             return new int[0];
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/StateLogger.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/StateLogger.java
new file mode 100644
index 0000000..a21a847
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/StateLogger.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.utils;
+
+import android.os.Build;
+import android.util.Log;
+
+/**
+ * Util class to perform simple state logging.
+ */
+public class StateLogger {
+
+    private static final boolean DEBUG = "eng".equals(Build.TYPE);
+    private static String TAG = "WmJetpack";
+
+    /**
+     * Simple info-level logging gated by {@link #DEBUG} flag
+     */
+    public static void log(String logText) {
+        if (DEBUG) {
+            Log.i(TAG, logText);
+        }
+    }
+
+    public static void logAlways(String logText) {
+        Log.i(TAG, logText);
+    }
+
+    public static void logE(String logText) {
+        Log.e(TAG, logText);
+    }
+
+    public static void logE(String logText, Throwable e) {
+        Log.e(TAG, logText, e);
+    }
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityLauncher.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityLauncher.java
new file mode 100644
index 0000000..ee2fcba
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityLauncher.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.jetpack.utils;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class TestActivityLauncher<T extends Activity> {
+
+    /** Key for string extra, ID to track an Activity that is launched. */
+    public static final String KEY_ACTIVITY_ID = "ActivityID";
+    /**
+     * Options that will be passed to the instrumentation.
+     * @see TestActivityLauncher#launch(Instrumentation)
+     */
+    private final ActivityOptions mOptions = ActivityOptions.makeBasic();
+
+    /**
+     * The class for the {@link Activity} that you are launching.
+     */
+    private final Class<T> mActivityClass;
+
+    /**
+     * The intent that will be used to launch the {@link Activity}.
+     */
+    private final Intent mIntent;
+
+    public TestActivityLauncher(@NonNull Context context, @NonNull Class<T> activityClass) {
+        mActivityClass = activityClass;
+        mIntent = new Intent(context, activityClass);
+    }
+
+    public TestActivityLauncher<T> addIntentFlag(int flag) {
+        mIntent.addFlags(flag);
+        return this;
+    }
+
+    public TestActivityLauncher<T> setActivityId(@Nullable String id) {
+        mIntent.putExtra(KEY_ACTIVITY_ID, id);
+        return this;
+    }
+
+    public TestActivityLauncher<T> setWindowingMode(int windowingMode) {
+        mOptions.setLaunchWindowingMode(windowingMode);
+        return this;
+    }
+
+    public T launch(@NonNull Instrumentation instrumentation) {
+        return mActivityClass.cast(instrumentation.startActivitySync(mIntent, mOptions.toBundle()));
+    }
+
+}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityWithId.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityWithId.java
index 1987020..455db39 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityWithId.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivityWithId.java
@@ -16,7 +16,7 @@
 
 package android.server.wm.jetpack.utils;
 
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.ACTIVITY_ID_LABEL;
+import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
 
 import android.content.Intent;
 import android.os.Bundle;
@@ -37,8 +37,8 @@
 
         // Get ID
         Intent intent = getIntent();
-        if (intent != null && intent.hasExtra(ACTIVITY_ID_LABEL)) {
-            mId = intent.getStringExtra(ACTIVITY_ID_LABEL);
+        if (intent != null && intent.hasExtra(KEY_ACTIVITY_ID)) {
+            mId = intent.getStringExtra(KEY_ACTIVITY_ID);
         }
     }
 
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java
index 10fe6fc..f221875 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java
@@ -62,6 +62,11 @@
         return value;
     }
 
+    // Doesn't change the count.
+    public void clearQueue() {
+        mLinkedBlockingQueue.clear();
+    }
+
     @Nullable
     public T getLastReportedValue() {
         return mLastReportedValue;
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java
index dd9c168..981570e 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java
@@ -16,12 +16,17 @@
 
 package android.server.wm.jetpack.utils;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE;
+import static android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -30,11 +35,14 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import android.app.Activity;
 import android.app.ActivityOptions;
 import android.app.Application;
 import android.app.Instrumentation;
+import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -53,11 +61,11 @@
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.function.BooleanSupplier;
 
 /** Base class for all tests in the module. */
 public class WindowManagerJetpackTestBase {
 
-    public static final String ACTIVITY_ID_LABEL = "ActivityID";
     public static final String EXTRA_EMBED_ACTIVITY = "EmbedActivity";
     public static final String EXTRA_SPLIT_RATIO = "SplitRatio";
 
@@ -86,24 +94,52 @@
         sVisibleActivities.clear();
     }
 
-    public Activity startActivityNewTask(@NonNull Class activityClass) {
+    protected boolean hasDeviceFeature(final String requiredFeature) {
+        return mContext.getPackageManager().hasSystemFeature(requiredFeature);
+    }
+
+    /**
+     * Rotation support is indicated by explicitly having both landscape and portrait
+     * features or not listing either at all.
+     */
+    protected void assumeSupportsRotation() {
+        final boolean supportsLandscape = hasDeviceFeature(FEATURE_SCREEN_LANDSCAPE);
+        final boolean supportsPortrait = hasDeviceFeature(FEATURE_SCREEN_PORTRAIT);
+        assumeTrue((supportsLandscape && supportsPortrait)
+                || (!supportsLandscape && !supportsPortrait));
+    }
+
+    public <T extends Activity> T startActivityNewTask(@NonNull Class<T> activityClass) {
         return startActivityNewTask(activityClass, null /* activityId */);
     }
 
-    public Activity startActivityNewTask(@NonNull Class activityClass,
+    public <T extends Activity> T startActivityNewTask(@NonNull Class<T> activityClass,
             @Nullable String activityId) {
-        return startActivityNewTask(mContext, mInstrumentation, activityClass, activityId);
+        return launcherForActivityNewTask(activityClass, activityId, false /* isFullScreen */)
+                .launch(mInstrumentation);
     }
 
-    public static Activity startActivityNewTask(@NonNull Context context,
-            @NonNull Instrumentation instrumentation, @NonNull Class activityClass,
+    public <T extends  Activity> T startFullScreenActivityNewTask(@NonNull Class<T> activityClass,
             @Nullable String activityId) {
-        final Intent intent = new Intent(context, activityClass);
-        intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
-        if (activityId != null) {
-            intent.putExtra(ACTIVITY_ID_LABEL, activityId);
-        }
-        return instrumentation.startActivitySync(intent);
+        return launcherForActivityNewTask(activityClass, activityId, true/* isFullScreen */)
+                .launch(mInstrumentation);
+    }
+
+    private <T extends Activity> TestActivityLauncher<T> launcherForActivityNewTask(
+            @NonNull Class<T> activityClass, @Nullable String activityId, boolean isFullScreen) {
+        final int windowingMode = isFullScreen ? WINDOWING_MODE_FULLSCREEN :
+                WINDOWING_MODE_UNDEFINED;
+        return new TestActivityLauncher<>(mContext, activityClass)
+                .addIntentFlag(FLAG_ACTIVITY_NEW_TASK)
+                .setActivityId(activityId)
+                .setWindowingMode(windowingMode);
+    }
+
+    public static void waitForOrFail(String message, BooleanSupplier condition) {
+        Condition.waitFor(new Condition<>(message, condition)
+                .setRetryIntervalMs(500)
+                .setRetryLimit(5)
+                .setOnFailure(unusedResult -> fail("FAILED because unsatisfied: " + message)));
     }
 
     /**
@@ -141,7 +177,7 @@
     public static <T extends Activity> void startActivityFromActivity(Activity activityToLaunchFrom,
             Class<T> activityToLaunchClass, String newActivityId) {
         Intent intent = new Intent(activityToLaunchFrom, activityToLaunchClass);
-        intent.putExtra(ACTIVITY_ID_LABEL, newActivityId);
+        intent.putExtra(KEY_ACTIVITY_ID, newActivityId);
         activityToLaunchFrom.startActivity(intent);
     }
 
@@ -154,7 +190,7 @@
         Intent intent = new Intent();
         intent.setClassName(activityToLaunchComponent.getPackageName(),
                 activityToLaunchComponent.getClassName());
-        intent.putExtra(ACTIVITY_ID_LABEL, newActivityId);
+        intent.putExtra(KEY_ACTIVITY_ID, newActivityId);
         intent.putExtras(extras);
         activityToLaunchFrom.startActivity(intent);
     }
@@ -205,9 +241,36 @@
         activity.setRequestedOrientation(orientation == ORIENTATION_PORTRAIT
                 ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
         // Wait for the activity to layout, which will happen after the orientation change
+        waitForOrFail("Activity orientation must be updated",
+                () -> activity.getResources().getConfiguration().orientation == orientation);
+    }
+
+    public static void enterPipActivityHandlesConfigChanges(TestActivity activity) {
+        if (activity.isInPictureInPictureMode()) {
+            throw new IllegalStateException("Activity must not be in PiP");
+        }
+        activity.resetLayoutCounter();
+        // Change the orientation
+        PictureInPictureParams params = (new PictureInPictureParams.Builder()).build();
+        activity.enterPictureInPictureMode(params);
+        // Wait for the activity to layout, which will happen after the orientation change
         assertTrue(activity.waitForLayout());
         // Check that orientation matches
-        assertEquals(orientation, activity.getResources().getConfiguration().orientation);
+        assertTrue(activity.isInPictureInPictureMode());
+    }
+
+    public static void exitPipActivityHandlesConfigChanges(TestActivity activity) {
+        if (!activity.isInPictureInPictureMode()) {
+            throw new IllegalStateException("Activity must be in PiP");
+        }
+        activity.resetLayoutCounter();
+        Intent intent = new Intent(activity, activity.getClass());
+        intent.addFlags(FLAG_ACTIVITY_SINGLE_TOP);
+        activity.startActivity(intent);
+        // Wait for the activity to layout, which will happen after the orientation change
+        assertTrue(activity.waitForLayout());
+        // Check that orientation matches
+        assertFalse(activity.isInPictureInPictureMode());
     }
 
     public static void setActivityOrientationActivityDoesNotHandleOrientationChanges(
@@ -235,6 +298,10 @@
      * display rotates for orientation, then the maximum portrait bounds will be a rotated version
      * of the maximum landscape bounds.
      */
+    // TODO(b/186631239): ActivityManagerTestBase#ignoresOrientationRequests could disable
+    // activity rotation, as a result the display area would remain in the old orientation while
+    // the activity orientation changes. We should check the existence of this request before
+    // running tests that compare orientation values.
     public static boolean doesDisplayRotateForOrientation(@NonNull Rect portraitMaximumBounds,
             @NonNull Rect landscapeMaximumBounds) {
         return !portraitMaximumBounds.equals(landscapeMaximumBounds);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
index 436cd42..073e584 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
@@ -16,6 +16,7 @@
 
 package android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.server.wm.ActivityTransitionTests.EdgeExtensionActivity.BOTTOM;
 import static android.server.wm.ActivityTransitionTests.EdgeExtensionActivity.DIRECTION_KEY;
@@ -114,7 +115,9 @@
         final Intent intent = new Intent(mContext, LauncherActivity.class)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        return (LauncherActivity) instrumentation.startActivitySync(intent);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        return (LauncherActivity) instrumentation.startActivitySync(intent, options.toBundle());
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index 5af9c41..9ae1532 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -492,7 +492,7 @@
 
         // Start a portrait activity first to ensure that the orientation will change.
         launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
-        mWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
+        mWmState.waitForDisplayOrientation(ORIENTATION_PORTRAIT);
         final int prevRotation = mWmState.getRotation();
 
         getLaunchActivityBuilder()
@@ -502,7 +502,7 @@
                 // rotated but the activity is rotated.
                 .setIntentExtra(bundle -> bundle.putBoolean(EXTRA_CONFIG_INFO_IN_ON_CREATE, true))
                 .execute();
-        mWmState.waitForLastOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mWmState.waitForDisplayOrientation(ORIENTATION_LANDSCAPE);
 
         final SizeInfo reportedSizes =
                 getLastReportedSizesForActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
index 759b4e1..866b028 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
@@ -65,7 +65,6 @@
 public class AssistantStackTests extends ActivityManagerTestBase {
 
     private int mAssistantDisplayId = DEFAULT_DISPLAY;
-    private int mDefaultWindowingMode;
 
     public void setUp() throws Exception {
         super.setUp();
@@ -76,7 +75,6 @@
             WindowManagerState.Task assistantStack =
                     mWmState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT);
             mAssistantDisplayId = assistantStack.mDisplayId;
-            mDefaultWindowingMode = getDefaultDisplayWindowingMode();
         }
     }
 
@@ -92,7 +90,7 @@
             // Ensure that the activity launched in the fullscreen assistant stack
             assertAssistantStackExists();
             // In a multi-window environment the assistant might not be fullscreen
-            assumeTrue(mDefaultWindowingMode == WINDOWING_MODE_FULLSCREEN);
+            assumeTrue(getDefaultDisplayWindowingMode() == WINDOWING_MODE_FULLSCREEN);
             assertTrue("Expected assistant stack to be fullscreen",
                     mWmState.getRootTaskByActivityType(
                             ACTIVITY_TYPE_ASSISTANT).isFullscreen());
@@ -134,7 +132,7 @@
 
     @Test
     public void testAssistantStackLaunchNewTask() throws Exception {
-        assertAssistantStackCanLaunchAndReturnFromNewTask(mDefaultWindowingMode);
+        assertAssistantStackCanLaunchAndReturnFromNewTask();
     }
 
     @Test
@@ -151,7 +149,7 @@
         //assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
     }
 
-    private void assertAssistantStackCanLaunchAndReturnFromNewTask(int expectedWindowingMode)
+    private void assertAssistantStackCanLaunchAndReturnFromNewTask()
             throws Exception {
         // Enable the assistant and launch an assistant activity which will launch a new task
         try (final AssistantSession assistantSession = new AssistantSession()) {
@@ -161,8 +159,7 @@
                     extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)),
                     extraString(EXTRA_ASSISTANT_DISPLAY_ID, Integer.toString(mAssistantDisplayId)));
             // Ensure that the fullscreen stack is on top and the test activity is now visible
-            waitForValidStateWithActivityTypeAndWindowingMode(
-                    TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, expectedWindowingMode);
+            waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
         }
 
         if (isAssistantOnTopOfDream()) {
@@ -175,11 +172,13 @@
             mWmState.assertFocusedRootTask("Assistant stack should be focused.",
                     WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
         } else {
+            final int testActivityWindowingMode =
+                    mWmState.getTaskDisplayArea(TEST_ACTIVITY).getWindowingMode();
             mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
             mWmState.assertFrontStack("TestActivity stack should be on top.",
-                    expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+                    testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
             mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
-                    expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+                    testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
         }
 
         // Now, tell it to finish itself and ensure that the assistant stack is brought back forward
@@ -211,15 +210,17 @@
             mWmState.waitFor((amState) -> !amState.containsActivity(ASSISTANT_ACTIVITY),
                     getActivityName(ASSISTANT_ACTIVITY) + " finished");
         }
-        waitForValidStateWithActivityTypeAndWindowingMode(
-                TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
+        waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
         waitAndAssertTopResumedActivity(TEST_ACTIVITY, mAssistantDisplayId,
                 "TestActivity should be resumed");
         mWmState.assertFocusedActivity("TestActivity should be focused", TEST_ACTIVITY);
-        mWmState.assertFrontStack("Fullscreen stack should be on top.",
-                mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
-        mWmState.assertFocusedRootTask("Fullscreen stack should be focused.",
-                mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
+
+        final int testActivityWindowingMode =
+                mWmState.getTaskDisplayArea(TEST_ACTIVITY).getWindowingMode();
+        mWmState.assertFrontStack("TestActivity stack should be on top.",
+                testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
+        mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
+                testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
     }
 
     @Test
@@ -273,8 +274,7 @@
             launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                     extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"),
                     extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)));
-            waitForValidStateWithActivityTypeAndWindowingMode(
-                    TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
+            waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
 
             final ComponentName homeActivity = mWmState.getHomeActivityName();
             int windowingMode = mWmState.getFocusedRootTaskWindowingMode();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
index c1396d6..6109dec 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
@@ -253,17 +253,23 @@
             separateTestJournal();
             fontScaleSession.set(fontScale);
             mWmState.computeState(activityName);
-            assertRelaunchOrConfigChanged(activityName, relaunch ? 1 : 0, relaunch ? 0 : 1);
+            // The number of config changes could be greater than expected as there may have
+            // other configuration change events triggered after font scale changed, such as
+            // NavigationBar recreated.
+            new ActivityLifecycleCounts(activityName).assertCountWithRetry(
+                    "relaunch or config changed",
+                    countSpec(ActivityCallback.ON_DESTROY, CountSpec.EQUALS, relaunch ? 1 : 0),
+                    countSpec(ActivityCallback.ON_CREATE, CountSpec.EQUALS, relaunch ? 1 : 0),
+                    countSpec(ActivityCallback.ON_CONFIGURATION_CHANGED,
+                            CountSpec.GREATER_THAN_OR_EQUALS, relaunch ? 0 : 1));
 
             // Verify that the display metrics are updated, and therefore the text size is also
             // updated accordingly.
             final Bundle changedExtras = TestJournalContainer.get(activityName).extras;
+            final float scale = fontScale;
             waitForOrFail("reported fontPixelSize from " + activityName,
-                    () -> changedExtras.containsKey(EXTRA_FONT_PIXEL_SIZE));
-            final int expectedFontPixelSize =
-                    scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, fontScale, densityDpi);
-            assertEquals("Expected font pixel size should match", expectedFontPixelSize,
-                    changedExtras.getInt(EXTRA_FONT_PIXEL_SIZE));
+                    () -> scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, scale, densityDpi)
+                            == changedExtras.getInt(EXTRA_FONT_PIXEL_SIZE));
         }
     }
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
index ac06678..713958d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
@@ -28,6 +28,8 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.app.Activity;
+import android.content.res.Resources;
+import android.content.pm.PackageManager;
 import android.graphics.Insets;
 import android.os.Bundle;
 import android.view.View;
@@ -55,6 +57,7 @@
         assertNotNull("test setup failed", activity.mLastContentInsets);
         assumeFalse(Insets.NONE.equals(activity.mLastContentInsets.getInsetsIgnoringVisibility(
                 statusBars() | navigationBars())));
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             activity.mLayoutHappened = false;
@@ -113,4 +116,15 @@
             setContentView(view);
         }
     }
+
+    private static boolean remoteInsetsControllerControlsSystemBars() {
+        return InstrumentationRegistry.getInstrumentation().getTargetContext().getResources()
+                    .getBoolean(android.R.bool.config_remoteInsetsControllerControlsSystemBars);
+    }
+
+    private boolean isCar() {
+        PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
+                              .getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
index 75aa696..eea2396 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
@@ -171,74 +171,6 @@
         return result;
     }
 
-    public static class DisplayMetricsSession implements AutoCloseable {
-        private final ReportedDisplayMetrics mInitialDisplayMetrics;
-        private final int mDisplayId;
-
-        DisplayMetricsSession(int displayId) {
-            mDisplayId = displayId;
-            mInitialDisplayMetrics = ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
-        }
-
-        ReportedDisplayMetrics getInitialDisplayMetrics() {
-            return mInitialDisplayMetrics;
-        }
-
-        ReportedDisplayMetrics getDisplayMetrics() {
-            return ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
-        }
-
-        void changeAspectRatio(double aspectRatio, int orientation) {
-            final Size originalSize = mInitialDisplayMetrics.physicalSize;
-            final int smaller = Math.min(originalSize.getWidth(), originalSize.getHeight());
-            final int larger = (int) (smaller * aspectRatio);
-            Size overrideSize;
-            if (orientation == ORIENTATION_LANDSCAPE) {
-                overrideSize = new Size(larger, smaller);
-            }
-            else {
-                overrideSize = new Size(smaller, larger);
-            }
-            overrideDisplayMetrics(overrideSize, mInitialDisplayMetrics.physicalDensity);
-        }
-
-        void changeDisplayMetrics(double sizeRatio, double densityRatio) {
-            // Given a display may already have an override applied before the test is begun,
-            // resize based upon the override.
-            final Size originalSize;
-            final int density;
-            if (mInitialDisplayMetrics.overrideSize != null) {
-                originalSize = mInitialDisplayMetrics.overrideSize;
-            } else {
-                originalSize = mInitialDisplayMetrics.physicalSize;
-            }
-
-            if (mInitialDisplayMetrics.overrideDensity != null) {
-                density = mInitialDisplayMetrics.overrideDensity;
-            } else {
-                density = mInitialDisplayMetrics.physicalDensity;
-            }
-
-            final Size overrideSize = new Size((int)(originalSize.getWidth() * sizeRatio),
-                    (int)(originalSize.getHeight() * sizeRatio));
-            final int overrideDensity = (int)(density * densityRatio);
-            overrideDisplayMetrics(overrideSize, overrideDensity);
-        }
-
-        void overrideDisplayMetrics(final Size size, final int density) {
-            mInitialDisplayMetrics.setDisplayMetrics(size, density);
-        }
-
-        void restoreDisplayMetrics() {
-            mInitialDisplayMetrics.restoreDisplayMetrics();
-        }
-
-        @Override
-        public void close() {
-            restoreDisplayMetrics();
-        }
-    }
-
     /** @see ObjectTracker#manage(AutoCloseable) */
     protected DisplayMetricsSession createManagedDisplayMetricsSession(int displayId) {
         return mObjectTracker.manage(new DisplayMetricsSession(displayId));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
index c39aaa2..cbc4026 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
@@ -89,6 +89,7 @@
         // TODO(b/187757919): Allow Automotive to skip this test until privacy chip is implemented
         // in immersive mode
         assumeFalse(isCar());
+        assumeFalse(isWatch());
 
         final PrivacyIndicatorBoundsTests.TestActivity activity = mTestActivity.launchActivity(
                 new Intent().putExtra(EXTRA_ORIENTATION, orientation));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
index 4b7242e..7b75861b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.server.wm.SplitActivityLifecycleTest.ActivityB.EXTRA_SHOW_WHEN_LOCKED;
@@ -494,6 +495,39 @@
     }
 
     /**
+     * Verifies the Activity in primary TaskFragment is no longer focused after clear adjacent
+     * TaskFragments.
+     */
+    @Test
+    public void testResetFocusedAppAfterClearAdjacentTaskFragment() {
+        // TODO(b/232476698) Remove the assume in the next release.
+        assumeExtensionVersionAtLeast2();
+
+        // Initialize test environment by launching Activity A and B side-by-side.
+        initializeSplitActivities(false /* verifyEmbeddedTask */);
+
+        // Request the focus on the primary TaskFragment
+        WindowContainerTransaction wct = new WindowContainerTransaction()
+                .requestFocusOnTaskFragment(mTaskFragA.getTaskFragToken());
+        mTaskFragmentOrganizer.applyTransaction(wct);
+        waitForActivityFocused(5000, mActivityA);
+        assertThat(mWmState.getFocusedApp()).isEqualTo(mActivityA.flattenToShortString());
+
+        // Expand top TaskFragment and clear the adjacent TaskFragments to have the two
+        // TaskFragment stacked.
+        wct = new WindowContainerTransaction()
+                .setBounds(mTaskFragB.getToken(), new Rect())
+                .setWindowingMode(mTaskFragB.getToken(), WINDOWING_MODE_UNDEFINED)
+                .setAdjacentTaskFragments(mTaskFragA.getTaskFragToken(), null, null);
+        mTaskFragmentOrganizer.applyTransaction(wct);
+
+        // Ensure the Activity on primary TaskFragment is stopped and no longer focused.
+        waitAndAssertActivityState(mActivityA, STATE_STOPPED, "Activity A must be stopped");
+        assertThat(mWmState.getFocusedApp()).isNotEqualTo(mActivityA.flattenToShortString());
+        assertThat(mWmState.getFocusedWindow()).isEqualTo(mActivityB.flattenToShortString());
+    }
+
+    /**
      * Verifies an Activity below adjacent translucent TaskFragments is visible.
      */
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
index cfbf89e..87c683e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -16,6 +16,7 @@
 
 package android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.server.wm.MockImeHelper.createManagedMockImeSession;
 import static android.view.SurfaceControlViewHost.SurfacePackage;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -32,6 +33,7 @@
 
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.content.ComponentName;
@@ -66,6 +68,7 @@
 import android.widget.PopupWindow;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ActivityScenario;
 import androidx.test.filters.FlakyTest;
 import androidx.test.rule.ActivityTestRule;
 
@@ -96,6 +99,8 @@
     private final ActivityTestRule<ConfigChangeHandlingActivity> mActivityRule =
         new ActivityTestRule<>(ConfigChangeHandlingActivity.class);
 
+    private ActivityScenario<ConfigChangeHandlingActivity> mScenario;
+
     private Instrumentation mInstrumentation;
     private Activity mActivity;
     private SurfaceView mSurfaceView;
@@ -919,6 +924,19 @@
 
     @Test
     public void testEmbeddedViewReceivesInputOnBottom() throws Throwable {
+        // Close the activity that was launched by setup
+        mActivityRule.finishActivity();
+
+        // Launch activity in fullscreen windowing mode
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(mInstrumentation.getTargetContext(), ConfigChangeHandlingActivity.class);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        mScenario = ActivityScenario.launch(intent, options.toBundle());
+        mScenario.onActivity(activity -> {
+            mActivity = activity;
+        });
+
         mEmbeddedView = new Button(mActivity);
         mEmbeddedView.setOnClickListener((View v) -> {
             mClicked = true;
@@ -929,7 +947,7 @@
         waitUntilEmbeddedViewDrawn();
 
         // We should receive no input until we punch a hole
-        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mSurfaceView);
         mInstrumentation.waitForIdleSync();
         assertFalse(mClicked);
 
@@ -949,7 +967,7 @@
         // operations
         waitForTouchableRegionChanged(originalRegion);
 
-        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mSurfaceView);
         mInstrumentation.waitForIdleSync();
         assertTrue(mClicked);
     }
@@ -977,6 +995,19 @@
 
     @Test
     public void testHostInputTokenAllowsObscuredTouches() throws Throwable {
+        // Close the activity that was launched by setup
+        mActivityRule.finishActivity();
+
+        // Launch activity in fullscreen windowing mode
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(mInstrumentation.getTargetContext(), ConfigChangeHandlingActivity.class);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        mScenario = ActivityScenario.launch(intent, options.toBundle());
+        mScenario.onActivity(activity -> {
+            mActivity = activity;
+        });
+
         SurfaceControlViewHost.SurfacePackage p = null;
 
         mTestService = getService();
@@ -987,7 +1018,7 @@
             mSurfaceView.getRootSurfaceControl().setTouchableRegion(new Region());
         });
         mInstrumentation.waitForIdleSync();
-        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mSurfaceView);
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mTestService.getViewIsTouchedAndObscured());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
index 5ec5b97..d3bd635 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
@@ -26,7 +26,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
 
 import android.app.Activity;
 import android.content.ComponentName;
@@ -128,8 +127,6 @@
      */
     @Test
     public void testUntrustedModeTaskFragmentVisibility_reparentActivityInTaskFragment() {
-        // TODO(b/207070762): Remove after migration is done.
-        assumeFalse(ENABLE_SHELL_TRANSITIONS);
         final Activity translucentActivity = startActivity(TranslucentActivity.class);
 
         // Create a task fragment with activity in untrusted mode.
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java b/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
index 6b8be2d..7a4c543 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
@@ -60,7 +60,7 @@
         resetAppErrors();
     }
 
-    /** Make sure the developer options apply correctly leading to the dialog being shown. */
+    /** Make sure the developer option applies correctly leading to the dialog being shown. */
     @Test
     public void testDevSettingOverride() {
         try (SettingsSession<Integer> devDialogShow =
@@ -71,16 +71,6 @@
                      secureIntSession(Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION)) {
             // set developer setting to show dialogs anyway
             devDialogShow.set(1);
-
-            // enable only the regular option for showing the crash dialog after the first crash
-            showOnFirstCrash.set(1);
-            showOnFirstCrashDev.set(0);
-            launchActivityNoWait(Components.CRASHING_ACTIVITY);
-            findCrashDialogAndCloseApp();
-            ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
-
-            resetAppErrors();
-
             // enable only the dev option for showing the crash dialog after the first crash
             showOnFirstCrash.set(0);
             showOnFirstCrashDev.set(1);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
index e73ae81..7bfc7cd 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -307,6 +307,7 @@
                         TAPPING_TARGET_WINDOW_SIZE);
                 // Any opacity higher than this would make InputDispatcher block the touch
                 params.alpha = mInputManager.getMaximumObscuringOpacityForTouch();
+                params.setFitInsetsTypes(0);
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
@@ -361,6 +362,7 @@
                 placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
                         viewOnScreenLocation[0], viewOnScreenLocation[1],
                         TAPPING_TARGET_WINDOW_SIZE);
+                params.setFitInsetsTypes(0);
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
@@ -462,6 +464,7 @@
                 placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
                         viewOnScreenLocation[0], viewOnScreenLocation[1],
                         TAPPING_TARGET_WINDOW_SIZE);
+                params.setFitInsetsTypes(0);
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
@@ -517,6 +520,7 @@
                         viewOnScreenLocation[0], viewOnScreenLocation[1], TAPPING_TARGET_WINDOW_SIZE);
                 // Move it off the touch path (center) but still overlap with window above
                 params.y += PARTIAL_OBSCURING_WINDOW_SIZE;
+                params.setFitInsetsTypes(0);
                 intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
                 mActivity.startForegroundService(intent);
             });
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index 7969243..cfa91f5 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -258,6 +258,8 @@
     @Presubmit
     @Test
     public void testControl_andCancel() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             runOnUiThread(() -> {
                 setupAnimationListener();
@@ -278,6 +280,8 @@
 
     @Test
     public void testControl_andImmediatelyCancel() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             runOnUiThread(() -> {
                 setupAnimationListener();
@@ -295,6 +299,8 @@
     @Presubmit
     @Test
     public void testControl_immediately_show() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             setVisibilityAndWait(mType, false);
 
@@ -318,6 +324,8 @@
     @Presubmit
     @Test
     public void testControl_immediately_hide() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             setVisibilityAndWait(mType, true);
 
@@ -341,6 +349,8 @@
     @Presubmit
     @Test
     public void testControl_transition_show() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             setVisibilityAndWait(mType, false);
 
@@ -362,6 +372,8 @@
     @Presubmit
     @Test
     public void testControl_transition_hide() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             setVisibilityAndWait(mType, true);
 
@@ -383,6 +395,8 @@
     @Presubmit
     @Test
     public void testControl_transition_show_interpolator() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             mInterpolator = new DecelerateInterpolator();
             setVisibilityAndWait(mType, false);
@@ -405,6 +419,8 @@
     @Presubmit
     @Test
     public void testControl_transition_hide_interpolator() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             mInterpolator = new AccelerateInterpolator();
             setVisibilityAndWait(mType, true);
@@ -426,6 +442,8 @@
 
     @Test
     public void testControl_andLoseControl() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
         retryIfCancelled(() -> {
             mInterpolator = new AccelerateInterpolator();
             setVisibilityAndWait(mType, true);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
index 5c537e8..2fcf5ce 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
@@ -29,6 +29,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
@@ -70,6 +71,7 @@
                 WINDOWING_MODE_FULLSCREEN);
         mRootView = mActivity.getWindow().getDecorView();
         assumeTrue(hasWindowInsets(mRootView, systemBars()));
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 91916b1..4a76d92 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -116,6 +116,8 @@
 
     @Test
     public void testHide() {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -134,6 +136,8 @@
 
     @Test
     public void testShow() {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -181,6 +185,8 @@
 
     @Test
     public void testTopAppHidesStatusBarByMethod() {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -190,6 +196,8 @@
 
     @Test
     public void testTopAppHidesStatusBarByWindowFlag() {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivity(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -199,6 +207,8 @@
 
     @Test
     public void testTopAppHidesStatusBarBySystemUiFlag() {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivity(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -291,6 +301,8 @@
 
     @Test
     public void testSetSystemBarsBehavior_default() throws InterruptedException {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -317,6 +329,8 @@
 
     @Test
     public void testSetSystemBarsBehavior_showTransientBarsBySwipe() throws InterruptedException {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivity(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -398,6 +412,8 @@
 
     @Test
     public void testSystemUiVisibilityCallbackCausedByInsets() {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivity(TestActivity.class);
         final View controlTarget = activity.getWindow().getDecorView();
         final int[] targetSysUiVis = new int[1];
@@ -425,6 +441,7 @@
 
     private void testSysUiVisCallbackCausedByInsets(int insetsType, int sysUiFlag, View target,
             int[] targetSysUiVis, int[] nonTargetSysUiVis) {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
         if (target.getRootWindowInsets().isVisible(insetsType)) {
 
             // Controlled by methods
@@ -453,6 +470,11 @@
     public void testSystemUiVisibilityCallbackCausedByAppearance() {
         final TestActivity activity = startActivity(TestActivity.class);
         final View controlTarget = activity.getWindow().getDecorView();
+
+        // Assume we have at least one visible system bar.
+        assumeTrue(controlTarget.getRootWindowInsets().isVisible(statusBars()) ||
+                controlTarget.getRootWindowInsets().isVisible(navigationBars()));
+
         final int[] targetSysUiVis = new int[1];
         getInstrumentation().runOnMainSync(() -> {
             controlTarget.setOnSystemUiVisibilityChangeListener(
@@ -468,6 +490,8 @@
 
     @Test
     public void testSetSystemUiVisibilityAfterCleared_showBarsBySwipe() throws Exception {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -527,6 +551,8 @@
 
     @Test
     public void testSetSystemUiVisibilityAfterCleared_showBarsByApp() throws Exception {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
         final View rootView = activity.getWindow().getDecorView();
 
@@ -567,6 +593,8 @@
 
     @Test
     public void testHideOnCreate() throws Exception {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestHideOnCreateActivity activity =
                 startActivityInWindowingModeFullScreen(TestHideOnCreateActivity.class);
         final View rootView = activity.getWindow().getDecorView();
@@ -654,6 +682,8 @@
 
     @Test
     public void testInsetsDispatch() throws Exception {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         // Start an activity which hides system bars in fullscreen mode,
         // otherwise, it might not be able to hide system bars in other windowing modes.
         final TestHideOnCreateActivity activity = startActivityInWindowingModeFullScreen(
@@ -688,6 +718,8 @@
 
     @Test
     public void testWindowInsetsController_availableAfterAddView() throws Exception {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         final TestHideOnCreateActivity activity =
                 startActivityInWindowingModeFullScreen(TestHideOnCreateActivity.class);
         final View rootView = activity.getWindow().getDecorView();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
index 806cee5..b0c2a12 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
@@ -199,6 +199,8 @@
 
     @Test
     public void testImmersiveFullscreenHidesSystemBars() throws Throwable {
+        assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
         // Run the test twice, because the issue that shows system bars even in the immersive mode,
         // happens at the 2nd try.
         for (int i = 1; i <= 2; ++i) {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
index f895e4f..f9211904 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
@@ -240,6 +240,9 @@
         assertEmptySequence(PipActivity.class, getTransitionLog(),
                 "launchBelow");
 
+        // Set secondary split as launch root
+        mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
+
         // Launch second activity to side
         getTransitionLog().clear();
         new Launcher(SecondActivity.class)
@@ -264,6 +267,9 @@
         // Enter split screen
         moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
 
+        // Set secondary split as launch root
+        mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
+
         // Launch second activity to side
         final Activity secondActivity = new Launcher(SecondActivity.class)
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index e355f9a..d0e3834 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -2053,6 +2053,7 @@
         static final int EQUALS = 1;
         static final int GREATER_THAN = 2;
         static final int LESS_THAN = 3;
+        static final int GREATER_THAN_OR_EQUALS = 4;
 
         final T mEvent;
         final int mRule;
@@ -2076,6 +2077,9 @@
                     case LESS_THAN:
                         mMessage = event + " must be less than " + count;
                         break;
+                    case GREATER_THAN_OR_EQUALS:
+                        mMessage = event + " must be greater than (or equals to) " + count;
+                        break;
                     default:
                         mMessage = "Don't care";
                 }
@@ -2093,6 +2097,8 @@
                     return value > mCount;
                 case LESS_THAN:
                     return value < mCount;
+                case GREATER_THAN_OR_EQUALS:
+                    return value >= mCount;
                 default:
             }
             throw new RuntimeException("Unknown CountSpec rule");
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/DisplayMetricsSession.java b/tests/framework/base/windowmanager/util/src/android/server/wm/DisplayMetricsSession.java
new file mode 100644
index 0000000..86eea03
--- /dev/null
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/DisplayMetricsSession.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm;
+
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.server.wm.ActivityManagerTestBase.ReportedDisplayMetrics;
+
+import android.util.Size;
+
+/**
+ * A test helper class that queries or changes the latest DisplayMetrics override in WM by
+ * sending Shell wm commands. Provides handling for errors, orientation types and fallback
+ * behaviors.
+ * Example usage: This can be used to resize a Display in CTS test and trigger configuration
+ * changes.
+ */
+public class DisplayMetricsSession implements AutoCloseable {
+    private final ReportedDisplayMetrics mInitialDisplayMetrics;
+    private final int mDisplayId;
+
+    public DisplayMetricsSession(int displayId) {
+        mDisplayId = displayId;
+        mInitialDisplayMetrics = ReportedDisplayMetrics.getDisplayMetrics(
+                mDisplayId);
+    }
+
+    ReportedDisplayMetrics getInitialDisplayMetrics() {
+        return mInitialDisplayMetrics;
+    }
+
+    ReportedDisplayMetrics getDisplayMetrics() {
+        return ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
+    }
+
+    void changeAspectRatio(double aspectRatio, int orientation) {
+        final Size originalSize = mInitialDisplayMetrics.physicalSize;
+        final int smaller = Math.min(originalSize.getWidth(), originalSize.getHeight());
+        final int larger = (int) (smaller * aspectRatio);
+        Size overrideSize;
+        if (orientation == ORIENTATION_LANDSCAPE) {
+            overrideSize = new Size(larger, smaller);
+        } else {
+            overrideSize = new Size(smaller, larger);
+        }
+        overrideDisplayMetrics(overrideSize, mInitialDisplayMetrics.physicalDensity);
+    }
+
+    public void changeDisplayMetrics(double sizeRatio, double densityRatio) {
+        // Given a display may already have an override applied before the test is begun,
+        // resize based upon the override.
+        final Size originalSize;
+        final int density;
+        if (mInitialDisplayMetrics.overrideSize != null) {
+            originalSize = mInitialDisplayMetrics.overrideSize;
+        } else {
+            originalSize = mInitialDisplayMetrics.physicalSize;
+        }
+
+        if (mInitialDisplayMetrics.overrideDensity != null) {
+            density = mInitialDisplayMetrics.overrideDensity;
+        } else {
+            density = mInitialDisplayMetrics.physicalDensity;
+        }
+
+        final Size overrideSize = new Size((int)(originalSize.getWidth() * sizeRatio),
+                (int)(originalSize.getHeight() * sizeRatio));
+        final int overrideDensity = (int)(density * densityRatio);
+        overrideDisplayMetrics(overrideSize, overrideDensity);
+    }
+
+    void overrideDisplayMetrics(final Size size, final int density) {
+        mInitialDisplayMetrics.setDisplayMetrics(size, density);
+    }
+
+    public void restoreDisplayMetrics() {
+        mInitialDisplayMetrics.restoreDisplayMetrics();
+    }
+
+    @Override
+    public void close() {
+        restoreDisplayMetrics();
+    }
+}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
index a6d5f76..8a6a680 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
@@ -234,6 +234,13 @@
         assertEquals(message, screenOrientation, getLastOrientation());
     }
 
+    /** Waits for the configuration orientation (landscape or portrait) of the default display. */
+    public void waitForDisplayOrientation(int configOrientation) {
+        waitForWithAmState(state -> state.getDisplay(DEFAULT_DISPLAY)
+                        .mFullConfiguration.orientation == configOrientation,
+                "orientation of default display to be " + configOrientation);
+    }
+
     /**
      * Wait for the configuration orientation of the Activity.
      */
diff --git a/tests/input/src/android/input/cts/IncompleteMotionTest.kt b/tests/input/src/android/input/cts/IncompleteMotionTest.kt
index d39958e..b9c6cbb 100644
--- a/tests/input/src/android/input/cts/IncompleteMotionTest.kt
+++ b/tests/input/src/android/input/cts/IncompleteMotionTest.kt
@@ -37,6 +37,7 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.util.concurrent.CompletableFuture
 import java.util.concurrent.atomic.AtomicBoolean
 import kotlin.concurrent.thread
 
@@ -100,34 +101,42 @@
 
         // Start a valid touch stream
         sendEvent(downTime, ACTION_DOWN, x, y, true /*sync*/)
+        val resultFuture = CompletableFuture<Void>()
         // Lock up the UI thread. This ensures that the motion event that we will write will
         // not get processed by the app right away.
         activity.runOnUiThread {
             val sendMoveAndFocus = thread(start = true) {
-                sendEvent(downTime, ACTION_MOVE, x, y + 10, false /*sync*/)
-                // The MOVE event is sent async because the UI thread is blocked.
-                // Give dispatcher some time to send it to the app
-                SystemClock.sleep(700)
+                try {
+                    sendEvent(downTime, ACTION_MOVE, x, y + 10, false /*sync*/)
+                    // The MOVE event is sent async because the UI thread is blocked.
+                    // Give dispatcher some time to send it to the app
+                    SystemClock.sleep(700)
 
-                val handlerThread = HandlerThread("Receive broadcast from overlay activity")
-                handlerThread.start()
-                val looper: Looper = handlerThread.looper
-                val handler = Handler(looper)
-                val receiver = OverlayFocusedBroadcastReceiver()
-                val intentFilter = IntentFilter(OVERLAY_ACTIVITY_FOCUSED)
-                activity.registerReceiver(receiver, intentFilter, null, handler)
+                    val handlerThread = HandlerThread("Receive broadcast from overlay activity")
+                    handlerThread.start()
+                    val looper: Looper = handlerThread.looper
+                    val handler = Handler(looper)
+                    val receiver = OverlayFocusedBroadcastReceiver()
+                    val intentFilter = IntentFilter(OVERLAY_ACTIVITY_FOCUSED)
+                    activity.registerReceiver(receiver, intentFilter, null, handler)
 
-                // Now send hasFocus=false event to the app by launching a new focusable window
-                startOverlayActivity()
-                PollingCheck.waitFor { receiver.overlayActivityIsFocused() }
-                activity.unregisterReceiver(receiver)
-                handlerThread.quit()
-                // We need to ensure that the focus event has been written to the app's socket
-                // before unblocking the UI thread. Having the overlay activity receive
-                // hasFocus=true event is a good proxy for that. However, it does not guarantee
-                // that dispatcher has written the hasFocus=false event to the current activity.
-                // For safety, add another small sleep here
-                SystemClock.sleep(300)
+                    // Now send hasFocus=false event to the app by launching a new focusable window
+                    startOverlayActivity()
+                    PollingCheck.waitFor { receiver.overlayActivityIsFocused() }
+                    activity.unregisterReceiver(receiver)
+                    handlerThread.quit()
+                    // We need to ensure that the focus event has been written to the app's socket
+                    // before unblocking the UI thread. Having the overlay activity receive
+                    // hasFocus=true event is a good proxy for that. However, it does not guarantee
+                    // that dispatcher has written the hasFocus=false event to the current activity.
+                    // For safety, add another small sleep here
+                    SystemClock.sleep(300)
+                    resultFuture.complete(null)
+                } catch (e: Throwable) {
+                    // Catch potential throwable as to not crash UI thread, rethrow and validate
+                    // outside.
+                    resultFuture.completeExceptionally(e)
+                }
             }
             sendMoveAndFocus.join()
         }
@@ -139,6 +148,9 @@
         // If we wait too long here, we will cause ANR (if the platform has a bug).
         // If the MOVE event is received, however, we can stop the test.
         PollingCheck.waitFor { activity.receivedMove() }
+        // Before finishing the test, check that no exceptions occurred while running the
+        // instructions in the 'sendMoveAndFocus' thread.
+        resultFuture.get()
     }
 
     private fun sendEvent(downTime: Long, action: Int, x: Float, y: Float, sync: Boolean) {
diff --git a/tests/inputmethod/Android.bp b/tests/inputmethod/Android.bp
index 63f826f..5d00e88 100644
--- a/tests/inputmethod/Android.bp
+++ b/tests/inputmethod/Android.bp
@@ -31,7 +31,6 @@
         "androidx.test.rules",
         "androidx.test.uiautomator_uiautomator",
         "compatibility-device-util-axt",
-        "cts-wm-util",
         "cts-inputmethod-util",
         "cts-mock-a11y-ime-client",
         "ctstestrunner-axt",
@@ -41,6 +40,7 @@
         "testng",
         "kotlin-test",
         "cts-wm-util",
+        "cts_window-extensions",
     ],
     srcs: [
         "src/**/*.java",
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index 72888d7..ffd0028 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -35,8 +35,8 @@
 
         <uses-library android:name="android.test.runner"/>
 
-        <!-- TestActivity etc are merged from util/AndroidManifest.xml -->
-
+        <uses-library android:name="androidx.window.extensions"
+                      android:required="false" />
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/inputmethod/mockime/Android.bp b/tests/inputmethod/mockime/Android.bp
index 5ee0505..ba03f4f 100644
--- a/tests/inputmethod/mockime/Android.bp
+++ b/tests/inputmethod/mockime/Android.bp
@@ -30,6 +30,8 @@
         "androidx.annotation_annotation",
         "androidx.autofill_autofill",
         "compatibility-device-util-axt",
+        "cts_window_jetpack_utils",
+        "cts_window-extensions",
     ],
 }
 
diff --git a/tests/inputmethod/mockime/AndroidManifest.xml b/tests/inputmethod/mockime/AndroidManifest.xml
index e695412..5753ebb 100644
--- a/tests/inputmethod/mockime/AndroidManifest.xml
+++ b/tests/inputmethod/mockime/AndroidManifest.xml
@@ -41,6 +41,7 @@
              android:exported="true"
              android:visibleToInstantApps="true">
         </provider>
-
+        <uses-library android:name="androidx.window.extensions"
+                      android:required="false" />
     </application>
 </manifest>
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
index cb49460..cb0dd06 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
@@ -16,6 +16,9 @@
 
 package com.android.cts.mockime;
 
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Pair;
@@ -23,7 +26,13 @@
 import android.view.inputmethod.InputBinding;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.layout.DisplayFeature;
+import androidx.window.extensions.layout.FoldingFeature;
+import androidx.window.extensions.layout.WindowLayoutInfo;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Predicate;
@@ -443,4 +452,84 @@
         }
         return stream.copy();
     }
+
+    /**
+     *  A copy of {@link WindowLayoutInfo} class just for the purpose of testing with MockIME
+     *  test setup.
+     *  This is because only in this setup we will pass {@link WindowLayoutInfo} through
+     *  different processes.
+     */
+    public static class WindowLayoutInfoParcelable implements Parcelable {
+        private List<DisplayFeature> mDisplayFeatures = new ArrayList<DisplayFeature>();
+
+        public WindowLayoutInfoParcelable(WindowLayoutInfo windowLayoutInfo) {
+            this.mDisplayFeatures = windowLayoutInfo.getDisplayFeatures();
+        }
+        public WindowLayoutInfoParcelable(Parcel in) {
+            while (in.dataAvail() > 0) {
+                Rect bounds;
+                int type = -1, state = -1;
+                bounds = in.readParcelable(Rect.class.getClassLoader(), Rect.class);
+                type = in.readInt();
+                state = in.readInt();
+                mDisplayFeatures.add(new FoldingFeature(bounds, type, state));
+            }
+        }
+
+        @Override
+        public boolean equals(@Nullable Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof WindowLayoutInfoParcelable)) {
+                return false;
+            }
+
+            List<androidx.window.extensions.layout.DisplayFeature> listA =
+                    this.getDisplayFeatures();
+            List<DisplayFeature> listB = ((WindowLayoutInfoParcelable) o).getDisplayFeatures();
+            if (listA.size() != listB.size()) return false;
+            for (int i = 0; i < listA.size(); ++i) {
+                if (!listA.get(i).equals(listB.get(i))) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            // The actual implementation is FoldingFeature, DisplayFeature is an abstract class.
+            mDisplayFeatures.forEach(feature -> {
+                        dest.writeParcelable(feature.getBounds(), flags);
+                        dest.writeInt(((FoldingFeature) feature).getType());
+                        dest.writeInt(((FoldingFeature) feature).getState());
+                    }
+            );
+        }
+
+        public List<DisplayFeature> getDisplayFeatures() {
+            return mDisplayFeatures;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Parcelable.Creator<WindowLayoutInfoParcelable> CREATOR =
+                new Parcelable.Creator<WindowLayoutInfoParcelable>() {
+
+                    @Override
+                    public WindowLayoutInfoParcelable createFromParcel(Parcel in) {
+                        return new WindowLayoutInfoParcelable(in);
+                    }
+
+                    @Override
+                    public WindowLayoutInfoParcelable[] newArray(int size) {
+                        return new WindowLayoutInfoParcelable[size];
+                    }
+                };
+    }
 }
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
index cfc30ec..eea1727 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
@@ -25,6 +25,7 @@
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.window.extensions.layout.WindowLayoutInfo;
 
 import java.lang.annotation.Retention;
 
@@ -60,6 +61,8 @@
             "InlineSuggestionViewContentDesc";
     private static final String STRICT_MODE_ENABLED = "StrictModeEnabled";
     private static final String VERIFY_CONTEXT_APIS_IN_ON_CREATE = "VerifyContextApisInOnCreate";
+    private static final String WINDOW_LAYOUT_INFO_CALLBACK_ENABLED =
+            "WindowLayoutInfoCallbackEnabled";
 
     /**
      * Simulate the manifest flag enableOnBackInvokedCallback being true for the IME.
@@ -187,6 +190,10 @@
         return mBundle.getBoolean(VERIFY_CONTEXT_APIS_IN_ON_CREATE, false);
     }
 
+    public boolean isWindowLayoutInfoCallbackEnabled() {
+        return mBundle.getBoolean(WINDOW_LAYOUT_INFO_CALLBACK_ENABLED, false);
+    }
+
     public boolean isOnBackCallbackEnabled() {
         return mBundle.getBoolean(ON_BACK_CALLBACK_ENABLED, false);
     }
@@ -374,6 +381,14 @@
         }
 
         /**
+         * Sets whether to enable {@link WindowLayoutInfo} callbacks for {@link MockIme}.
+         */
+        public Builder setWindowLayoutInfoCallbackEnabled(boolean enabled) {
+            mBundle.putBoolean(WINDOW_LAYOUT_INFO_CALLBACK_ENABLED, enabled);
+            return this;
+        }
+
+        /**
          * Sets whether the IME's
          * {@link android.content.pm.ApplicationInfo#isOnBackInvokedCallbackEnabled()}
          * should be set to {@code true}.
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 528da58..faa169f 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.mockime;
 
+import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -82,6 +83,9 @@
 import androidx.autofill.inline.UiVersions;
 import androidx.autofill.inline.UiVersions.StylesBuilder;
 import androidx.autofill.inline.v1.InlineSuggestionUi;
+import androidx.window.extensions.WindowExtensions;
+import androidx.window.extensions.layout.WindowLayoutComponent;
+import androidx.window.extensions.layout.WindowLayoutInfo;
 
 import java.util.ArrayList;
 import java.util.concurrent.ExecutorService;
@@ -117,6 +121,14 @@
         return eventActionName + ".command";
     }
 
+    @Nullable
+    private final WindowExtensions mWindowExtensions = getWindowExtensions();
+    @Nullable
+    private final WindowLayoutComponent mWindowLayoutComponent =
+            mWindowExtensions != null ? mWindowExtensions.getWindowLayoutComponent() : null;
+
+    private Consumer<WindowLayoutInfo> mWindowLayoutInfoConsumer;
+
     private final HandlerThread mHandlerThread = new HandlerThread("CommandReceiver");
 
     private final Handler mMainHandler = new Handler();
@@ -692,6 +704,11 @@
             } else {
                 registerReceiver(mCommandReceiver, filter, null /* broadcastPermission */, handler);
             }
+            // If Extension components are not loaded successfully, notify Test app.
+            if (mSettings.isWindowLayoutInfoCallbackEnabled()) {
+                getTracer().onVerify("windowLayoutComponentLoaded",
+                        () -> mWindowLayoutComponent != null);
+            }
             if (mSettings.isVerifyContextApisInOnCreate()) {
                 getTracer().onVerify("isUiContext", this::verifyIsUiContext);
                 getTracer().onVerify("getDisplay", this::verifyGetDisplay);
@@ -726,6 +743,12 @@
             // in IME event.
             mLastDispatchedConfiguration.setTo(getResources().getConfiguration());
         });
+
+        if (mSettings.isWindowLayoutInfoCallbackEnabled() && mWindowLayoutComponent != null) {
+            mWindowLayoutInfoConsumer = (windowLayoutInfo) -> getTracer().getWindowLayoutInfo(
+                    windowLayoutInfo, () -> {});
+            mWindowLayoutComponent.addWindowLayoutInfoListener(this, mWindowLayoutInfoConsumer);
+        }
     }
 
     @Override
@@ -1060,6 +1083,9 @@
         getTracer().onDestroy(() -> {
             mDestroying = true;
             super.onDestroy();
+            if (mSettings.isWindowLayoutInfoCallbackEnabled() && mWindowLayoutComponent != null) {
+                mWindowLayoutComponent.removeWindowLayoutInfoListener(mWindowLayoutInfoConsumer);
+            }
             unregisterReceiver(mCommandReceiver);
             mHandlerThread.quitSafely();
         });
@@ -1202,6 +1228,8 @@
 
     @Override
     public void onConfigurationChanged(Configuration configuration) {
+        // Broadcasting configuration change is implemented at WindowProviderService level.
+        super.onConfigurationChanged(configuration);
         getTracer().onConfigurationChanged(() -> {}, configuration);
         mLastDispatchedConfiguration.setTo(configuration);
     }
@@ -1517,5 +1545,14 @@
                     mIme.mLastDispatchedConfiguration));
             recordEventInternal("onConfigurationChanged", runnable, arguments);
         }
+
+        void getWindowLayoutInfo(@NonNull WindowLayoutInfo windowLayoutInfo,
+                @NonNull Runnable runnable) {
+            final Bundle arguments = new Bundle();
+            ImeEventStreamTestUtils.WindowLayoutInfoParcelable parcel =
+                    new ImeEventStreamTestUtils.WindowLayoutInfoParcelable(windowLayoutInfo);
+            arguments.putParcelable("WindowLayoutInfo", parcel);
+            recordEventInternal("getWindowLayoutInfo", runnable, arguments);
+        }
     }
 }
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 56795ad..c4c7089 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -1496,6 +1496,11 @@
     }
 
     @NonNull
+    public ImeCommand callGetWindowLayoutInfo() {
+        return callCommandInternal("getWindowLayoutInfo", new Bundle());
+    }
+
+    @NonNull
     public ImeCommand callSetStylusHandwritingInkView() {
         return callCommandInternal("setStylusHandwritingInkView", new Bundle());
     }
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index a9cec51..594932b 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -18,6 +18,8 @@
 
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.server.wm.jetpack.utils.ExtensionUtil.EXTENSION_VERSION_2;
+import static android.server.wm.jetpack.utils.ExtensionUtil.isExtensionVersionAtLeast;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
@@ -29,6 +31,7 @@
 import static android.view.inputmethod.cts.util.TestUtils.waitOnMainUntil;
 
 import static com.android.cts.mockime.ImeEventStreamTestUtils.EventFilterMode.CHECK_EXIT_EVENT_ONLY;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.WindowLayoutInfoParcelable;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
@@ -41,6 +44,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
 import android.app.Activity;
@@ -48,10 +52,12 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.inputmethodservice.InputMethodService;
 import android.os.Bundle;
 import android.os.SystemClock;
+import android.server.wm.DisplayMetricsSession;
 import android.support.test.uiautomator.UiObject2;
 import android.text.TextUtils;
 import android.view.KeyCharacterMap;
@@ -79,7 +85,11 @@
 import androidx.test.filters.MediumTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.window.extensions.layout.DisplayFeature;
+import androidx.window.extensions.layout.WindowLayoutInfo;
 
+import com.android.compatibility.common.util.ApiTest;
+import com.android.compatibility.common.util.FeatureUtil;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.cts.mockime.ImeCommand;
 import com.android.cts.mockime.ImeEvent;
@@ -88,6 +98,7 @@
 import com.android.cts.mockime.MockImeSession;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -794,6 +805,121 @@
         }
     }
 
+    /**
+     * Starts a {@link MockImeSession} and verifies MockIme receives {@link WindowLayoutInfo}
+     * updates. Trigger Configuration changes by modifying the DisplaySession where MockIME window
+     * is located, then verify Bounds from MockIME window and {@link DisplayFeature} from
+     * WindowLayoutInfo updates observe the same changes to the hinge location.
+     * Here we use {@link WindowLayoutInfoParcelable} to pass {@link WindowLayoutInfo} values
+     * between this test process and the MockIME process.
+     */
+    @Ignore("b/264026686")
+    @Test
+    @ApiTest(apis = {
+            "androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener"})
+    public void testImeListensToWindowLayoutInfo() throws Exception {
+        assumeTrue(
+                "This test should only be run on devices with extension version that supports IME"
+                        + " as WindowLayoutInfo listener ",
+                isExtensionVersionAtLeast(EXTENSION_VERSION_2));
+
+        try (MockImeSession imeSession = MockImeSession.create(
+                InstrumentationRegistry.getInstrumentation().getContext(),
+                InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+                new ImeSettings.Builder().setWindowLayoutInfoCallbackEnabled(true))) {
+
+            final ImeEventStream stream = imeSession.openEventStream();
+            TestActivity activity = createTestActivity(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+
+            assertTrue(expectEvent(stream, verificationMatcher("windowLayoutComponentLoaded"),
+                    CHECK_EXIT_EVENT_ONLY, TIMEOUT).getReturnBooleanValue());
+
+            try (DisplayMetricsSession displaySession = new DisplayMetricsSession(
+                    activity.getDisplay().getDisplayId())) {
+
+                final double displayResizeRatio = 0.8;
+
+                // MockIME has registered addWindowLayoutInfo, it should be emitting the
+                // current location of hinge now.
+                WindowLayoutInfoParcelable windowLayoutInit = verifyReceivedWindowLayout(
+                        stream);
+                // Skip the test if the device doesn't support hinges.
+                assertNotNull(windowLayoutInit);
+                assertNotNull(windowLayoutInit.getDisplayFeatures());
+                assumeFalse(windowLayoutInit.getDisplayFeatures().isEmpty());
+
+                final Rect windowLayoutInitBounds = windowLayoutInit.getDisplayFeatures().get(0)
+                        .getBounds();
+
+                expectEvent(stream, event -> "onStartInput".equals(event.getEventName()),
+                        TIMEOUT);
+                expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()),
+                        TIMEOUT);
+
+                // After IME is shown, get the bounds of IME.
+                final Rect imeBoundsInit = expectCommand(stream,
+                        imeSession.callGetCurrentWindowMetricsBounds(), TIMEOUT)
+                        .getReturnParcelableValue();
+                // Contain first part of the test in a try-block so that the display session
+                // could be restored for the remaining testsuite even if something fails.
+                try {
+                    // Shrink the entire display 20% smaller.
+                    displaySession.changeDisplayMetrics(displayResizeRatio /* sizeRatio */,
+                            1.0 /* densityRatio */);
+
+                    // onConfigurationChanged on WM side triggers a new calculation for
+                    // hinge location.
+                    WindowLayoutInfoParcelable windowLayoutSizeChange = verifyReceivedWindowLayout(
+                            stream);
+
+                    // Expect to receive same number of display features in WindowLayoutInfo.
+                    assertEquals(windowLayoutInit.getDisplayFeatures().size(),
+                            windowLayoutSizeChange.getDisplayFeatures().size());
+
+                    Rect windowLayoutSizeChangeBounds =
+                            windowLayoutSizeChange.getDisplayFeatures().get(
+                                    0).getBounds();
+                    Rect imeBoundsShrunk = expectCommand(stream,
+                            imeSession.callGetCurrentWindowMetricsBounds(), TIMEOUT)
+                            .getReturnParcelableValue();
+
+                    final Boolean widthsChangedInSameRatio =
+                            (windowLayoutInitBounds.width() * displayResizeRatio
+                                    == windowLayoutSizeChangeBounds.width() && (
+                                    imeBoundsInit.width() * displayResizeRatio
+                                            == imeBoundsShrunk.width()));
+                    final Boolean heightsChangedInSameRatio =
+                            (windowLayoutInitBounds.height() * displayResizeRatio
+                                    == windowLayoutSizeChangeBounds.height() && (
+                                    imeBoundsInit.height() * displayResizeRatio
+                                            == imeBoundsShrunk.height()));
+                    // Expect the hinge dimension to shrink in exactly one direction, the actual
+                    // dimension depends on device implementation. Observe hinge dimensions from
+                    // IME configuration bounds and from WindowLayoutInfo.
+                    assertTrue(widthsChangedInSameRatio || heightsChangedInSameRatio);
+                } finally {
+                    // Restore Display to original size.
+                    displaySession.restoreDisplayMetrics();
+                    // Advance stream to ignore unrelated side effect from WM configuration changes.
+                    // TODO(b/257990185): Add filtering in WM Extensions to remove this.
+                    stream.skipAll();
+
+                    WindowLayoutInfoParcelable windowLayoutRestored = verifyReceivedWindowLayout(
+                            stream);
+
+                    assertEquals(windowLayoutInitBounds,
+                            windowLayoutRestored.getDisplayFeatures().get(0).getBounds());
+
+                    final Rect imeBoundsRestored = expectCommand(stream,
+                            imeSession.callGetCurrentWindowMetricsBounds(), TIMEOUT)
+                            .getReturnParcelableValue();
+
+                    assertEquals(imeBoundsRestored, imeBoundsInit);
+                }
+            }
+        }
+    }
+
     /** Verify if {@link InputMethodService#isUiContext()} returns {@code true}. */
     @Test
     public void testIsUiContext() throws Exception {
@@ -1131,4 +1257,13 @@
             return this;
         }
     }
+
+    private static WindowLayoutInfoParcelable verifyReceivedWindowLayout(ImeEventStream stream)
+            throws TimeoutException {
+        WindowLayoutInfoParcelable received = expectEvent(stream,
+                event -> "getWindowLayoutInfo".equals(event.getEventName()),
+                TIMEOUT).getArguments().getParcelable("WindowLayoutInfo",
+                WindowLayoutInfoParcelable.class);
+        return received;
+    }
 }
diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml
index 09de676..faf4547 100644
--- a/tests/media/AndroidTest.xml
+++ b/tests/media/AndroidTest.xml
@@ -34,7 +34,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaV2TestCases-3.2" />
+        <option name="media-folder-name" value="CtsMediaV2TestCases-3.4" />
         <option name="dynamic-config-module" value="CtsMediaV2TestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/media/DynamicConfig.xml b/tests/media/DynamicConfig.xml
index 486e537..6097fb7 100644
--- a/tests/media/DynamicConfig.xml
+++ b/tests/media/DynamicConfig.xml
@@ -1,5 +1,5 @@
 <dynamicConfig>
     <entry key="media_files_url">
-      <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-3.2.zip</value>
+      <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-3.4.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/media/README.md b/tests/media/README.md
index 7880319..b8ed5b9 100644
--- a/tests/media/README.md
+++ b/tests/media/README.md
@@ -3,7 +3,7 @@
 
 The aim of these tests is not solely to verify the CDD requirements but also to test components, their plugins and their interactions with media framework.
 
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-3.2.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-3.4.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
 
 All Big Buck Bunny(bbb) test vectors are of 8-bit format. They are downloaded from [link](https://peach.blender.org/download/) and resampled according to the test requirements.
 All Cosmos Laundromat(cosmat) test vectors are of 10-bit format. They are downloaded from [link](https://media.xiph.org/) and resampled according to the test requirements.
diff --git a/tests/media/common/src/android/mediav2/common/cts/BitStreamUtils.java b/tests/media/common/src/android/mediav2/common/cts/BitStreamUtils.java
index 616eaa4..66ed70f 100644
--- a/tests/media/common/src/android/mediav2/common/cts/BitStreamUtils.java
+++ b/tests/media/common/src/android/mediav2/common/cts/BitStreamUtils.java
@@ -16,6 +16,7 @@
 
 package android.mediav2.common.cts;
 
+import static android.media.MediaCodecInfo.CodecProfileLevel.*;
 import static android.media.MediaFormat.PICTURE_TYPE_B;
 import static android.media.MediaFormat.PICTURE_TYPE_I;
 import static android.media.MediaFormat.PICTURE_TYPE_P;
@@ -23,11 +24,13 @@
 
 import android.media.MediaCodec;
 import android.media.MediaFormat;
+import android.util.Pair;
 
 import org.junit.Assert;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.HashMap;
 
 /**
  * This class contains utility functions that parse compressed bitstream and returns metadata
@@ -38,9 +41,15 @@
  * Currently this class hosts utils that can,
  * <ul>
  *     <li>Return frame type of the access units of avc, hevc, av1.</li>
+ *     <li>Return profile/level information of avc, hevc, av1, vp9, mpeg4, h263, aac</li>
  * </ul>
  */
 public class BitStreamUtils {
+    public static int getHashMapVal(HashMap<Integer, Integer> obj, int key) {
+        Integer val = obj.get(key);
+        return val == null ? -1 : val;
+    }
+
     static class ParsableBitArray {
         protected final byte[] mData;
         protected final int mOffset;
@@ -71,9 +80,9 @@
         }
 
         public int readBits(int numBits) {
-            if (numBits > 31) {
-                throw new IllegalArgumentException(
-                        "left shift overflow exception, reading too many bits at one go");
+            if (numBits > 32) {
+                throw new IllegalArgumentException("readBits Exception: maximum storage space of "
+                        + "return value of readBits : 32, less than bits to read : " + numBits);
             }
             int value = 0;
             for (int i = 0; i < numBits; i++) {
@@ -84,9 +93,9 @@
         }
 
         public long readBitsLong(int numBits) {
-            if (numBits > 63) {
-                throw new IllegalArgumentException(
-                        "left shift overflow exception, reading too many bits at one go");
+            if (numBits > 64) {
+                throw new IllegalArgumentException("readBitsLong Exception: maximum storage space "
+                        + "of return value of readBits : 64, less than bits to read : " + numBits);
             }
             long value = 0;
             for (int i = 0; i < numBits; i++) {
@@ -168,10 +177,131 @@
         }
 
         public abstract int getFrameType();
+
+        public abstract Pair<Integer, Integer> getProfileLevel(boolean isCsd);
+
+        // .first = profile, .second = level
+        public Pair<Integer, Integer> plToPair(int profile, int level) {
+            return Pair.create(profile, level);
+        }
+    }
+
+    static class Mpeg4Parser extends ParserBase {
+        @Override
+        public int getFrameType() {
+            return PICTURE_TYPE_UNKNOWN;
+        }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) {
+            ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit);
+            Assert.assertEquals(0, bitArray.readBits(8));
+            Assert.assertEquals(0, bitArray.readBits(8));
+            Assert.assertEquals(1, bitArray.readBits(8));
+            Assert.assertEquals(0xb0, bitArray.readBits(8));
+            int profileLevel = bitArray.readBits(8);
+            switch (profileLevel) {
+                case 0x08: return plToPair(MPEG4ProfileSimple, MPEG4Level0);
+                case 0x01: return plToPair(MPEG4ProfileSimple, MPEG4Level1);
+                case 0x02: return plToPair(MPEG4ProfileSimple, MPEG4Level2);
+                case 0x03: return plToPair(MPEG4ProfileSimple, MPEG4Level3);
+                case 0xf0: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level0);
+                case 0xf1: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level1);
+                case 0xf2: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level2);
+                case 0xf3: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level3);
+                case 0xf7: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level3b);
+                case 0xf4: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level4);
+                case 0xf5: return plToPair(MPEG4ProfileAdvancedSimple, MPEG4Level5);
+                default: return null;
+            }
+        }
+    }
+
+    static class H263Parser extends ParserBase {
+        @Override
+        public int getFrameType() {
+            return PICTURE_TYPE_UNKNOWN;
+        }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) {
+            ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit);
+            Assert.assertEquals("bad psc", 0x20, bitArray.readBits(22));
+            bitArray.readBits(8); // tr
+            Assert.assertEquals(1, bitArray.readBits(1));
+            Assert.assertEquals(0, bitArray.readBits(1));
+            bitArray.readBits(1);  // split screen
+            bitArray.readBits(1);  // camera indicator
+            bitArray.readBits(1);  // freeze indicator
+            int sourceFormat = bitArray.readBits(3);
+            int picType;
+            int umv = 0, sac = 0, ap = 0, pb = 0;
+            int aic = 0, df = 0, ss = 0, rps = 0, isd = 0, aiv = 0, mq = 0;
+            int rpr = 0, rru = 0;
+            if (sourceFormat == 7) {
+                int ufep = bitArray.readBits(3);
+                if (ufep == 1) {
+                    sourceFormat = bitArray.readBits(3);
+                    bitArray.readBits(1); // custom pcf
+                    umv = bitArray.readBits(1);
+                    sac = bitArray.readBits(1);
+                    ap = bitArray.readBits(1);
+                    aic = bitArray.readBits(1);
+                    df = bitArray.readBits(1);
+                    ss = bitArray.readBits(1);
+                    rps = bitArray.readBits(1);
+                    isd = bitArray.readBits(1);
+                    aiv = bitArray.readBits(1);
+                    mq = bitArray.readBits(1);
+                    Assert.assertEquals(1, bitArray.readBits(1));
+                    Assert.assertEquals(0, bitArray.readBits(3));
+                }
+                picType = bitArray.readBits(3);
+                rpr = bitArray.readBits(1);
+                rru = bitArray.readBits(1);
+                bitArray.readBits(1);  // rtype
+                Assert.assertEquals(0, bitArray.readBits(1));  // reserved
+                Assert.assertEquals(0, bitArray.readBits(1));  // reserved
+                Assert.assertEquals(1, bitArray.readBits(1));  // start code emulation
+            } else {
+                picType = bitArray.readBits(1);
+                umv = bitArray.readBits(1);
+                sac = bitArray.readBits(1);
+                ap = bitArray.readBits(1);
+                pb = bitArray.readBits(1);
+            }
+            int profile = H263ProfileBaseline;
+            if (ap == 1) profile = H263ProfileBackwardCompatible;
+            if (aic == 1 && df == 1 && ss == 1 && mq == 1) profile = H263ProfileISWV2;
+            return plToPair(profile, -1);
+        }
     }
 
     static class AvcParser extends ParserBase {
         private static final int NO_NAL_UNIT_FOUND = -1;
+        private static final HashMap<Integer, Integer> LEVEL_MAP = new HashMap<>() {
+            {
+                put(10, AVCLevel1);
+                put(11, AVCLevel11);
+                put(12, AVCLevel12);
+                put(13, AVCLevel13);
+                put(20, AVCLevel2);
+                put(21, AVCLevel21);
+                put(22, AVCLevel22);
+                put(30, AVCLevel3);
+                put(31, AVCLevel31);
+                put(32, AVCLevel32);
+                put(40, AVCLevel4);
+                put(41, AVCLevel41);
+                put(42, AVCLevel42);
+                put(50, AVCLevel5);
+                put(51, AVCLevel51);
+                put(52, AVCLevel52);
+                put(60, AVCLevel6);
+                put(61, AVCLevel61);
+                put(62, AVCLevel62);
+            }
+        };
 
         private int getNalUnitStartOffset(byte[] dataArray, int start, int limit) {
             for (int pos = start; pos + 3 < limit; pos++) {
@@ -198,7 +328,8 @@
                 int nalUnitType = getNalUnitType(mData, offset);
                 if (nalUnitType == 1 || nalUnitType == 2 || nalUnitType == 5) {  // coded slice
                     NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit);
-                    bitArray.readBits(8); // forbidden zero bit + nal_ref_idc + nal_unit_type
+                    Assert.assertEquals(0, bitArray.readBits(1)); // forbidden zero bit
+                    bitArray.readBits(7); // nal_ref_idc + nal_unit_type
                     bitArray.readUEV(); // first_mb_in_slice
                     int sliceType = bitArray.readUEV();
                     if (sliceType % 5 == 0) {
@@ -215,6 +346,77 @@
             }
             return PICTURE_TYPE_UNKNOWN;
         }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) {
+            for (int pos = mOffset; pos < mLimit; ) {
+                int offset = getNalUnitStartOffset(mData, pos, mLimit);
+                if (offset == NO_NAL_UNIT_FOUND) return null;
+                if (getNalUnitType(mData, offset) == 7) { // seq_parameter_set_rbsp
+                    NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit);
+                    Assert.assertEquals(0, bitArray.readBits(1)); // forbidden zero bit
+                    bitArray.readBits(7); // nal_ref_idc + nal_unit_type
+                    int profileIdc = bitArray.readBits(8);
+                    int constraintSet0Flag = bitArray.readBits(1);
+                    int constraintSet1Flag = bitArray.readBits(1);
+                    int constraintSet2Flag = bitArray.readBits(1);
+                    int constraintSet3Flag = bitArray.readBits(1);
+                    int constraintSet4Flag = bitArray.readBits(1);
+                    int constraintSet5Flag = bitArray.readBits(1);
+                    Assert.assertEquals(0, bitArray.readBits(2)); // reserved zero 2 bits
+                    int levelIdc = bitArray.readBits(8);
+
+                    int profile = -1;
+                    if (constraintSet0Flag == 1 || profileIdc == 66) {
+                        profile = constraintSet1Flag == 1 ? AVCProfileConstrainedBaseline :
+                                AVCProfileBaseline;
+                    } else if (constraintSet1Flag == 1 || profileIdc == 77) {
+                        profile = AVCProfileMain;
+                    } else if (constraintSet2Flag == 1 || profileIdc == 88) {
+                        profile = AVCProfileExtended;
+                    } else if (profileIdc == 100) {
+                        profile = (constraintSet4Flag == 1 && constraintSet5Flag == 1)
+                                ? AVCProfileConstrainedHigh : AVCProfileHigh;
+                    } else if (profileIdc == 110) {
+                        profile = AVCProfileHigh10;
+                    } else if (profileIdc == 122) {
+                        profile = AVCProfileHigh422;
+                    } else if (profileIdc == 244) {
+                        profile = AVCProfileHigh444;
+                    }
+
+                    // In bitstreams conforming to the Baseline, Constrained Baseline, Main, or
+                    // Extended profiles :
+                    // - If level_idc is equal to 11 and constraint_set3_flag is equal to 1, the
+                    // indicated level is level 1b.
+                    // - Otherwise (level_idc is not equal to 11 or constraint_set3_flag is not
+                    // equal to 1), level_idc is equal to a value of ten times the level number
+                    // (of the indicated level) specified in Table A-1.
+                    int level;
+                    if ((levelIdc == 11) && (profile == AVCProfileBaseline
+                            || profile == AVCProfileConstrainedBaseline || profile == AVCProfileMain
+                            || profile == AVCProfileExtended)) {
+                        level = constraintSet3Flag == 1 ? AVCLevel1b : AVCLevel11;
+                    } else if ((levelIdc == 9) && (profile == AVCProfileHigh
+                            || profile == AVCProfileHigh10 || profile == AVCProfileHigh422
+                            || profile == AVCProfileHigh444)) {
+                        // In bitstreams conforming to the High, High 10, High 4:2:2, High 4:4:4
+                        // Predictive, High 10 Intra, High 4:2:2 Intra, High 4:4:4 Intra, or
+                        // CAVLC 4:4:4 Intra profiles,
+                        // - If level_idc is equal to 9, the indicated level is level 1b.
+                        // - Otherwise (level_idc is not equal to 9), level_idc is equal to a
+                        // value of ten times the level number (of the indicated level) specified
+                        // in Table A-1
+                        level = AVCLevel1b;
+                    } else {
+                        level = getHashMapVal(LEVEL_MAP, levelIdc);
+                    }
+                    return plToPair(profile, level);
+                }
+                pos = offset;
+            }
+            return null;
+        }
     }
 
     static class HevcParser extends ParserBase {
@@ -223,6 +425,35 @@
         private static final int RASL_R = 9;
         private static final int BLA_W_LP = 16;
         private static final int RSV_IRAP_VCL23 = 23;
+        private static final HashMap<Integer, Integer> LEVEL_MAP_MAIN_TIER = new HashMap<>() {
+            {
+                put(30, HEVCMainTierLevel1);
+                put(60, HEVCMainTierLevel2);
+                put(63, HEVCMainTierLevel21);
+                put(90, HEVCMainTierLevel3);
+                put(93, HEVCMainTierLevel31);
+                put(120, HEVCMainTierLevel4);
+                put(123, HEVCMainTierLevel41);
+                put(150, HEVCMainTierLevel5);
+                put(153, HEVCMainTierLevel51);
+                put(156, HEVCMainTierLevel52);
+                put(180, HEVCMainTierLevel6);
+                put(183, HEVCMainTierLevel61);
+                put(186, HEVCMainTierLevel62);
+            }
+        };
+        private static final HashMap<Integer, Integer> LEVEL_MAP_HIGH_TIER = new HashMap<>() {
+            {
+                put(120, HEVCHighTierLevel4);
+                put(123, HEVCHighTierLevel41);
+                put(150, HEVCHighTierLevel5);
+                put(153, HEVCHighTierLevel51);
+                put(156, HEVCHighTierLevel52);
+                put(180, HEVCHighTierLevel6);
+                put(183, HEVCHighTierLevel61);
+                put(186, HEVCHighTierLevel62);
+            }
+        };
 
         private int getNalUnitStartOffset(byte[] dataArray, int start, int limit) {
             for (int pos = start; pos + 3 < limit; pos++) {
@@ -275,6 +506,120 @@
             }
             return PICTURE_TYPE_UNKNOWN;
         }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) {
+            for (int pos = mOffset; pos < mLimit; ) {
+                int offset = getNalUnitStartOffset(mData, pos, mLimit);
+                if (offset == NO_NAL_UNIT_FOUND) return null;
+                if (getNalUnitType(mData, offset) == 33) { // sps_nut
+                    NalParsableBitArray bitArray = new NalParsableBitArray(mData, offset, mLimit);
+                    bitArray.readBits(16); // nal unit header
+                    bitArray.readBits(4); // sps video parameter set id
+                    bitArray.readBits(3); // sps_max_sub_layers_minus1
+                    bitArray.readBits(1); // sps temporal id nesting flag
+                    // profile_tier_level
+                    bitArray.readBits(2); // generalProfileSpace
+                    int generalTierFlag = bitArray.readBits(1);
+                    int generalProfileIdc = bitArray.readBits(5);
+                    int[] generalProfileCompatibility = new int[32];
+                    for (int j = 0; j < generalProfileCompatibility.length; j++) {
+                        generalProfileCompatibility[j] = bitArray.readBits(1);
+                    }
+                    bitArray.readBits(1); // general progressive source flag
+                    bitArray.readBits(1); // general interlaced source flag
+                    bitArray.readBits(1); // general non packed constraint flag
+                    bitArray.readBits(1); // general frame only constraint flag
+
+                    // interpretation of next 44 bits is dependent on generalProfileIdc and
+                    // generalProfileCompatibility; but we do not use them in this validation
+                    // process, so we're skipping over them.
+                    bitArray.readBitsLong(44);
+                    int generalLevelIdc = bitArray.readBits(8);
+
+                    int profile = -1;
+                    if (generalProfileIdc == 1 || generalProfileCompatibility[1] == 1) {
+                        profile = HEVCProfileMain;
+                    } else if (generalProfileIdc == 2 || generalProfileCompatibility[2] == 1) {
+                        profile = HEVCProfileMain10;
+                    } else if (generalProfileIdc == 3 || generalProfileCompatibility[3] == 1) {
+                        profile = HEVCProfileMainStill;
+                    }
+
+                    return plToPair(profile, getHashMapVal(
+                            generalTierFlag == 0 ? LEVEL_MAP_MAIN_TIER : LEVEL_MAP_HIGH_TIER,
+                            generalLevelIdc));
+                }
+                pos = offset;
+            }
+            return null;
+        }
+    }
+
+    static class Vp9Parser extends ParserBase {
+        private static final HashMap<Integer, Integer> PROFILE_MAP = new HashMap<>() {
+            {
+                put(0, VP9Profile0);
+                put(1, VP9Profile1);
+                put(2, VP9Profile2);
+                put(3, VP9Profile3);
+            }
+        };
+        private static final HashMap<Integer, Integer> LEVEL_MAP = new HashMap<>() {
+            {
+                put(10, VP9Level1);
+                put(11, VP9Level11);
+                put(20, VP9Level2);
+                put(21, VP9Level21);
+                put(30, VP9Level3);
+                put(31, VP9Level31);
+                put(40, VP9Level4);
+                put(41, VP9Level41);
+                put(50, VP9Level5);
+                put(51, VP9Level51);
+                put(60, VP9Level6);
+                put(61, VP9Level61);
+                put(62, VP9Level62);
+            }
+        };
+
+        private Pair<Integer, Integer> getProfileLevelFromCSD() { // parse vp9 codecprivate
+            int profile = -1, level = -1;
+            for (int pos = mOffset; pos < mLimit; ) {
+                ParsableBitArray bitArray = new ParsableBitArray(mData, pos + mOffset, mLimit);
+                int id = bitArray.readBits(8);
+                int len = bitArray.readBits(8);
+                pos += 2;
+                int val = bitArray.readBits(len * 8);
+                pos += len;
+                if (id == 1 || id == 2) {
+                    Assert.assertEquals(1, len);
+                    if (id == 1) profile = val;
+                    else level = val;
+                }
+                if (profile != -1 && level != -1) break;
+            }
+            return plToPair(getHashMapVal(PROFILE_MAP, profile), getHashMapVal(LEVEL_MAP, level));
+        }
+
+        private Pair<Integer, Integer> getProfileFromFrameHeader() { // parse uncompressed header
+            ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit);
+            bitArray.readBits(2); // frame marker
+            int profileLBit = bitArray.readBits(1);
+            int profileHBit = bitArray.readBits(1);
+            int profile = profileHBit << 1 + profileLBit;
+            return plToPair(getHashMapVal(PROFILE_MAP, profile), -1);
+        }
+
+        @Override
+        public int getFrameType() {
+            return PICTURE_TYPE_UNKNOWN;
+        }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(boolean isCsd) {
+            return isCsd ? getProfileLevelFromCSD() : getProfileFromFrameHeader();
+        }
     }
 
     static class Av1Parser extends ParserBase {
@@ -578,6 +923,48 @@
             return frameHeader;
         }
 
+        // parse av1 codec configuration record
+        private Pair<Integer, Integer> getProfileLevelFromCSD() {
+            int profile = -1;
+            ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit);
+            Assert.assertEquals(1, bitArray.readBits(1));  // marker
+            Assert.assertEquals(1, bitArray.readBits(7));  // version
+            int seqProfile = bitArray.readBits(3);
+            int seqLevelIdx0 = bitArray.readBits(5);
+            bitArray.readBits(1);  // seqTier0
+            int highBitDepth = bitArray.readBits(1);
+            bitArray.readBits(1);  // is input 12 bit;
+            if (seqProfile == 0) {
+                profile = highBitDepth == 0 ? AV1ProfileMain8 : AV1ProfileMain10;
+            }
+
+            int level = AV1Level2 << seqLevelIdx0;
+            return plToPair(profile, level);
+        }
+
+        // parse av1 sequence header
+        private Pair<Integer, Integer> getProfileLevelFromSeqHeader() {
+            for (int pos = mOffset; pos < mLimit; ) {
+                ObuInfo obuDetails = parseObuHeader(mData, pos, mLimit);
+                ObuParsableBitArray bitArray =
+                        new ObuParsableBitArray(mData, pos + obuDetails.getObuDataOffset(),
+                                pos + obuDetails.getTotalObuSize());
+                if (obuDetails.mObuType == OBU_SEQUENCE_HEADER) {
+                    int profile = -1;
+                    parseSequenceHeader(bitArray);
+                    if (mSeqHeader.seqProfile == 0) {
+                        profile = mSeqHeader.enableHighBitDepth == 0 ? AV1ProfileMain8 :
+                                AV1ProfileMain10;
+                    }
+
+                    int level = AV1Level2 << mSeqHeader.seqLevelIdx[0];
+                    return plToPair(profile, level);
+                }
+                pos += obuDetails.getTotalObuSize();
+            }
+            return null;
+        }
+
         @Override
         public int getFrameType() {
             ArrayList<FrameHeaderObu> headers = new ArrayList();
@@ -609,26 +996,68 @@
             }
             return PICTURE_TYPE_UNKNOWN;
         }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(boolean isCsd) {
+            return isCsd ? getProfileLevelFromCSD() : getProfileLevelFromSeqHeader();
+        }
+    }
+
+    static class AacParser extends ParserBase {
+        @Override
+        public int getFrameType() {
+            return PICTURE_TYPE_UNKNOWN;
+        }
+
+        @Override
+        public Pair<Integer, Integer> getProfileLevel(@SuppressWarnings("unused") boolean isCsd) {
+            // parse AudioSpecificConfig() of ISO 14496 Part 3
+            ParsableBitArray bitArray = new ParsableBitArray(mData, mOffset, mLimit);
+            int audioObjectType = bitArray.readBits(5);
+            if (audioObjectType == 31) {
+                audioObjectType = 32 + bitArray.readBits(6); // audio object type ext
+            }
+            return plToPair(audioObjectType, -1);
+        }
     }
 
     public static ParserBase getParserObject(String mediaType) {
         switch (mediaType) {
+            case MediaFormat.MIMETYPE_VIDEO_MPEG4:
+                return new Mpeg4Parser();
+            case MediaFormat.MIMETYPE_VIDEO_H263:
+                return new H263Parser();
             case MediaFormat.MIMETYPE_VIDEO_AVC:
                 return new AvcParser();
             case MediaFormat.MIMETYPE_VIDEO_HEVC:
                 return new HevcParser();
             case MediaFormat.MIMETYPE_VIDEO_AV1:
                 return new Av1Parser();
+            case MediaFormat.MIMETYPE_VIDEO_VP9:
+                return new Vp9Parser();
+            case MediaFormat.MIMETYPE_AUDIO_AAC:
+                return new AacParser();
         }
         return null;
     }
 
     public static int getFrameTypeFromBitStream(ByteBuffer buf, MediaCodec.BufferInfo info,
             ParserBase o) {
+        if (o == null) return PICTURE_TYPE_UNKNOWN;
         byte[] dataArray = new byte[info.size];
         buf.position(info.offset);
         buf.get(dataArray);
         o.set(dataArray, 0, info.size);
         return o.getFrameType();
     }
+
+    public static Pair<Integer, Integer> getProfileLevelFromBitStream(ByteBuffer buf,
+            MediaCodec.BufferInfo info, ParserBase o) {
+        if (o == null) return null;
+        byte[] dataArray = new byte[info.size];
+        buf.position(info.offset);
+        buf.get(dataArray);
+        o.set(dataArray, 0, info.size);
+        return o.getProfileLevel((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0);
+    }
 }
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
index 5da75fb..a600773 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
@@ -315,12 +315,23 @@
                 + mTestConfig, mIsAudio || mIsVideo);
     }
 
+    public void deleteMuxedFile() {
+        if (mMuxedOutputFile != null) {
+            File file = new File(mMuxedOutputFile);
+            if (file.exists()) {
+                assertTrue("unable to delete file " + mMuxedOutputFile, file.delete());
+            }
+            mMuxedOutputFile = null;
+        }
+    }
+
     @After
     public void tearDown() {
         if (mMuxer != null) {
             mMuxer.release();
             mMuxer = null;
         }
+        deleteMuxedFile();
     }
 
     @Override
@@ -591,6 +602,14 @@
         mMuxOutput = false;
     }
 
+    public void setLoopBack(boolean loopBack) {
+        mIsLoopBack = loopBack;
+    }
+
+    public String getMuxedOutputFilePath() {
+        return mMuxedOutputFile;
+    }
+
     void validateTestState() {
         super.validateTestState();
         if ((mIsAudio || (mIsVideo && mActiveEncCfg.mMaxBFrames == 0))
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
index 0735f11..2736823 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
@@ -704,6 +704,9 @@
                 // sec 2.3.2
                 list.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
                 list.add(MediaFormat.MIMETYPE_VIDEO_MPEG2);
+                if (IS_AT_LEAST_U) {
+                    list.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+                }
             }
         } else {
             if (MediaUtils.hasMicrophone() && needAudio) {
@@ -998,6 +1001,10 @@
         return mIsCodecInAsyncMode ? mAsyncHandle.getOutputFormat() : mOutFormat;
     }
 
+    public int getOutputCount() {
+        return mOutputCount;
+    }
+
     protected void flushCodec() {
         mCodec.flush();
         // TODO(b/147576107): is it ok to clearQueues right away or wait for some signal
diff --git a/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java b/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java
index c1192b2..515e978 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java
@@ -48,49 +48,54 @@
         DecodeStreamToYuv ref = new DecodeStreamToYuv(refMediaType, refFile);
         RawResource refYuv = ref.getDecodedYuv();
         mTmpFiles.add(refYuv.mFileName);
-        setUp(refYuv, testMediaType, testFile, allowRefResize, allowRefLoopBack);
+
+        DecodeStreamToYuv test = new DecodeStreamToYuv(testMediaType, testFile);
+        RawResource testYuv = test.getDecodedYuv();
+        mTmpFiles.add(testYuv.mFileName);
+
+        init(refYuv, testYuv, allowRefResize, allowRefLoopBack);
     }
 
-    public CompareStreams(RawResource ref, String testMediaType, String testFile,
-            boolean allowRefResize, boolean allowRefLoopBack)
-            throws IOException, InterruptedException {
-        setUp(ref, testMediaType, testFile, allowRefResize, allowRefLoopBack);
-    }
-
-    private void setUp(RawResource ref, String testMediaType, String testFile,
+    public CompareStreams(RawResource refYuv, String testMediaType, String testFile,
             boolean allowRefResize, boolean allowRefLoopBack)
             throws IOException, InterruptedException {
         DecodeStreamToYuv test = new DecodeStreamToYuv(testMediaType, testFile);
         RawResource testYuv = test.getDecodedYuv();
         mTmpFiles.add(testYuv.mFileName);
-        if (ref.mBytesPerSample != testYuv.mBytesPerSample) {
+
+        init(refYuv, testYuv, allowRefResize, allowRefLoopBack);
+    }
+
+    private void init(RawResource refYuv, RawResource testYuv, boolean allowRefResize,
+            boolean allowRefLoopBack) throws IOException {
+        if (refYuv.mBytesPerSample != testYuv.mBytesPerSample) {
             String msg = String.format(
                     "Reference file bytesPerSample and Test file bytesPerSample are not same. "
                             + "Reference bytesPerSample : %d, Test bytesPerSample : %d",
-                    ref.mBytesPerSample, testYuv.mBytesPerSample);
+                    refYuv.mBytesPerSample, testYuv.mBytesPerSample);
             cleanUp();
             throw new IllegalArgumentException(msg);
         }
-        RawResource refYuv;
-        if (ref.mHeight == testYuv.mHeight && ref.mWidth == testYuv.mWidth) {
-            refYuv = ref;
+        RawResource refYuvResized;
+        if (refYuv.mHeight == testYuv.mHeight && refYuv.mWidth == testYuv.mWidth) {
+            refYuvResized = refYuv;
         } else {
             if (allowRefResize) {
-                refYuv = readAndResizeInputRawYUV(ref, testYuv.mWidth, testYuv.mHeight,
+                refYuvResized = readAndResizeInputRawYUV(refYuv, testYuv.mWidth, testYuv.mHeight,
                         testYuv.mBytesPerSample);
-                mTmpFiles.add(refYuv.mFileName);
+                mTmpFiles.add(refYuvResized.mFileName);
             } else {
                 String msg = String.format(
                         "Reference file attributes and Test file attributes are not same. "
                                 + "Reference width : %d, height : %d, bytesPerSample : %d, Test "
                                 + "width : %d, height : %d, bytesPerSample : %d",
-                        ref.mWidth, ref.mHeight, ref.mBytesPerSample, testYuv.mWidth,
+                        refYuv.mWidth, refYuv.mHeight, refYuv.mBytesPerSample, testYuv.mWidth,
                         testYuv.mHeight, testYuv.mBytesPerSample);
                 cleanUp();
                 throw new IllegalArgumentException(msg);
             }
         }
-        mStatistics = new VideoErrorManager(refYuv, testYuv, allowRefLoopBack);
+        mStatistics = new VideoErrorManager(refYuvResized, testYuv, allowRefLoopBack);
     }
 
     private RawResource readAndResizeInputRawYUV(RawResource res, int width, int height,
diff --git a/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java b/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java
index 4f1981c..0a50624 100644
--- a/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java
+++ b/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java
@@ -93,8 +93,7 @@
         MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
         codecName = mcl.findDecoderForFormat(format);
         if (codecName == null) {
-            throw new IllegalArgumentException(
-                    "No track with mediaType: " + mediaType + " found in file: " + file);
+            throw new IllegalArgumentException("No decoder for format: " + format);
         }
         return codecName;
     }
diff --git a/tests/media/common/src/android/mediav2/common/cts/EncoderProfileLevelTestBase.java b/tests/media/common/src/android/mediav2/common/cts/EncoderProfileLevelTestBase.java
new file mode 100644
index 0000000..1d81c07b
--- /dev/null
+++ b/tests/media/common/src/android/mediav2/common/cts/EncoderProfileLevelTestBase.java
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) 2023 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.mediav2.common.cts;
+
+import static android.media.MediaCodecInfo.CodecProfileLevel.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Wrapper class for testing encoders support for profile and level
+ */
+public class EncoderProfileLevelTestBase extends CodecEncoderTestBase {
+    private static final String LOG_TAG = EncoderProfileLevelTestBase.class.getSimpleName();
+
+    private static int divUp(int num, int den) {
+        return (num + den - 1) / den;
+    }
+
+    public static int getMinLevel(String mediaType, int width, int height, int frameRate,
+            int bitrate, int profile) {
+        switch (mediaType) {
+            case MediaFormat.MIMETYPE_VIDEO_AVC:
+                return getMinLevelAVC(width, height, frameRate, bitrate);
+            case MediaFormat.MIMETYPE_VIDEO_HEVC:
+                return getMinLevelHEVC(width, height, frameRate, bitrate);
+            case MediaFormat.MIMETYPE_VIDEO_H263:
+                return getMinLevelH263(width, height, frameRate, bitrate);
+            case MediaFormat.MIMETYPE_VIDEO_MPEG2:
+                return getMinLevelMPEG2(width, height, frameRate, bitrate);
+            case MediaFormat.MIMETYPE_VIDEO_MPEG4:
+                return getMinLevelMPEG4(width, height, frameRate, bitrate, profile);
+            case MediaFormat.MIMETYPE_VIDEO_VP9:
+                return getMinLevelVP9(width, height, frameRate, bitrate);
+            case MediaFormat.MIMETYPE_VIDEO_AV1:
+                return getMinLevelAV1(width, height, frameRate, bitrate);
+            default:
+                return -1;
+        }
+    }
+
+    private static int getMinLevelAVC(int width, int height, int frameRate, int bitrate) {
+        class LevelLimitAVC {
+            private LevelLimitAVC(int level, int mbsPerSec, long mbs, int bitrate) {
+                this.mLevel = level;
+                this.mMbsPerSec = mbsPerSec;
+                this.mMbs = mbs;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mLevel;
+            private final int mMbsPerSec;
+            private final long mMbs;
+            private final int mBitrate;
+        }
+        LevelLimitAVC[] limitsAVC = {
+                new LevelLimitAVC(AVCLevel1, 1485, 99, 64000),
+                new LevelLimitAVC(AVCLevel1b, 1485, 99, 128000),
+                new LevelLimitAVC(AVCLevel11, 3000, 396, 192000),
+                new LevelLimitAVC(AVCLevel12, 6000, 396, 384000),
+                new LevelLimitAVC(AVCLevel13, 11880, 396, 768000),
+                new LevelLimitAVC(AVCLevel2, 11880, 396, 2000000),
+                new LevelLimitAVC(AVCLevel21, 19800, 792, 4000000),
+                new LevelLimitAVC(AVCLevel22, 20250, 1620, 4000000),
+                new LevelLimitAVC(AVCLevel3, 40500, 1620, 10000000),
+                new LevelLimitAVC(AVCLevel31, 108000, 3600, 14000000),
+                new LevelLimitAVC(AVCLevel32, 216000, 5120, 20000000),
+                new LevelLimitAVC(AVCLevel4, 245760, 8192, 20000000),
+                new LevelLimitAVC(AVCLevel41, 245760, 8192, 50000000),
+                new LevelLimitAVC(AVCLevel42, 522240, 8704, 50000000),
+                new LevelLimitAVC(AVCLevel5, 589824, 22080, 135000000),
+                new LevelLimitAVC(AVCLevel51, 983040, 36864, 240000000),
+                new LevelLimitAVC(AVCLevel52, 2073600, 36864, 240000000),
+                new LevelLimitAVC(AVCLevel6, 4177920, 139264, 240000000),
+                new LevelLimitAVC(AVCLevel61, 8355840, 139264, 480000000),
+                new LevelLimitAVC(AVCLevel62, 16711680, 139264, 800000000),
+        };
+        int blockSize = 16;
+        int mbs = divUp(width, blockSize) * divUp(height, blockSize);
+        float mbsPerSec = mbs * frameRate;
+        for (LevelLimitAVC levelLimitsAVC : limitsAVC) {
+            if (mbs <= levelLimitsAVC.mMbs && mbsPerSec <= levelLimitsAVC.mMbsPerSec
+                    && bitrate <= levelLimitsAVC.mBitrate) {
+                return levelLimitsAVC.mLevel;
+            }
+        }
+        // if none of the levels suffice, select the highest level
+        return AVCLevel62;
+    }
+
+    private static int getMinLevelHEVC(int width, int height, int frameRate, int bitrate) {
+        class LevelLimitHEVC {
+            private LevelLimitHEVC(int level, int frameRate, long samples, int bitrate) {
+                this.mLevel = level;
+                this.mFrameRate = frameRate;
+                this.mSamples = samples;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mLevel;
+            private final int mFrameRate;
+            private final long mSamples;
+            private final int mBitrate;
+        }
+        LevelLimitHEVC[] limitsHEVC = {
+                new LevelLimitHEVC(HEVCMainTierLevel1, 15, 36864, 128000),
+                new LevelLimitHEVC(HEVCMainTierLevel2, 30, 122880, 1500000),
+                new LevelLimitHEVC(HEVCMainTierLevel21, 30, 245760, 3000000),
+                new LevelLimitHEVC(HEVCMainTierLevel3, 30, 552960, 6000000),
+                new LevelLimitHEVC(HEVCMainTierLevel31, 30, 983040, 10000000),
+                new LevelLimitHEVC(HEVCMainTierLevel4, 30, 2228224, 12000000),
+                new LevelLimitHEVC(HEVCHighTierLevel4, 30, 2228224, 30000000),
+                new LevelLimitHEVC(HEVCMainTierLevel41, 60, 2228224, 20000000),
+                new LevelLimitHEVC(HEVCHighTierLevel41, 60, 2228224, 50000000),
+                new LevelLimitHEVC(HEVCMainTierLevel5, 30, 8912896, 25000000),
+                new LevelLimitHEVC(HEVCHighTierLevel5, 30, 8912896, 100000000),
+                new LevelLimitHEVC(HEVCMainTierLevel51, 60, 8912896, 40000000),
+                new LevelLimitHEVC(HEVCHighTierLevel51, 60, 8912896, 160000000),
+                new LevelLimitHEVC(HEVCMainTierLevel52, 120, 8912896, 60000000),
+                new LevelLimitHEVC(HEVCHighTierLevel52, 120, 8912896, 240000000),
+                new LevelLimitHEVC(HEVCMainTierLevel6, 30, 35651584, 60000000),
+                new LevelLimitHEVC(HEVCHighTierLevel6, 30, 35651584, 240000000),
+                new LevelLimitHEVC(HEVCMainTierLevel61, 60, 35651584, 120000000),
+                new LevelLimitHEVC(HEVCHighTierLevel61, 60, 35651584, 480000000),
+                new LevelLimitHEVC(HEVCMainTierLevel62, 120, 35651584, 240000000),
+                new LevelLimitHEVC(HEVCHighTierLevel62, 120, 35651584, 800000000),
+        };
+        int blockSize = 8;
+        int blocks = divUp(width, blockSize) * divUp(height, blockSize);
+        int samples = blocks * blockSize * blockSize;
+        for (LevelLimitHEVC levelLimitsHEVC : limitsHEVC) {
+            if (samples <= levelLimitsHEVC.mSamples && frameRate <= levelLimitsHEVC.mFrameRate
+                    && bitrate <= levelLimitsHEVC.mBitrate) {
+                return levelLimitsHEVC.mLevel;
+            }
+        }
+        // if none of the levels suffice, select the highest level
+        return HEVCHighTierLevel62;
+    }
+
+    private static int getMinLevelH263(int width, int height, int frameRate, int bitrate) {
+        class LevelLimitH263 {
+            private LevelLimitH263(int level, long sampleRate, int width, int height, int frameRate,
+                    int bitrate) {
+                this.mLevel = level;
+                this.mSampleRate = sampleRate;
+                this.mWidth = width;
+                this.mHeight = height;
+                this.mFrameRate = frameRate;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mLevel;
+            private final long mSampleRate;
+            private final int mWidth;
+            private final int mHeight;
+            private final int mFrameRate;
+            private final int mBitrate;
+        }
+        LevelLimitH263[] limitsH263 = {
+                new LevelLimitH263(H263Level10, 380160, 176, 144, 15, 64000),
+                new LevelLimitH263(H263Level45, 380160, 176, 144, 15, 128000),
+                new LevelLimitH263(H263Level20, 1520640, 352, 288, 30, 128000),
+                new LevelLimitH263(H263Level30, 3041280, 352, 288, 30, 384000),
+                new LevelLimitH263(H263Level40, 3041280, 352, 288, 30, 2048000),
+                new LevelLimitH263(H263Level50, 5068800, 352, 288, 60, 4096000),
+                new LevelLimitH263(H263Level60, 10368000, 720, 288, 60, 8192000),
+                new LevelLimitH263(H263Level70, 20736000, 720, 576, 60, 16384000),
+        };
+        int blockSize = 16;
+        int mbs = divUp(width, blockSize) * divUp(height, blockSize);
+        int size = mbs * blockSize * blockSize;
+        int sampleRate = size * frameRate;
+        for (LevelLimitH263 levelLimitsH263 : limitsH263) {
+            if (sampleRate <= levelLimitsH263.mSampleRate && height <= levelLimitsH263.mHeight
+                    && width <= levelLimitsH263.mWidth && frameRate <= levelLimitsH263.mFrameRate
+                    && bitrate <= levelLimitsH263.mBitrate) {
+                return levelLimitsH263.mLevel;
+            }
+        }
+        // if none of the levels suffice, select the highest level
+        return H263Level70;
+    }
+
+    private static int getMinLevelVP9(int width, int height, int frameRate, int bitrate) {
+        class LevelLimitVP9 {
+            private LevelLimitVP9(int level, long sampleRate, int size, int maxWH, int bitrate) {
+                this.mLevel = level;
+                this.mSampleRate = sampleRate;
+                this.mSize = size;
+                this.mMaxWH = maxWH;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mLevel;
+            private final long mSampleRate;
+            private final int mSize;
+            private final int mMaxWH;
+            private final int mBitrate;
+        }
+        LevelLimitVP9[] limitsVP9 = {
+                new LevelLimitVP9(VP9Level1, 829440, 36864, 512, 200000),
+                new LevelLimitVP9(VP9Level11, 2764800, 73728, 768, 800000),
+                new LevelLimitVP9(VP9Level2, 4608000, 122880, 960, 1800000),
+                new LevelLimitVP9(VP9Level21, 9216000, 245760, 1344, 3600000),
+                new LevelLimitVP9(VP9Level3, 20736000, 552960, 2048, 7200000),
+                new LevelLimitVP9(VP9Level31, 36864000, 983040, 2752, 12000000),
+                new LevelLimitVP9(VP9Level4, 83558400, 2228224, 4160, 18000000),
+                new LevelLimitVP9(VP9Level41, 160432128, 2228224, 4160, 30000000),
+                new LevelLimitVP9(VP9Level5, 311951360, 8912896, 8384, 60000000),
+                new LevelLimitVP9(VP9Level51, 588251136, 8912896, 8384, 120000000),
+                new LevelLimitVP9(VP9Level52, 1176502272, 8912896, 8384, 180000000),
+                new LevelLimitVP9(VP9Level6, 1176502272, 35651584, 16832, 180000000),
+                new LevelLimitVP9(VP9Level61, 2353004544L, 35651584, 16832, 240000000),
+                new LevelLimitVP9(VP9Level62, 4706009088L, 35651584, 16832, 480000000),
+        };
+        int blockSize = 8;
+        int blocks = divUp(width, blockSize) * divUp(height, blockSize);
+        int size = blocks * blockSize * blockSize;
+        int sampleRate = size * frameRate;
+        int maxWH = Math.max(width, height);
+        for (LevelLimitVP9 levelLimitsVP9 : limitsVP9) {
+            if (sampleRate <= levelLimitsVP9.mSampleRate && size <= levelLimitsVP9.mSize
+                    && maxWH <= levelLimitsVP9.mMaxWH && bitrate <= levelLimitsVP9.mBitrate) {
+                return levelLimitsVP9.mLevel;
+            }
+        }
+        // if none of the levels suffice, select the highest level
+        return VP9Level62;
+    }
+
+    private static int getMinLevelMPEG2(int width, int height, int frameRate, int bitrate) {
+        class LevelLimitMPEG2 {
+            private LevelLimitMPEG2(int level, long sampleRate, int width, int height,
+                    int frameRate, int bitrate) {
+                this.mLevel = level;
+                this.mSampleRate = sampleRate;
+                this.mWidth = width;
+                this.mHeight = height;
+                this.mFrameRate = frameRate;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mLevel;
+            private final long mSampleRate;
+            private final int mWidth;
+            private final int mHeight;
+            private final int mFrameRate;
+            private final int mBitrate;
+        }
+        // main profile limits, higher profiles will also support selected level
+        LevelLimitMPEG2[] limitsMPEG2 = {
+                new LevelLimitMPEG2(MPEG2LevelLL, 3041280, 352, 288, 30, 4000000),
+                new LevelLimitMPEG2(MPEG2LevelML, 10368000, 720, 576, 30, 15000000),
+                new LevelLimitMPEG2(MPEG2LevelH14, 47001600, 1440, 1088, 60, 60000000),
+                new LevelLimitMPEG2(MPEG2LevelHL, 62668800, 1920, 1088, 60, 80000000),
+                new LevelLimitMPEG2(MPEG2LevelHP, 125337600, 1920, 1088, 60, 80000000),
+        };
+        int blockSize = 16;
+        int mbs = divUp(width, blockSize) * divUp(height, blockSize);
+        int size = mbs * blockSize * blockSize;
+        int sampleRate = size * frameRate;
+        for (LevelLimitMPEG2 levelLimitsMPEG2 : limitsMPEG2) {
+            if (sampleRate <= levelLimitsMPEG2.mSampleRate && width <= levelLimitsMPEG2.mWidth
+                    && height <= levelLimitsMPEG2.mHeight
+                    && frameRate <= levelLimitsMPEG2.mFrameRate
+                    && bitrate <= levelLimitsMPEG2.mBitrate) {
+                return levelLimitsMPEG2.mLevel;
+            }
+        }
+        // if none of the levels suffice, select the highest level
+        return MPEG2LevelHP;
+    }
+
+    private static int getMinLevelMPEG4(int width, int height, int frameRate, int bitrate,
+            int profile) {
+        class LevelLimitMPEG4 {
+            private LevelLimitMPEG4(int profile, int level, long sampleRate, int width, int height,
+                    int frameRate, int bitrate) {
+                this.mProfile = profile;
+                this.mLevel = level;
+                this.mSampleRate = sampleRate;
+                this.mWidth = width;
+                this.mHeight = height;
+                this.mFrameRate = frameRate;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mProfile;
+            private final int mLevel;
+            private final long mSampleRate;
+            private final int mWidth;
+            private final int mHeight;
+            private final int mFrameRate;
+            private final int mBitrate;
+        }
+        // simple profile limits, higher profiles will also support selected level
+        LevelLimitMPEG4[] limitsMPEG4 = {
+                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level0, 380160, 176, 144, 15, 64000),
+                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level1, 380160, 176, 144, 30, 64000),
+                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level0b, 380160, 176, 144, 15, 128000),
+                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level2, 1520640, 352, 288, 30, 128000),
+                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level3, 3041280, 352, 288, 30, 384000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileSimple, MPEG4Level4a, 9216000, 640, 480, 30, 4000000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileSimple, MPEG4Level5, 10368000, 720, 576, 30, 8000000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileSimple, MPEG4Level6, 27648000, 1280, 720, 30, 12000000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileAdvancedSimple, MPEG4Level1, 760320, 176, 144, 30, 128000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileAdvancedSimple, MPEG4Level2, 1520640, 352, 288, 30, 384000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileAdvancedSimple, MPEG4Level3, 3041280, 352, 288, 30, 768000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileAdvancedSimple, MPEG4Level3b, 3041280, 352, 288, 30, 1500000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileAdvancedSimple, MPEG4Level4, 6082560, 704, 576, 30, 3000000),
+                new LevelLimitMPEG4(
+                        MPEG4ProfileAdvancedSimple, MPEG4Level5, 12441600, 720, 576, 30, 8000000),
+        };
+        int blockSize = 16;
+        int mbs = divUp(width, blockSize) * divUp(height, blockSize);
+        int size = mbs * blockSize * blockSize;
+        int sampleRate = size * frameRate;
+        if (profile != MPEG4ProfileAdvancedSimple && profile != MPEG4ProfileSimple) {
+            throw new RuntimeException("Unrecognized profile " + profile + " for "
+                    + MediaFormat.MIMETYPE_VIDEO_MPEG4);
+        }
+        for (LevelLimitMPEG4 levelLimitsMPEG4 : limitsMPEG4) {
+            if (profile == levelLimitsMPEG4.mProfile && sampleRate <= levelLimitsMPEG4.mSampleRate
+                    && width <= levelLimitsMPEG4.mWidth && height <= levelLimitsMPEG4.mHeight
+                    && frameRate <= levelLimitsMPEG4.mFrameRate
+                    && bitrate <= levelLimitsMPEG4.mBitrate) {
+                return levelLimitsMPEG4.mLevel;
+            }
+        }
+        // if none of the levels suffice, select the highest level
+        return MPEG4Level6;
+    }
+
+    private static int getMinLevelAV1(int width, int height, int frameRate, int bitrate) {
+        class LevelLimitAV1 {
+            private LevelLimitAV1(int level, int size, int width, int height, long sampleRate,
+                    int bitrate) {
+                this.mLevel = level;
+                this.mSize = size;
+                this.mWidth = width;
+                this.mHeight = height;
+                this.mSampleRate = sampleRate;
+                this.mBitrate = bitrate;
+            }
+
+            private final int mLevel;
+            private final int mSize;
+            private final int mWidth;
+            private final int mHeight;
+            private final long mSampleRate;
+            private final int mBitrate;
+        }
+        // taking bitrate from main profile, will also be supported by high profile
+        LevelLimitAV1[] limitsAV1 = {
+                new LevelLimitAV1(AV1Level2, 147456, 2048, 1152, 4423680, 1500000),
+                new LevelLimitAV1(AV1Level21, 278784, 2816, 1584, 8363520, 3000000),
+                new LevelLimitAV1(AV1Level3, 665856, 4352, 2448, 19975680, 6000000),
+                new LevelLimitAV1(AV1Level31, 1065024, 5504, 3096, 31950720, 10000000),
+                new LevelLimitAV1(AV1Level4, 2359296, 6144, 3456, 70778880, 12000000),
+                new LevelLimitAV1(AV1Level41, 2359296, 6144, 3456, 141557760, 20000000),
+                new LevelLimitAV1(AV1Level5, 8912896, 8192, 4352, 267386880, 30000000),
+                new LevelLimitAV1(AV1Level51, 8912896, 8192, 4352, 534773760, 40000000),
+                new LevelLimitAV1(AV1Level52, 8912896, 8192, 4352, 1069547520, 60000000),
+                new LevelLimitAV1(AV1Level53, 8912896, 8192, 4352, 1069547520, 60000000),
+                new LevelLimitAV1(AV1Level6, 35651584, 16384, 8704, 1069547520, 60000000),
+                new LevelLimitAV1(AV1Level61, 35651584, 16384, 8704, 2139095040, 100000000),
+                new LevelLimitAV1(AV1Level62, 35651584, 16384, 8704, 4278190080L, 160000000),
+                new LevelLimitAV1(AV1Level63, 35651584, 16384, 8704, 4278190080L, 160000000),
+        };
+        int blockSize = 8;
+        int blocks = divUp(width, blockSize) * divUp(height, blockSize);
+        int size = blocks * blockSize * blockSize;
+        int sampleRate = size * frameRate;
+        for (LevelLimitAV1 levelLimitsAV1 : limitsAV1) {
+            if (size <= levelLimitsAV1.mSize && width <= levelLimitsAV1.mWidth
+                    && height <= levelLimitsAV1.mHeight && sampleRate <= levelLimitsAV1.mSampleRate
+                    && bitrate <= levelLimitsAV1.mBitrate) {
+                return levelLimitsAV1.mLevel;
+            }
+        }
+        // if none of the levels suffice or high profile, select the highest level
+        return AV1Level73;
+    }
+
+    protected BitStreamUtils.ParserBase mParser;
+    protected Pair<Integer, Integer> mProfileLevel;
+    protected boolean mGotCsd;
+
+    public EncoderProfileLevelTestBase(String encoder, String mediaType,
+            EncoderConfigParams[] encCfgParams, String allTestParams) {
+        super(encoder, mediaType, encCfgParams, allTestParams);
+    }
+
+    @Override
+    protected void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
+        super.resetContext(isAsync, signalEOSWithLastFrame);
+        mParser = BitStreamUtils.getParserObject(mMediaType);
+        mProfileLevel = null;
+        mGotCsd = false;
+    }
+
+    @Override
+    protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+        if (info.size > 0 && mProfileLevel == null) {
+            if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+                ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
+                mProfileLevel = BitStreamUtils.getProfileLevelFromBitStream(buf, info, mParser);
+                mGotCsd = true;
+            } else {
+                if ((mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_VP9) || mMediaType.equals(
+                        MediaFormat.MIMETYPE_VIDEO_H263)) && mOutputCount == 0) {
+                    ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
+                    mProfileLevel = BitStreamUtils.getProfileLevelFromBitStream(buf, info, mParser);
+                }
+            }
+        }
+        super.dequeueOutput(bufferIndex, info);
+    }
+
+    private int getProfile(MediaFormat format, String msg) {
+        // Query output profile. KEY_PROFILE gets precedence over KEY_AAC_PROFILE
+        int aacProfile = format.getInteger(MediaFormat.KEY_AAC_PROFILE, -1);
+        int profile = format.getInteger(MediaFormat.KEY_PROFILE, aacProfile);
+        if (profile != -1) {
+            return profile;
+        } else {
+            fail(msg + "profile key not present in format " + format + mTestConfig + mTestEnv);
+        }
+        return -1;
+    }
+
+    private int getLevel(MediaFormat format, String msg) {
+        assertTrue(msg + "level not present in format " + format + mTestConfig + mTestEnv,
+                format.containsKey(MediaFormat.KEY_LEVEL));
+        return format.getInteger(MediaFormat.KEY_LEVEL);
+    }
+
+    protected void validateProfile(int exp, int got, String msg) {
+        if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            if (exp == AVCProfileBaseline || exp == AVCProfileConstrainedBaseline) {
+                assertTrue(String.format(msg + "Profile information mismatch, Expected %d, Got %d ",
+                                exp, got) + mTestConfig + mTestEnv,
+                        (got == AVCProfileBaseline || got == AVCProfileConstrainedBaseline));
+                return;
+            } else if (exp == AVCProfileHigh || exp == AVCProfileConstrainedHigh) {
+                assertTrue(String.format(msg + "Profile information mismatch, Expected %d, Got %d ",
+                                exp, got) + mTestConfig + mTestEnv,
+                        (got == AVCProfileHigh || got == AVCProfileConstrainedHigh));
+                return;
+            }
+        }
+        assertEquals(String.format(msg + "Profile information mismatch, Expected %d, Got %d ",
+                exp, got) + mTestConfig + mTestEnv, exp, got);
+    }
+
+    protected void validateLevel(int exp, int got, String msg) {
+        assertEquals(String.format(msg + "Level information mismatch, Expected %d, Got %d ",
+                exp, got) + mTestConfig + mTestEnv, exp, got);
+    }
+
+    protected void validateMinLevel(int min, int got, String msg) {
+        assertTrue(String.format(msg + "Level information unexpected, Expected at least %d,"
+                + " Got %d ", min, got) + mTestConfig + mTestEnv, min <= got);
+    }
+
+    protected void validateBitStreamForProfileAndLevel(int cfgProfile, int cfgLevel) {
+        if (mProfileLevel != null) {
+            validateProfile(cfgProfile, mProfileLevel.first, "Validating profile of bitstream : ");
+            if (mProfileLevel.second != -1) {
+                validateMinLevel(cfgLevel, mProfileLevel.second,
+                        "Validating level of bitstream : ");
+            }
+        }
+    }
+
+    protected void validateFormatForProfileAndLevelWRTBitstream(MediaFormat format, String msg) {
+        if (mProfileLevel != null) {
+            validateProfile(mProfileLevel.first, getProfile(format, msg), msg);
+            if (mProfileLevel.second != -1) {
+                validateLevel(mProfileLevel.second, getLevel(format, msg), msg);
+            }
+        }
+    }
+
+    protected void validateFormatForProfileAndLevelWRTCfg(MediaFormat format, String msg) {
+        validateProfile(mActiveEncCfg.mProfile, getProfile(format, msg), msg);
+        if (mActiveEncCfg.mLevel != -1) {
+            validateMinLevel(mActiveEncCfg.mLevel, getLevel(format, msg), msg);
+        }
+    }
+
+    protected void validateFormatForProfileAndLevel(MediaFormat format, String msg) {
+        validateFormatForProfileAndLevelWRTBitstream(format, msg + " wrt to bitstream : ");
+        validateFormatForProfileAndLevelWRTCfg(format, msg + " wrt to cfg : ");
+    }
+
+    protected MediaFormat validateProfileAndLevel() throws IOException {
+        // check if bitstream is in accordance with configured profile and level info.
+        if (mProfileLevel != null) {
+            validateBitStreamForProfileAndLevel(mActiveEncCfg.mProfile, mActiveEncCfg.mLevel);
+        }
+
+        // check if output format is in accordance with configured profile and level info.
+        if (mCodecName.toUpperCase().startsWith("OMX")) {
+            Log.i(LOG_TAG, "omx components don't present prof/level in outputformat");
+        } else {
+            validateFormatForProfileAndLevel(mOutFormat, "Testing output format : ");
+        }
+
+        // check if extracted output profile and level information are in accordance with
+        // configured profile and level info
+        if (mMuxOutput && !mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_H263)) {
+            // Explicit signaling of header information such as profile, level etc is not
+            // directly available as HLS in H263 header. That information is conveyed through
+            // external means of RTP header
+            MediaExtractor extractor = new MediaExtractor();
+            extractor.setDataSource(mMuxedOutputFile);
+            assertEquals("Should be only 1 track \n" + mTestConfig + mTestEnv, 1,
+                    extractor.getTrackCount());
+            MediaFormat trackFormat = extractor.getTrackFormat(0);
+            extractor.release();
+            if (mGotCsd || (trackFormat.containsKey(MediaFormat.KEY_PROFILE)
+                    || trackFormat.containsKey(MediaFormat.KEY_LEVEL))) {
+                validateFormatForProfileAndLevel(trackFormat, "Testing extractor format :- ");
+            }
+            return trackFormat;
+        }
+        return null;
+    }
+}
diff --git a/tests/media/common/src/android/mediav2/common/cts/OutputSurface.java b/tests/media/common/src/android/mediav2/common/cts/OutputSurface.java
index cc975d4..86c14bad 100644
--- a/tests/media/common/src/android/mediav2/common/cts/OutputSurface.java
+++ b/tests/media/common/src/android/mediav2/common/cts/OutputSurface.java
@@ -172,8 +172,11 @@
         EGLConfig[] configs = new EGLConfig[1];
         int[] numConfigs = new int[1];
         if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
-                numConfigs, 0)) {
-            throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
+                numConfigs, 0) || numConfigs[0] == 0) {
+            throw new RuntimeException(String.format(
+                    "unable to find EGL config supporting renderable-type:ES2 "
+                    + "surface-type:pbuffer r:%d g:%d b:%d a:%d",
+                    eglColorSize, eglColorSize, eglColorSize, eglAlphaSize));
         }
 
         // Configure context for OpenGL ES 3.0/2.0.
diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh
index a45c747..66db3b4 100755
--- a/tests/media/copy_media.sh
+++ b/tests/media/copy_media.sh
@@ -17,7 +17,7 @@
 ## script to install mediav2 test files manually
 
 adbOptions=" "
-resLabel=CtsMediaV2TestCases-3.2
+resLabel=CtsMediaV2TestCases-3.4
 srcDir="/tmp/$resLabel"
 tgtDir="/sdcard/test"
 usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
index 7dda9cb..d85b242 100644
--- a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
+++ b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
@@ -81,7 +81,7 @@
         setUpSurface(mActivity);
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/AudioEncoderTest.java b/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
index 54460fc..51d8ae5 100644
--- a/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
@@ -110,7 +110,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = true;
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
index 3dcc213..ae57cee 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
@@ -59,7 +59,7 @@
         mSupportRequirements = supportRequirements;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index 82d0a14..4851eab 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -138,7 +138,7 @@
         setUpSurface(mActivity);
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index b176384..00ed238 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -163,7 +163,7 @@
         return list;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index d7e424e..799aa72 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -118,7 +118,7 @@
         mSupportRequirements = supportRequirements;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index 7e4199b..e302c59 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -251,7 +251,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{9})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}_{3}_{9}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
index be8fd60..c8a9ece 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
@@ -244,7 +244,7 @@
         return params;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = true;
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index 8f803b4..d295a59 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -81,7 +81,7 @@
         mCodecInfo = codecInfo;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final List<Object[]> argsList = new ArrayList<>();
         MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
diff --git a/tests/media/src/android/mediav2/cts/CodecUnitTest.java b/tests/media/src/android/mediav2/cts/CodecUnitTest.java
index ecfb4cf..5358ce2 100644
--- a/tests/media/src/android/mediav2/cts/CodecUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecUnitTest.java
@@ -28,6 +28,7 @@
 import android.media.MediaFormat;
 import android.mediav2.common.cts.CodecTestBase;
 import android.os.Bundle;
+import android.util.Log;
 import android.util.Pair;
 
 import androidx.test.filters.SdkSuppress;
@@ -50,6 +51,7 @@
 
 @RunWith(Enclosed.class)
 public class CodecUnitTest {
+    private static final String TAG = "CodecUnitTest";
     static final int PER_TEST_TIMEOUT_MS = 10000;
     static final long STALL_TIME_MS = 1000;
 
@@ -131,6 +133,7 @@
                     if (!(e instanceof IllegalArgumentException)) {
                         fail("codec configure rec/exp :: " + e + " / IllegalArgumentException");
                     }
+                    Log.v(TAG, "expected exception thrown", e);
                 }
             }
             try {
@@ -159,6 +162,7 @@
                 if (!(e instanceof IllegalArgumentException)) {
                     fail("codec configure rec/exp :: " + e + " / IllegalArgumentException");
                 }
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 mCodec.release();
             }
@@ -169,7 +173,7 @@
                 configureCodec(format, isAsync, false, true);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -178,7 +182,7 @@
                 mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -188,7 +192,7 @@
                 mCodec.dequeueOutputBuffer(info, Q_DEQ_TIMEOUT_US);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -197,7 +201,7 @@
                 flushCodec();
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -232,7 +236,7 @@
                 mCodec.getInputBuffer(0);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -241,7 +245,7 @@
                 mCodec.getInputFormat();
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -250,7 +254,7 @@
                 mCodec.getOutputBuffer(0);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -259,14 +263,14 @@
                 mCodec.getOutputFormat();
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
 
             try {
                 mCodec.getOutputFormat(0);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -275,7 +279,7 @@
                 mCodec.start();
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -284,7 +288,7 @@
                 mCodec.getInputImage(0);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -293,7 +297,7 @@
                 mCodec.getOutputImage(0);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -302,7 +306,7 @@
                 mCodec.queueInputBuffer(0, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -311,7 +315,7 @@
                 mCodec.releaseOutputBuffer(0, false);
                 fail(msg);
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -322,7 +326,7 @@
                 mCodec = MediaCodec.createByCodecName(null);
                 fail("createByCodecName succeeds with null argument");
             } catch (NullPointerException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 if (mCodec != null) mCodec.release();
             }
@@ -335,7 +339,7 @@
                 mCodec = MediaCodec.createByCodecName("invalid name");
                 fail("createByCodecName succeeds with invalid name");
             } catch (IllegalArgumentException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 if (mCodec != null) mCodec.release();
             }
@@ -348,7 +352,7 @@
                 mCodec = MediaCodec.createDecoderByType(null);
                 fail("createDecoderByType succeeds with null argument");
             } catch (NullPointerException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 if (mCodec != null) mCodec.release();
             }
@@ -361,7 +365,7 @@
                 mCodec = MediaCodec.createDecoderByType("invalid mediaType");
                 fail("createDecoderByType succeeds with invalid mediaType");
             } catch (IllegalArgumentException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 if (mCodec != null) mCodec.release();
             }
@@ -374,7 +378,7 @@
                 mCodec = MediaCodec.createEncoderByType(null);
                 fail("createEncoderByType succeeds with null argument");
             } catch (NullPointerException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 if (mCodec != null) mCodec.release();
             }
@@ -387,7 +391,7 @@
                 mCodec = MediaCodec.createEncoderByType("invalid mediaType");
                 fail("createEncoderByType succeeds with invalid mediaType");
             } catch (IllegalArgumentException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             } finally {
                 if (mCodec != null) mCodec.release();
             }
@@ -896,28 +900,28 @@
                 mCodec.getCanonicalName();
                 fail("get canonical name succeeds after codec release");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
 
             try {
                 mCodec.getCodecInfo();
                 fail("get codec info succeeds after codec release");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
 
             try {
                 mCodec.getName();
                 fail("get name succeeds after codec release");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
 
             try {
                 mCodec.getMetrics();
                 fail("get metrics succeeds after codec release");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -998,7 +1002,7 @@
                 mIsCodecInAsyncMode = !isAsync;
                 fail("set call back succeeds in running state");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
             queueEOS();
             waitForAllOutputs();
@@ -1013,7 +1017,7 @@
                 mIsCodecInAsyncMode = isAsync;
                 fail("set call back succeeds in running state");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
             queueEOS();
             waitForAllOutputs();
@@ -1033,7 +1037,7 @@
                 mAsyncHandle.setCallBack(mCodec, false);
                 fail("set call back succeeds in released state");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -1307,7 +1311,7 @@
                     mCodec.getOutputFormat(0);
                     fail("getOutputFormat succeeds in released state");
                 } catch (IllegalStateException e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 mCodec.start();
                 mCodec.stop();
@@ -1456,7 +1460,7 @@
                 mCodec.setParameters(updateBitrate(bitrate >> 1));
                 fail("Codec set parameter succeeds in release mode");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -1559,7 +1563,7 @@
                 mCodec.stop();
                 fail("Codec stop succeeds in release mode");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -1621,7 +1625,7 @@
                 mCodec.reset();
                 fail("Codec reset succeeds in release mode");
             } catch (IllegalStateException e) {
-                // expected
+                Log.v(TAG, "expected exception thrown", e);
             }
         }
 
@@ -1868,7 +1872,7 @@
                     mCodec.queueInputBuffer(-1, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                     fail("queueInputBuffer succeeds with bad buffer index :: " + -1);
                 } catch (Exception e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 mCodec.stop();
                 mCodec.reset();
@@ -1896,7 +1900,7 @@
                     fail("queueInputBuffer succeeds with bad size param :: " + buffer.capacity() +
                             100);
                 } catch (Exception e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 mCodec.stop();
                 mCodec.reset();
@@ -1923,7 +1927,7 @@
                             MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                     fail("queueInputBuffer succeeds with bad offset and size param");
                 } catch (Exception e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 mCodec.stop();
                 mCodec.reset();
@@ -1951,7 +1955,7 @@
                             MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                     fail("queueInputBuffer succeeds with bad offset param :: " + -1);
                 } catch (Exception e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 mCodec.stop();
                 mCodec.reset();
@@ -2021,7 +2025,7 @@
                     mCodec.releaseOutputBuffer(-1, false);
                     fail("releaseOutputBuffer succeeds for bad buffer index " + -1);
                 } catch (MediaCodec.CodecException e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 queueEOS();
                 int bufferIndex = 0;
@@ -2045,7 +2049,7 @@
                     mCodec.releaseOutputBuffer(bufferIndex, false);
                     fail("releaseOutputBuffer succeeds for buffer index not owned by client");
                 } catch (MediaCodec.CodecException e) {
-                    // expected
+                    Log.v(TAG, "expected exception thrown", e);
                 }
                 mCodec.stop();
                 mCodec.reset();
diff --git a/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java b/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java
index 798b384..5be61ce 100644
--- a/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java
@@ -309,7 +309,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3}_{4}_{5}_{6}_{7})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}_{4}_{5}_{6}_{7}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
index 7a21152..d8114e2 100644
--- a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
@@ -82,7 +82,7 @@
         mSupportRequirements = supportRequirements;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3}_{4}_{5})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}_{4}_{5}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
diff --git a/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
index 3ea3a4c..68cb566 100644
--- a/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
@@ -67,7 +67,7 @@
         mHDRDynamicInfoContainer = hdrDynamicInfoContainer;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
index 157ad1a..e3ef98c 100644
--- a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
@@ -195,7 +195,7 @@
                 .build();
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
index a754351..04ebb11 100644
--- a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
@@ -111,7 +111,7 @@
                     for (int transfer : transfers) {
                         for (int maxBFrame : maxBFrames) {
                             if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
-                                    && !mediaType.equals((MediaFormat.MIMETYPE_VIDEO_HEVC))
+                                    && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)
                                     && maxBFrame != 0) {
                                 continue;
                             }
@@ -126,7 +126,7 @@
                                     .setInputBitDepth(bitDepth)
                                     .build();
                             testArgs[1] = cfg;
-                            testArgs[2] = String.format("%s:%s:%s:%s:%d-bframes",
+                            testArgs[2] = String.format("%s_%s_%s_%s_%d-bframes",
                                     rangeToString(range),
                                     colorStandardToString(standard),
                                     colorTransferToString(transfer),
@@ -140,7 +140,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
index c6877e0..0b4ed23b 100644
--- a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
@@ -83,7 +83,7 @@
                 .build();
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index 75c6aa2..9a6b350 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -24,15 +24,12 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
-import android.media.MediaExtractor;
 import android.media.MediaFormat;
-import android.media.MediaMuxer;
-import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
+import android.mediav2.common.cts.EncoderProfileLevelTestBase;
 import android.mediav2.common.cts.OutputManager;
 import android.util.Log;
 import android.util.Pair;
@@ -45,9 +42,7 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import java.io.File;
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -59,23 +54,26 @@
  * in its codec capabilities. The test sets profile and level keys in media format and uses it
  * during encoder configuration. Upon successful configuration, frames are queued for encoding
  * (byte buffer mode) and the encoded output (bitstream) is expected to contain the same profile
- * and level information that was used during configure.
+ * that was used during configure. The level shall be at least the input configured level.
  * <p>
- * NOTE: The test configures profile, level information basing on standard guidelines, not
- * arbitrarily so encoders ARE expected to place these values in the bitstream as-is.
+ * NOTE: The test configures level information basing on standard guidelines, not arbitrarily so
+ * encoders are expected to maintain at least the input configured level
  * <p>
- * The test additionally checks if the output format returned by component contains same profile
- * and level information. Having output format contain this information is useful during muxing
+ * The test parses the bitstream (csd or frame header) and determines profile and level
+ * information. This serves as reference for further validation. The test checks if the output
+ * format returned by component contains same profile and level information as the bitstream. The
+ * output of encoder is muxed and is extracted. The extracted format is expected to contain same
+ * profile and level information as the bitstream.
  * <p>
  * As per cdd, if a device contains an encoder capable of encoding a profile/level combination
  * then it should contain a decoder capable of decoding the same profile/level combination. This
  * is verified.
  * <p>
  * If device implementations support encoding in a media type, then as per cdd they are expected to
- * handle certain profile and level configurations. This is verified as well.
+ * handle certain profile and level configurations. This is verified.
  */
 @RunWith(Parameterized.class)
-public class EncoderProfileLevelTest extends CodecEncoderTestBase {
+public class EncoderProfileLevelTest extends EncoderProfileLevelTestBase {
     private static final String LOG_TAG = EncoderProfileLevelTest.class.getSimpleName();
     private static final HashMap<String, Pair<int[], Integer>> PROFILE_LEVEL_CDD = new HashMap<>();
 
@@ -85,16 +83,52 @@
         super(encoder, mediaType, encCfgParams, allTestParams);
     }
 
+    private static List<Object[]> prepareTestArgs(Object[] arg, int[] profiles, int colorFormat) {
+        List<Object[]> argsList = new ArrayList<>();
+        final int[] maxBFrames = {0, 2};
+        final String mediaType = (String) arg[0];
+        boolean isVideo = mediaType.startsWith("video/");
+        final int br = (int) arg[1];
+        final int param1 = (int) arg[2];
+        final int param2 = (int) arg[3];
+        final int fps = (int) arg[4];
+        if (isVideo) {
+            for (int maxBframe : maxBFrames) {
+                if (maxBframe != 0) {
+                    if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                            && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+                        continue;
+                    }
+                }
+                Object[] testArgs = new Object[3];
+                testArgs[0] = arg[0];
+                testArgs[1] = getVideoEncoderCfgParams(mediaType, br, param1, param2, fps,
+                        colorFormat, maxBframe, profiles);
+                testArgs[2] = String.format("%dkbps_%dx%d_%dfps_%s_%d-bframes", br / 1000, param1,
+                        param2, fps, colorFormatToString(colorFormat, -1), maxBframe);
+                argsList.add(testArgs);
+            }
+        } else {
+            Object[] testArgs = new Object[3];
+            testArgs[0] = arg[0];
+            testArgs[1] = getAudioEncoderCfgParams(mediaType, br, param1, param2, profiles);
+            testArgs[2] = String.format("%dkbps_%dkHz_%dch", br / 1000, param1 / 1000, param2);
+            argsList.add(testArgs);
+        }
+        return argsList;
+    }
+
     private static EncoderConfigParams[] getVideoEncoderCfgParams(String mediaType, int bitRate,
             int width, int height, int frameRate, int colorFormat, int maxBframe, int[] profiles) {
         ArrayList<EncoderConfigParams> cfgParams = new ArrayList<>();
         for (int profile : profiles) {
             int level = getMinLevel(mediaType, width, height, frameRate, bitRate, profile);
-            if (mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
-                    && maxBframe != 0
-                    && (profile == AVCProfileBaseline
-                    || profile == AVCProfileConstrainedBaseline)) {
-                continue;
+            if (maxBframe != 0) {
+                if (mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC) && (
+                        profile == AVCProfileBaseline
+                                || profile == AVCProfileConstrainedBaseline)) {
+                    continue;
+                }
             }
             cfgParams.add(new EncoderConfigParams.Builder(mediaType)
                     .setBitRate(bitRate)
@@ -124,7 +158,7 @@
         return cfgParams;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = true;
@@ -134,166 +168,133 @@
                 {MediaFormat.MIMETYPE_AUDIO_AAC, 64000, 48000, 1, -1},
                 {MediaFormat.MIMETYPE_AUDIO_AAC, 128000, 48000, 2, -1},
                 // Video - CodecMediaType, bit-rate, height, width, frame-rate
-                // TODO (b/151423508)
-                /*{MediaFormat.MIMETYPE_VIDEO_AVC, 64000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 128000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 192000, 352, 288, 7},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 352, 288, 15},*/
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 768000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 352, 288, 30},
-                // TODO (b/151423508)
-                /*{MediaFormat.MIMETYPE_VIDEO_AVC, 4000000, 352, 576, 25},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 4000000, 720, 576, 12},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 720, 576, 25},*/
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 14000000, 1280, 720, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 20000000, 1280, 1024, 42},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 20000000, 2048, 1024, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 50000000, 2048, 1024, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 50000000, 2048, 1080, 60},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 135000000, 3672, 1536, 25},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 240000000, 4096, 2304, 25},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 240000000, 4096, 2304, 50},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 240000000, 8192, 4320, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 480000000, 8192, 4320, 60},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, 800000000, 8192, 4320, 120},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 64000, 128, 96, 30},  // AVCLevel1
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 128000, 176, 144, 15}, // AVCLevel1b
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 192000, 320, 240, 10},  // AVCLevel11
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20},  // AVCLevel12
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 512000, 352, 240, 30},  // AVCLevel13
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 832000, 352, 288, 30},  // AVCLevel2
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 1000000, 352, 576, 25},  // AVCLevel21
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 1500000, 640, 480, 15},  // AVCLevel22
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30},  // AVCLevel3
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30},  // AVCLevel31
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 6000000, 1280, 1024, 42},  // AVCLevel32
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1088, 30},  // AVCLevel4
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 25000000, 2048, 1024, 30},  // AVCLevel41
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 50000000, 2048, 1088, 60},  // AVCLevel42
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 60000000, 2560, 1920, 30},  // AVCLevel5
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 80000000, 4096, 2048, 30},  // AVCLevel51
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 120000000, 4096, 2160, 60},  // AVCLevel52
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 240000000, 8192, 4320, 30},  // AVCLevel6
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 480000000, 8192, 4320, 60},  // AVCLevel61
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 800000000, 8192, 4320, 120},  // AVCLevel62
 
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 4000000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 15000000, 720, 576, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 60000000, 1440, 1088, 60},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 80000000, 1920, 1088, 60},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 80000000, 1920, 1088, 60},
+                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 4000000, 352, 288, 30},  // MPEG2LevelLL
+                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 15000000, 720, 480, 30},  // MPEG2LevelML
+                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 60000000, 1440, 1088, 30},  // MPEG2LevelH14
+                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 80000000, 1920, 1088, 30},  // MPEG2LevelHL
+                {MediaFormat.MIMETYPE_VIDEO_MPEG2, 80000000, 1920, 1088, 60},  // MPEG2LevelHP
 
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 384000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 4000000, 640, 480, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 8000000, 720, 576, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 12000000, 1280, 720, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 176, 144, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 384000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 768000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 1500000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 3000000, 704, 576, 30},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 8000000, 720, 576, 30},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 200000, 256, 144, 15},  // VP9Level1
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 512000, 384, 192, 30},  // VP9Level11
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 1000000, 480, 256, 30},  // VP9Level2
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 1500000, 640, 384, 30},  // VP9Level21
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30},  // VP9Level3
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30},  // VP9Level31
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30},  // VP9Level4
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 16000000, 2048, 1088, 60},  // VP9Level41
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30},  // VP9Level5
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 80000000, 4096, 2176, 60},  // VP9Level51
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 160000000, 4096, 2176, 120},  // VP9Level52
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 180000000, 8192, 4352, 30},  // VP9Level6
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 240000000, 8192, 4352, 60},  // VP9Level61
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 480000000, 8192, 4352, 120},  // VP9Level62
 
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 200000, 256, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 8000000, 384, 192, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 1800000, 480, 256, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 3600000, 640, 384, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 7200000, 1080, 512, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 12000000, 1280, 768, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 18000000, 2048, 1088, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 30000000, 2048, 1088, 60},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 60000000, 4096, 2176, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 120000000, 4096, 2176, 60},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 180000000, 4096, 2176, 120},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 180000000, 8192, 4352, 30},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 240000000, 8192, 4352, 60},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, 480000000, 8192, 4352, 120},
+                {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 176, 144, 15},  // H263Level10
+                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 15},  // H263Level45
+                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 352, 288, 15},  // H263Level20
+                {MediaFormat.MIMETYPE_VIDEO_H263, 384000, 352, 288, 30},  // H263Level30
+                {MediaFormat.MIMETYPE_VIDEO_H263, 2048000, 352, 288, 30},  // H263Level40
+                {MediaFormat.MIMETYPE_VIDEO_H263, 4096000, 352, 240, 60},  // H263Level50
+                {MediaFormat.MIMETYPE_VIDEO_H263, 8192000, 720, 240, 60},  // H263Level60
+                {MediaFormat.MIMETYPE_VIDEO_H263, 16384000, 720, 576, 50},  // H263Level70
 
-                {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 30},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 352, 288, 15},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 384000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 2048000, 352, 288, 30},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 4096000, 352, 240, 60},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 4096000, 352, 288, 50},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 8192000, 720, 240, 60},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 8192000, 720, 288, 50},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 16384000, 720, 480, 60},
-                {MediaFormat.MIMETYPE_VIDEO_H263, 16384000, 720, 576, 50},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 128000, 176, 144, 15},  // HEVCMainTierLevel1
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 512000, 352, 288, 30},  // HEVCMainTierLevel2
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1000000, 640, 360, 30},  // HEVCMainTierLevel21
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1000000, 512, 512, 30},  // HEVCMainTierLevel3
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30},  // HEVCMainTierLevel3
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30},  // HEVCMainTierLevel31
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30},  // HEVCMainTierLevel4
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 16000000, 1920, 1080, 30},  // HEVCHighTierLevel4
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 1920, 1080, 60},  // HEVCMainTierLevel41
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 30000000, 1920, 1080, 60},  // HEVCHighTierLevel41
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30},  // HEVCMainTierLevel5
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 50000000, 3840, 2160, 30},  // HEVCHighTierLevel5
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 40000000, 3840, 2160, 60},  // HEVCMainTierLevel51
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 80000000, 3840, 2160, 60},  // HEVCHighTierLevel51
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 50000000, 3840, 2160, 120}, // HEVCMainTierLevel52
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 100000000, 3840, 2160, 120}, //HEVCHighTierLevel52
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 50000000, 7680, 4320, 30},  // HEVCMainTierLevel6
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 80000000, 7680, 4320, 30},  // HEVCHighTierLevel6
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 100000000, 7680, 4320, 60}, // HEVCMainTierLevel61
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 240000000, 7680, 4320, 60}, // HEVCHighTierLevel61
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 200000000, 7680, 4320, 120}, //HEVCMainTierLevel62
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 360000000, 7680, 4320, 120}, //HEVCHighTierLevel62
 
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 128000, 176, 144, 15},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1500000, 352, 288, 30},
-                // TODO (b/152576008) - Limit HEVC Encoder test to 512x512
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 3000000, 512, 512, 30},
-                //{MediaFormat.MIMETYPE_VIDEO_HEVC, 3000000, 640, 360, 30},
-                //{MediaFormat.MIMETYPE_VIDEO_HEVC, 6000000, 960, 540, 30},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 10000000, 1280, 720, 33},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 12000000, 2048, 1080, 30},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 2048, 1080, 60},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 25000000, 4096, 2160, 30},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 40000000, 4096, 2160, 60},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 60000000, 4096, 2160, 120},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 60000000, 8192, 4320, 30},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 120000000, 8192, 4320, 60},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, 240000000, 8192, 4320, 120},
-
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 1500000, 426, 240, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 3000000, 640, 360, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 6000000, 854, 480, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 10000000, 1280, 720, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 12000000, 1920, 1080, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 20000000, 1920, 1080, 60},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 30000000, 3840, 2160, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 40000000, 3840, 2160, 60},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 60000000, 3840, 2160, 120},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 60000000, 7680, 4320, 30},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 100000000, 7680, 4320, 60},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, 160000000, 7680, 4320, 120},
-
-                {MediaFormat.MIMETYPE_VIDEO_VP8, 512000, 176, 144, 20},
-                {MediaFormat.MIMETYPE_VIDEO_VP8, 512000, 480, 360, 20},
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 1500000, 426, 240, 30},  // AV1Level2
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 3000000, 640, 360, 30},  // AV1Level21
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 6000000, 854, 480, 30},  // AV1Level3
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 10000000, 1280, 720, 30},  // AV1Level31
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 12000000, 1920, 1080, 30},  // AV1Level4
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 20000000, 1920, 1080, 60},  // AV1Level41
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 30000000, 3840, 2160, 30},  // AV1Level5
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 40000000, 3840, 2160, 60},  // AV1Level51
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 60000000, 3840, 2160, 120},  // AV1Level52
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 60000000, 7680, 4320, 30},  // AV1Level6
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 100000000, 7680, 4320, 60},  // AV1Level61
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 160000000, 7680, 4320, 120},  // AV1Level62
         };
         final List<Object[]> argsList = new ArrayList<>();
-        final int[] maxBFrames = {0, 2};
         for (Object[] arg : exhaustiveArgsList) {
             final String mediaType = (String) arg[0];
-            boolean isVideo = mediaType.startsWith("video/");
-            final int br = (int) arg[1];
-            final int param1 = (int) arg[2];
-            final int param2 = (int) arg[3];
-            final int fps = (int) arg[4];
-            Object[] testArgs = new Object[3];
-            testArgs[0] = arg[0];
-            if (isVideo) {
-                for (int maxBframe : maxBFrames) {
-                    if (maxBframe != 0) {
-                        if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
-                                && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
-                            continue;
-                        }
-                    }
-                    testArgs[1] = getVideoEncoderCfgParams(mediaType, br, param1, param2, fps,
-                            COLOR_FormatYUV420Flexible, maxBframe,
-                            Objects.requireNonNull(PROFILE_SDR_MAP.get(mediaType)));
-                    testArgs[2] = String.format("%dkbps_%dx%d_%dfps_%s_%d-bframes", br / 1000,
-                            param1, param2, fps, colorFormatToString(COLOR_FormatYUV420Flexible, 8),
-                            maxBframe);
-                    argsList.add(testArgs);
-                }
-            } else {
-                testArgs[1] = getAudioEncoderCfgParams(mediaType, br, param1, param2,
-                        Objects.requireNonNull(PROFILE_SDR_MAP.get(mediaType)));
-                testArgs[2] = String.format("%dkbps_%dkHz_%dch", br / 1000, param1 / 1000, param2);
-                argsList.add(testArgs);
-            }
-
+            argsList.addAll(prepareTestArgs(arg,
+                    Objects.requireNonNull(PROFILE_SDR_MAP.get(mediaType)),
+                    COLOR_FormatYUV420Flexible));
             // P010 support was added in Android T, hence limit the following tests to Android
             // T and above
             if (IS_AT_LEAST_T && PROFILE_HLG_MAP.get(mediaType) != null) {
-                for (int maxBframe : maxBFrames) {
-                    if (maxBframe != 0) {
-                        if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)
-                                && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
-                            continue;
-                        }
-                    }
-                    testArgs = new Object[3];
-                    testArgs[0] = arg[0];
-                    testArgs[1] = getVideoEncoderCfgParams(mediaType, br, param1, param2, fps,
-                            COLOR_FormatYUVP010, maxBframe,
-                            Objects.requireNonNull(PROFILE_HLG_MAP.get(mediaType)));
-                    testArgs[2] = String.format("%dkbps_%dx%d_%dfps_%s_%d-bframes", br / 1000,
-                            param1, param2, fps, colorFormatToString(COLOR_FormatYUVP010, 10),
-                            maxBframe);
-                    argsList.add(testArgs);
-                }
+                argsList.addAll(prepareTestArgs(arg,
+                        Objects.requireNonNull(PROFILE_HLG_MAP.get(mediaType)),
+                        COLOR_FormatYUVP010));
             }
         }
+        final Object[][] mpeg4SimpleProfileArgsList = new Object[][]{
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 15},  // MPEG4Level0 @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 176, 144, 15},  // MPEG4Level0b @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 128, 96, 30},  // MPEG4Level1 @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 352, 288, 15},  // MPEG4Level2 @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 384000, 352, 288, 30},  // MPEG4Level3 @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 4000000, 640, 480, 30},  // MPEG4Level4a @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 8000000, 720, 576, 24},  // MPEG4Level5 @sp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 12000000, 1280, 720, 30},  // MPEG4Level6 @sp
+        };
+        for (Object[] arg : mpeg4SimpleProfileArgsList) {
+            argsList.addAll(prepareTestArgs(arg, new int[]{MPEG4ProfileSimple},
+                    COLOR_FormatYUV420Flexible));
+        }
+        final Object[][] mpeg4AdvSimpleProfileArgsList = new Object[][]{
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 176, 144, 30},  // MPEG4Level1 @ asp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 384000, 352, 288, 15},  // MPEG4Level2 @ asp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 768000, 352, 288, 30},  // MPEG4Level3 @ asp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 1500000, 352, 288, 30},  // MPEG4Level3b @ asp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 3000000, 704, 576, 15},  // MPEG4Level4 @ asp
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 8000000, 720, 576, 30},  // MPEG4Level5 @ asp
+        };
+        for (Object[] arg : mpeg4AdvSimpleProfileArgsList) {
+            argsList.addAll(prepareTestArgs(arg, new int[]{MPEG4ProfileAdvancedSimple},
+                    COLOR_FormatYUV420Flexible));
+        }
         return prepareParamList(argsList, isEncoder, needAudio, needVideo, false);
     }
 
@@ -306,601 +307,134 @@
                 new Pair<>(new int[]{AVCProfileBaseline}, AVCLevel3));
         PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
                 new Pair<>(new int[]{HEVCProfileMain}, HEVCMainTierLevel3));
-        PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_VP8,
-                new Pair<>(new int[]{VP8ProfileMain}, VP8Level_Version0));
         PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_VP9,
                 new Pair<>(new int[]{VP9Profile0}, VP9Level3));
     }
 
-    private static int getMinLevel(String mediaType, int width, int height, int frameRate,
-            int bitrate, int profile) {
-        switch (mediaType) {
-            case MediaFormat.MIMETYPE_VIDEO_AVC:
-                return getMinLevelAVC(width, height, frameRate, bitrate);
-            case MediaFormat.MIMETYPE_VIDEO_HEVC:
-                return getMinLevelHEVC(width, height, frameRate, bitrate);
-            case MediaFormat.MIMETYPE_VIDEO_H263:
-                return getMinLevelH263(width, height, frameRate, bitrate);
-            case MediaFormat.MIMETYPE_VIDEO_MPEG2:
-                return getMinLevelMPEG2(width, height, frameRate, bitrate);
-            case MediaFormat.MIMETYPE_VIDEO_MPEG4:
-                return getMinLevelMPEG4(width, height, frameRate, bitrate, profile);
-            // complex features disabled in VP8 Level/Version 0
-            case MediaFormat.MIMETYPE_VIDEO_VP8:
-                return VP8Level_Version0;
-            case MediaFormat.MIMETYPE_VIDEO_VP9:
-                return getMinLevelVP9(width, height, frameRate, bitrate);
-            case MediaFormat.MIMETYPE_VIDEO_AV1:
-                return getMinLevelAV1(width, height, frameRate, bitrate);
-            default:
-                return -1;
-        }
-    }
-
-    private static int getMinLevelAVC(int width, int height, int frameRate, int bitrate) {
-        class LevelLimitAVC {
-            private LevelLimitAVC(int level, int mbsPerSec, long mbs, int bitrate) {
-                this.level = level;
-                this.mbsPerSec = mbsPerSec;
-                this.mbs = mbs;
-                this.bitrate = bitrate;
-            }
-
-            private final int level;
-            private final int mbsPerSec;
-            private final long mbs;
-            private final int bitrate;
-        }
-        LevelLimitAVC[] limitsAVC = {
-                new LevelLimitAVC(AVCLevel1, 1485, 99, 64000),
-                new LevelLimitAVC(AVCLevel1b, 1485, 99, 128000),
-                new LevelLimitAVC(AVCLevel11, 3000, 396, 192000),
-                new LevelLimitAVC(AVCLevel12, 6000, 396, 384000),
-                new LevelLimitAVC(AVCLevel13, 11880, 396, 768000),
-                new LevelLimitAVC(AVCLevel2, 11880, 396, 2000000),
-                new LevelLimitAVC(AVCLevel21, 19800, 792, 4000000),
-                new LevelLimitAVC(AVCLevel22, 20250, 1620, 4000000),
-                new LevelLimitAVC(AVCLevel3, 40500, 1620, 10000000),
-                new LevelLimitAVC(AVCLevel31, 108000, 3600, 14000000),
-                new LevelLimitAVC(AVCLevel32, 216000, 5120, 20000000),
-                new LevelLimitAVC(AVCLevel4, 245760, 8192, 20000000),
-                new LevelLimitAVC(AVCLevel41, 245760, 8192, 50000000),
-                new LevelLimitAVC(AVCLevel42, 522240, 8704, 50000000),
-                new LevelLimitAVC(AVCLevel5, 589824, 22080, 135000000),
-                new LevelLimitAVC(AVCLevel51, 983040, 36864, 240000000),
-                new LevelLimitAVC(AVCLevel52, 2073600, 36864, 240000000),
-                new LevelLimitAVC(AVCLevel6, 4177920, 139264, 240000000),
-                new LevelLimitAVC(AVCLevel61, 8355840, 139264, 480000000),
-                new LevelLimitAVC(AVCLevel62, 16711680, 139264, 800000000),
-        };
-        int mbs = ((width + 15) / 16) * ((height + 15) / 16);
-        float mbsPerSec = mbs * frameRate;
-        for (LevelLimitAVC levelLimitsAVC : limitsAVC) {
-            if (mbs <= levelLimitsAVC.mbs && mbsPerSec <= levelLimitsAVC.mbsPerSec
-                    && bitrate <= levelLimitsAVC.bitrate) {
-                return levelLimitsAVC.level;
-            }
-        }
-        // if none of the levels suffice, select the highest level
-        return AVCLevel62;
-    }
-
-    private static int getMinLevelHEVC(int width, int height, int frameRate, int bitrate) {
-        class LevelLimitHEVC {
-            private LevelLimitHEVC(int level, int frameRate, long samples, int bitrate) {
-                this.level = level;
-                this.frameRate = frameRate;
-                this.samples = samples;
-                this.bitrate = bitrate;
-            }
-
-            private final int level;
-            private final int frameRate;
-            private final long samples;
-            private final int bitrate;
-        }
-        LevelLimitHEVC[] limitsHEVC = {
-                new LevelLimitHEVC(HEVCMainTierLevel1, 15, 36864, 128000),
-                new LevelLimitHEVC(HEVCMainTierLevel2, 30, 122880, 1500000),
-                new LevelLimitHEVC(HEVCMainTierLevel21, 30, 245760, 3000000),
-                new LevelLimitHEVC(HEVCMainTierLevel3, 30, 552960, 6000000),
-                new LevelLimitHEVC(HEVCMainTierLevel31, 30, 983040, 10000000),
-                new LevelLimitHEVC(HEVCMainTierLevel4, 30, 2228224, 12000000),
-                new LevelLimitHEVC(HEVCHighTierLevel4, 30, 2228224, 30000000),
-                new LevelLimitHEVC(HEVCMainTierLevel41, 60, 2228224, 20000000),
-                new LevelLimitHEVC(HEVCHighTierLevel41, 60, 2228224, 50000000),
-                new LevelLimitHEVC(HEVCMainTierLevel5, 30, 8912896, 25000000),
-                new LevelLimitHEVC(HEVCHighTierLevel5, 30, 8912896, 100000000),
-                new LevelLimitHEVC(HEVCMainTierLevel51, 60, 8912896, 40000000),
-                new LevelLimitHEVC(HEVCHighTierLevel51, 60, 8912896, 160000000),
-                new LevelLimitHEVC(HEVCMainTierLevel52, 120, 8912896, 60000000),
-                new LevelLimitHEVC(HEVCHighTierLevel52, 120, 8912896, 240000000),
-                new LevelLimitHEVC(HEVCMainTierLevel6, 30, 35651584, 60000000),
-                new LevelLimitHEVC(HEVCHighTierLevel6, 30, 35651584, 240000000),
-                new LevelLimitHEVC(HEVCMainTierLevel61, 60, 35651584, 120000000),
-                new LevelLimitHEVC(HEVCHighTierLevel61, 60, 35651584, 480000000),
-                new LevelLimitHEVC(HEVCMainTierLevel62, 120, 35651584, 240000000),
-                new LevelLimitHEVC(HEVCHighTierLevel62, 120, 35651584, 800000000),
-        };
-        int samples = width * height;
-        for (LevelLimitHEVC levelLimitsHEVC : limitsHEVC) {
-            if (samples <= levelLimitsHEVC.samples && frameRate <= levelLimitsHEVC.frameRate
-                    && bitrate <= levelLimitsHEVC.bitrate) {
-                return levelLimitsHEVC.level;
-            }
-        }
-        // if none of the levels suffice, select the highest level
-        return HEVCHighTierLevel62;
-    }
-
-    private static int getMinLevelH263(int width, int height, int frameRate, int bitrate) {
-        class LevelLimitH263 {
-            private LevelLimitH263(int level, int height, int width, int frameRate,
-                    int bitrate) {
-                this.level = level;
-                this.height = height;
-                this.width = width;
-                this.frameRate = frameRate;
-                this.bitrate = bitrate;
-            }
-
-            private final int level;
-            private final int height;
-            private final int width;
-            private final int frameRate;
-            private final int bitrate;
-        }
-        LevelLimitH263[] limitsH263 = {
-                new LevelLimitH263(H263Level10, 176, 144, 15, 64000),
-                new LevelLimitH263(H263Level45, 176, 144, 15, 128000),
-                new LevelLimitH263(H263Level20, 176, 144, 30, 128000),
-                new LevelLimitH263(H263Level20, 352, 288, 15, 128000),
-                new LevelLimitH263(H263Level30, 352, 288, 30, 384000),
-                new LevelLimitH263(H263Level40, 352, 288, 30, 2048000),
-                new LevelLimitH263(H263Level50, 352, 240, 60, 4096000),
-                new LevelLimitH263(H263Level50, 352, 288, 50, 4096000),
-                new LevelLimitH263(H263Level60, 720, 240, 60, 8192000),
-                new LevelLimitH263(H263Level60, 720, 288, 50, 8192000),
-                new LevelLimitH263(H263Level70, 720, 480, 60, 16384000),
-                new LevelLimitH263(H263Level70, 720, 576, 50, 16384000),
-        };
-        for (LevelLimitH263 levelLimitsH263 : limitsH263) {
-            if (height <= levelLimitsH263.height && width <= levelLimitsH263.width &&
-                    frameRate <= levelLimitsH263.frameRate && bitrate <= levelLimitsH263.bitrate) {
-                return levelLimitsH263.level;
-            }
-        }
-        // if none of the levels suffice, select the highest level
-        return H263Level70;
-    }
-
-    private static int getMinLevelVP9(int width, int height, int frameRate, int bitrate) {
-        class LevelLimitVP9 {
-            private LevelLimitVP9(int level, long sampleRate, int size, int breadth,
-                    int bitrate) {
-                this.level = level;
-                this.sampleRate = sampleRate;
-                this.size = size;
-                this.breadth = breadth;
-                this.bitrate = bitrate;
-            }
-
-            private final int level;
-            private final long sampleRate;
-            private final int size;
-            private final int breadth;
-            private final int bitrate;
-        }
-        LevelLimitVP9[] limitsVP9 = {
-                new LevelLimitVP9(VP9Level1, 829440, 36864, 512, 200000),
-                new LevelLimitVP9(VP9Level11, 2764800, 73728, 768, 800000),
-                new LevelLimitVP9(VP9Level2, 4608000, 122880, 960, 1800000),
-                new LevelLimitVP9(VP9Level21, 9216000, 245760, 1344, 3600000),
-                new LevelLimitVP9(VP9Level3, 20736000, 552960, 2048, 7200000),
-                new LevelLimitVP9(VP9Level31, 36864000, 983040, 2752, 12000000),
-                new LevelLimitVP9(VP9Level4, 83558400, 2228224, 4160, 18000000),
-                new LevelLimitVP9(VP9Level41, 160432128, 2228224, 4160, 30000000),
-                new LevelLimitVP9(VP9Level5, 311951360, 8912896, 8384, 60000000),
-                new LevelLimitVP9(VP9Level51, 588251136, 8912896, 8384, 120000000),
-                new LevelLimitVP9(VP9Level52, 1176502272, 8912896, 8384, 180000000),
-                new LevelLimitVP9(VP9Level6, 1176502272, 35651584, 16832, 180000000),
-                new LevelLimitVP9(VP9Level61, 2353004544L, 35651584, 16832, 240000000),
-                new LevelLimitVP9(VP9Level62, 4706009088L, 35651584, 16832, 480000000),
-        };
-        int size = width * height;
-        int sampleRate = size * frameRate;
-        int breadth = Math.max(width, height);
-        for (LevelLimitVP9 levelLimitsVP9 : limitsVP9) {
-            if (sampleRate <= levelLimitsVP9.sampleRate && size <= levelLimitsVP9.size &&
-                    breadth <= levelLimitsVP9.breadth && bitrate <= levelLimitsVP9.bitrate) {
-                return levelLimitsVP9.level;
-            }
-        }
-        // if none of the levels suffice, select the highest level
-        return VP9Level62;
-    }
-
-    private static int getMinLevelMPEG2(int width, int height, int frameRate, int bitrate) {
-        class LevelLimitMPEG2 {
-            private LevelLimitMPEG2(int level, long sampleRate, int width, int height,
-                    int frameRate, int bitrate) {
-                this.level = level;
-                this.sampleRate = sampleRate;
-                this.width = width;
-                this.height = height;
-                this.frameRate = frameRate;
-                this.bitrate = bitrate;
-            }
-
-            private final int level;
-            private final long sampleRate;
-            private final int width;
-            private final int height;
-            private final int frameRate;
-            private final int bitrate;
-        }
-        // main profile limits, higher profiles will also support selected level
-        LevelLimitMPEG2[] limitsMPEG2 = {
-                new LevelLimitMPEG2(MPEG2LevelLL, 3041280, 352, 288, 30, 4000000),
-                new LevelLimitMPEG2(MPEG2LevelML, 10368000, 720, 576, 30, 15000000),
-                new LevelLimitMPEG2(MPEG2LevelH14, 47001600, 1440, 1088, 60, 60000000),
-                new LevelLimitMPEG2(MPEG2LevelHL, 62668800, 1920, 1088, 60, 80000000),
-                new LevelLimitMPEG2(MPEG2LevelHP, 125337600, 1920, 1088, 60, 80000000),
-        };
-        int size = width * height;
-        int sampleRate = size * frameRate;
-        for (LevelLimitMPEG2 levelLimitsMPEG2 : limitsMPEG2) {
-            if (sampleRate <= levelLimitsMPEG2.sampleRate && width <= levelLimitsMPEG2.width &&
-                    height <= levelLimitsMPEG2.height && frameRate <= levelLimitsMPEG2.frameRate &&
-                    bitrate <= levelLimitsMPEG2.bitrate) {
-                return levelLimitsMPEG2.level;
-            }
-        }
-        // if none of the levels suffice, select the highest level
-        return MPEG2LevelHP;
-    }
-
-    private static int getMinLevelMPEG4(int width, int height, int frameRate, int bitrate,
-            int profile) {
-        class LevelLimitMPEG4 {
-            private LevelLimitMPEG4(int profile, int level, long sampleRate, int width,
-                    int height, int frameRate, int bitrate) {
-                this.profile = profile;
-                this.level = level;
-                this.sampleRate = sampleRate;
-                this.width = width;
-                this.height = height;
-                this.frameRate = frameRate;
-                this.bitrate = bitrate;
-            }
-
-            private final int profile;
-            private final int level;
-            private final long sampleRate;
-            private final int width;
-            private final int height;
-            private final int frameRate;
-            private final int bitrate;
-        }
-        // simple profile limits, higher profiles will also support selected level
-        LevelLimitMPEG4[] limitsMPEG4 = {
-                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level0, 380160, 176, 144, 15, 64000),
-                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level1, 380160, 176, 144, 30, 64000),
-                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level0b, 380160, 176, 144, 15, 128000),
-                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level2, 1520640, 352, 288, 30, 128000),
-                new LevelLimitMPEG4(MPEG4ProfileSimple, MPEG4Level3, 3041280, 352, 288, 30, 384000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileSimple, MPEG4Level4a, 9216000, 640, 480, 30, 4000000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileSimple, MPEG4Level5, 10368000, 720, 576, 30, 8000000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileSimple, MPEG4Level6, 27648000, 1280, 720, 30, 12000000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileAdvancedSimple, MPEG4Level1, 760320, 176, 144, 30, 128000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileAdvancedSimple, MPEG4Level2, 1520640, 352, 288, 30, 384000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileAdvancedSimple, MPEG4Level3, 3041280, 352, 288, 30, 768000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileAdvancedSimple, MPEG4Level3b, 3041280, 352, 288, 30, 1500000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileAdvancedSimple, MPEG4Level4, 3041280, 704, 576, 30, 3000000),
-                new LevelLimitMPEG4(
-                        MPEG4ProfileAdvancedSimple, MPEG4Level5, 3041280, 720, 576, 30, 8000000),
-        };
-        int size = width * height;
-        int sampleRate = size * frameRate;
-        for (LevelLimitMPEG4 levelLimitsMPEG4 : limitsMPEG4) {
-            if (((profile & (MPEG4ProfileAdvancedSimple | MPEG4ProfileSimple)) != 0) &&
-                    profile != levelLimitsMPEG4.profile) continue;
-            if (sampleRate <= levelLimitsMPEG4.sampleRate && width <= levelLimitsMPEG4.width &&
-                    height <= levelLimitsMPEG4.height && frameRate <= levelLimitsMPEG4.frameRate &&
-                    bitrate <= levelLimitsMPEG4.bitrate) {
-                return levelLimitsMPEG4.level;
-            }
-        }
-        // if none of the levels suffice, select the highest level
-        return MPEG4Level6;
-    }
-
-    private static int getMinLevelAV1(int width, int height, int frameRate, int bitrate) {
-        class LevelLimitAV1 {
-            private LevelLimitAV1(int level, int size, int width, int height, long sampleRate,
-                    int bitrate) {
-                this.level = level;
-                this.size = size;
-                this.width = width;
-                this.height = height;
-                this.sampleRate = sampleRate;
-                this.bitrate = bitrate;
-            }
-
-            private final int level;
-            private final int size;
-            private final int width;
-            private final int height;
-            private final long sampleRate;
-            private final int bitrate;
-        }
-        // taking bitrate from main profile, will also be supported by high profile
-        LevelLimitAV1[] limitsAV1 = {
-                new LevelLimitAV1(AV1Level2, 147456, 2048, 1152, 4423680, 1500000),
-                new LevelLimitAV1(AV1Level21, 278784, 2816, 1584, 8363520, 3000000),
-                new LevelLimitAV1(AV1Level3, 665856, 4352, 2448, 19975680, 6000000),
-                new LevelLimitAV1(AV1Level31, 1065024, 5504, 3096, 31950720, 10000000),
-                new LevelLimitAV1(AV1Level4, 2359296, 6144, 3456, 70778880, 12000000),
-                new LevelLimitAV1(AV1Level41, 2359296, 6144, 3456, 141557760, 20000000),
-                new LevelLimitAV1(AV1Level5, 8912896, 8192, 4352, 267386880, 30000000),
-                new LevelLimitAV1(AV1Level51, 8912896, 8192, 4352, 534773760, 40000000),
-                new LevelLimitAV1(AV1Level52, 8912896, 8192, 4352, 1069547520, 60000000),
-                new LevelLimitAV1(AV1Level53, 8912896, 8192, 4352, 1069547520, 60000000),
-                new LevelLimitAV1(AV1Level6, 35651584, 16384, 8704, 1069547520, 60000000),
-                new LevelLimitAV1(AV1Level61, 35651584, 16384, 8704, 2139095040, 100000000),
-                new LevelLimitAV1(AV1Level62, 35651584, 16384, 8704, 4278190080L, 160000000),
-                new LevelLimitAV1(AV1Level63, 35651584, 16384, 8704, 4278190080L, 160000000),
-        };
-        int size = width * height;
-        int sampleRate = size * frameRate;
-        for (LevelLimitAV1 levelLimitsAV1 : limitsAV1) {
-            if (size <= levelLimitsAV1.size && width <= levelLimitsAV1.width &&
-                    height <= levelLimitsAV1.height && sampleRate <= levelLimitsAV1.sampleRate &&
-                    bitrate <= levelLimitsAV1.bitrate) {
-                return levelLimitsAV1.level;
-            }
-        }
-        // if none of the levels suffice or high profile, select the highest level
-        return AV1Level73;
-    }
-
-    private int getAacProfile(MediaFormat format) {
-        int aacProfile = format.getInteger(MediaFormat.KEY_AAC_PROFILE, -1);
-        int profile = format.getInteger(MediaFormat.KEY_PROFILE, -1);
-
-        if (aacProfile != -1 && profile != -1) {
-            assertEquals(String.format("aac-profile :- %d and profile :- %d are different.",
-                    aacProfile, profile), aacProfile, profile);
-            return aacProfile;
-        } else if (aacProfile != -1) {
-            return aacProfile;
-        } else if (profile != -1) {
-            return profile;
+    void checkIfTrackFormatIsOk(MediaFormat trackFormat) {
+        assertEquals("Input media type and extracted media type are not identical " + mTestEnv
+                        + mTestConfig, mActiveEncCfg.mMediaType,
+                trackFormat.getString(MediaFormat.KEY_MIME));
+        if (mIsVideo) {
+            assertEquals("Input width and extracted width are not same " + mTestEnv + mTestConfig,
+                    mActiveEncCfg.mWidth, getWidth(trackFormat));
+            assertEquals("Input height and extracted height are not same " + mTestEnv + mTestConfig,
+                    mActiveEncCfg.mHeight, getHeight(trackFormat));
         } else {
-            Log.e(LOG_TAG, "format doesn't contain either KEY_AAC_PROFILE or KEY_PROFILE");
-            return -1;
+            int expSampleRate = mActiveEncCfg.mProfile != AACObjectHE ? mActiveEncCfg.mSampleRate
+                    : mActiveEncCfg.mSampleRate / 2;
+            int expChCount = mActiveEncCfg.mProfile != AACObjectHE_PS ? mActiveEncCfg.mChannelCount
+                    : mActiveEncCfg.mChannelCount / 2;
+            assertEquals("Input sample rate and extracted sample rate are not same " + mTestEnv
+                            + mTestConfig, expSampleRate,
+                    trackFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
+            assertEquals("Input channe count and extracted channel count are not same " + mTestEnv
+                            + mTestConfig, expChCount,
+                    trackFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
         }
     }
 
-    @Override
-    public boolean isFormatSimilar(MediaFormat inpFormat, MediaFormat outFormat) {
-        if (!super.isFormatSimilar(inpFormat, outFormat)) {
-            Log.e(LOG_TAG, "Basic channel-rate/resolution comparisons failed");
-            return false;
-        }
-        String inpMediaType = inpFormat.getString(MediaFormat.KEY_MIME);
-        String outMediaType = outFormat.getString(MediaFormat.KEY_MIME);
-        assertEquals(String.format("input mediaType :- %s and output mediaType :- %s are "
-                        + "different.", inpMediaType, outMediaType), inpMediaType, outMediaType);
-        if (outMediaType.startsWith("audio/")) {
-            if (outFormat.getString(MediaFormat.KEY_MIME).equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-                int inputProfileKey, outputProfileKey;
-                outputProfileKey = getAacProfile(outFormat);
-                inputProfileKey = getAacProfile(inpFormat);
-                if (outputProfileKey != inputProfileKey) {
-                    Log.e(LOG_TAG, "aac-profile in output " + outputProfileKey +
-                            " doesn't match configured input " + inputProfileKey);
-                    return false;
+    private boolean shallSupportProfileAndLevel(EncoderConfigParams cfg) {
+        Pair<int[], Integer> cddProfileLevel =
+                Objects.requireNonNull(PROFILE_LEVEL_CDD.get(cfg.mMediaType));
+        int[] profileCdd = cddProfileLevel.first;
+        int levelCdd = cddProfileLevel.second;
+        for (int cddProfile : profileCdd) {
+            if (cfg.mProfile == cddProfile) {
+                if (!cfg.mIsAudio) {
+                    if (cfg.mLevel <= levelCdd) {
+                        if (cfg.mMediaType.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)
+                                && cfg.mLevel != MediaCodecInfo.CodecProfileLevel.H263Level45
+                                && cfg.mLevel > MediaCodecInfo.CodecProfileLevel.H263Level10) {
+                            continue;
+                        }
+                    } else {
+                        continue;
+                    }
                 }
+                return true;
             }
-        } else if (outMediaType.startsWith("video/")) {
-            if (!outFormat.containsKey(MediaFormat.KEY_PROFILE)) {
-                Log.e(LOG_TAG, "Output format doesn't contain profile key");
-                //TODO (b/151398466)
-                if (true) return true;
-                return false;
-            }
-            if (!outFormat.containsKey(MediaFormat.KEY_LEVEL)) {
-                Log.e(LOG_TAG, "Output format doesn't contain level key");
-                //TODO (b/151398466)
-                if (true) return true;
-                return false;
-            }
-            if (!inpFormat.containsKey(MediaFormat.KEY_PROFILE)) {
-                Log.e(LOG_TAG, "Input format doesn't contain profile key");
-                return false;
-            }
-            if (!inpFormat.containsKey(MediaFormat.KEY_LEVEL)) {
-                Log.e(LOG_TAG, "Input format doesn't contain level key");
-                return false;
-            }
-            if (outFormat.getInteger(MediaFormat.KEY_PROFILE)
-                    != inpFormat.getInteger(MediaFormat.KEY_PROFILE)) {
-                Log.e(LOG_TAG, "profile in output doesn't match configured input");
-                return false;
-            }
-            if (outFormat.getInteger(MediaFormat.KEY_LEVEL)
-                    != inpFormat.getInteger(MediaFormat.KEY_LEVEL)) {
-                Log.e(LOG_TAG, "level key in output doesn't match configured input");
-                return false;
-            }
-        } else {
-            Log.w(LOG_TAG, "non media mediaType:" + outMediaType);
         }
-        return true;
+        return false;
     }
 
     /**
-     * @see EncoderProfileLevelTest
-     * Besides the above, the test muxes the encoder output in all supported container formats
-     * and checks if muxers and extractors on device are signalling profile/level information
-     * correctly
+     * Check description of class {@link EncoderProfileLevelTest}
      */
     @CddTest(requirements = {"2.2.2/5.1/H-0-3", "2.2.2/5.1/H-0-4", "2.2.2/5.1/H-0-5", "5/C-0-3",
-            "5.2.1/C-1-1", "5.2.2/C-2-1", "5.2.3/C-2-1", "5.2.4/C-1-2",
-            "5.2.5/C-1-1"})
+            "5.2.1/C-1-1", "5.2.2/C-1-1", "5.2.4/C-1-2", "5.2.5/C-1-1"})
     @ApiTest(apis = {"android.media.MediaFormat#KEY_PROFILE",
             "android.media.MediaFormat#KEY_AAC_PROFILE",
             "android.media.MediaFormat#KEY_LEVEL"})
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testValidateProfileLevel() throws IOException, InterruptedException {
-        if (mEncCfgParams[0].mInputBitDepth != 8) {
+        if (mIsVideo && mEncCfgParams[0].mInputBitDepth != 8) {
             Assume.assumeTrue(mCodecName + " doesn't support " + colorFormatToString(
                             mEncCfgParams[0].mColorFormat, mEncCfgParams[0].mInputBitDepth),
                     hasSupportForColorFormat(mCodecName, mMediaType,
-                                             mEncCfgParams[0].mColorFormat));
+                            mEncCfgParams[0].mColorFormat));
         }
         boolean cddSupportedMediaType = PROFILE_LEVEL_CDD.get(mMediaType) != null;
-        int[] profileCdd = new int[0];
-        int levelCdd = 0;
-        if (cddSupportedMediaType) {
-            Pair<int[], Integer> cddProfileLevel = PROFILE_LEVEL_CDD.get(mMediaType);
-            profileCdd = cddProfileLevel.first;
-            levelCdd = cddProfileLevel.second;
-        }
 
         {
             mActiveRawRes = EncoderInput.getRawResource(mEncCfgParams[0]);
             assertNotNull("no raw resource found for testing config : "
-                    + mActiveEncCfg + mTestConfig + mTestEnv, mActiveRawRes);
+                    + mEncCfgParams[0] + mTestConfig + mTestEnv, mActiveRawRes);
             setUpSource(mActiveRawRes.mFileName);
             mSaveToMem = true;
+            mMuxOutput = true;
             mOutputBuff = new OutputManager();
             mCodec = MediaCodec.createByCodecName(mCodecName);
             MediaCodecInfo.CodecCapabilities codecCapabilities =
                     mCodec.getCodecInfo().getCapabilitiesForType(mMediaType);
+            int configsTested = 0;
             for (EncoderConfigParams cfg : mEncCfgParams) {
                 mActiveEncCfg = cfg;
                 MediaFormat format = cfg.getFormat();
                 if (!codecCapabilities.isFormatSupported(format)) {
                     if (cddSupportedMediaType) {
-                        boolean shallSupportProfileLevel = false;
-                        if (mIsAudio) {
-                            for (int cddProfile : profileCdd) {
-                                if (cfg.mProfile == cddProfile) {
-                                    shallSupportProfileLevel = true;
-                                    break;
-                                }
-                            }
-                        } else if (cfg.mProfile == profileCdd[0] && cfg.mLevel <= levelCdd) {
-                            shallSupportProfileLevel = true;
-                        }
-                        if (shallSupportProfileLevel) {
+                        if (shallSupportProfileAndLevel(cfg)) {
                             ArrayList<MediaFormat> formats = new ArrayList<>();
                             formats.add(format);
-                            assertFalse(String.format("No components present on the device supports"
-                                    + " cdd required profile:- %d, level:- %d, encode format:- %s",
-                                    cfg.mProfile, cfg.mLevel, format),
-                                    selectCodecs(mMediaType, formats, null, false).isEmpty());
+                            assertFalse("No components present on the device supports cdd "
+                                    + "required encode format:- " + format + mTestConfig + mTestEnv,
+                                    selectCodecs(mMediaType, formats, null, true).isEmpty());
                         }
                         Log.d(LOG_TAG, mCodecName + " doesn't support format: " + format);
                     }
                     continue;
                 }
 
-                // Verify if device has an equivalent decoder for the current format
-                {
-                    ArrayList<MediaFormat> formatList = new ArrayList<>();
-                    formatList.add(format);
-                    assertTrue("Device advertises support for encoding " + format
-                                    + " but cannot decode it. \n" + mTestConfig + mTestEnv,
-                            selectCodecs(mMediaType, formatList, null, false).size() > 0);
-                }
-
                 mOutputBuff.reset();
                 configureCodec(format, false, true, true);
                 mCodec.start();
                 doWork(5);
                 queueEOS();
                 waitForAllOutputs();
-                MediaFormat outFormat = mCodec.getOutputFormat();
-                /* TODO(b/147348711) */
-                if (false) mCodec.stop();
-                else mCodec.reset();
+                mCodec.reset();
 
-                // TODO (b/151398466)
-                if (mMediaType.equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-                    Assume.assumeTrue("neither KEY_AAC_PROFILE nor KEY_PROFILE are present",
-                            outFormat.containsKey(MediaFormat.KEY_AAC_PROFILE) ||
-                                    outFormat.containsKey(MediaFormat.KEY_PROFILE));
-                } else {
-                    Assume.assumeTrue("KEY_PROFILE not present",
-                            outFormat.containsKey(MediaFormat.KEY_PROFILE));
-                    Assume.assumeTrue(outFormat.containsKey(MediaFormat.KEY_LEVEL));
-                }
-                // TODO (b/166300446) avc mediaType fails validation
-                if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
-                    Log.w(LOG_TAG, "Skip validation for mediaType = " + mMediaType);
-                    continue;
-                }
-                // TODO (b/166305723) hevc mediaType fails validation
-                if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
-                    Log.w(LOG_TAG, "Skip validation for mediaType = " + mMediaType);
-                    continue;
-                }
-                // TODO (b/166300448) h263 and mpeg4 mediaTypes fails validation
-                if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_H263)
-                        || mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
-                    Log.w(LOG_TAG, "Skip validation for mediaType = " + mMediaType);
-                    continue;
-                }
-                // TODO (b/184889671) aac for profile AACObjectHE fails validation
-                // TODO (b/184890155) aac for profile AACObjectLD, AACObjectELD fails validation
-                if (mMediaType.equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-                    if (cfg.mProfile == AACObjectHE || cfg.mProfile == AACObjectELD
-                            || cfg.mProfile == AACObjectLD) {
-                        Log.w(LOG_TAG, "Skip validation for mediaType = " + mMediaType
-                                + " profile " + cfg.mProfile);
-                        continue;
-                    }
-                }
-                String msg = String.format("Configured input format and received output format are "
-                        + "not similar. \nConfigured Input format is :- %s \nReceived Output "
-                        + "format is :- %s \n", format, outFormat);
-                assertTrue(msg + mTestConfig + mTestEnv, isFormatSimilar(format, outFormat));
+                MediaFormat trackFormat = validateProfileAndLevel();
 
-                for (int muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
-                     muxerFormat <= MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST; muxerFormat++) {
-                    if (!isMediaTypeContainerPairValid(mMediaType, muxerFormat)) continue;
-                    ByteBuffer mBuff = mOutputBuff.getBuffer();
-                    String tmpPath = getTempFilePath((cfg.mInputBitDepth == 10) ? "10bit" : "");
-                    muxOutput(tmpPath, muxerFormat, outFormat, mBuff, mInfoList);
-                    MediaExtractor extractor = new MediaExtractor();
-                    extractor.setDataSource(tmpPath);
-                    assertEquals("Should be only 1 track \n" + mTestConfig + mTestEnv, 1,
-                            extractor.getTrackCount());
-                    MediaFormat extractedFormat = extractor.getTrackFormat(0);
-                    if (!isFormatSimilar(outFormat, extractedFormat)) {
-                        msg = " Input format and extracted format are not similar. "
-                                + "\n Muxer input format :- " + outFormat
-                                + "\n Extracted format :- " + extractedFormat
-                                + "\n Muxer writer :- " + muxerFormat + "\n" + mTestConfig
-                                + mTestEnv;
-                        fail(msg);
-                    }
-                    extractor.release();
-                    new File(tmpPath).delete();
+                deleteMuxedFile();
+
+                // validate extracted format for mandatory keys
+                if (trackFormat != null) checkIfTrackFormatIsOk(trackFormat);
+
+                // Verify if device has an equivalent decoder for the current format
+                ArrayList<MediaFormat> formatList = new ArrayList<>();
+                if (mProfileLevel != null && mProfileLevel.second != -1
+                        && cfg.mLevel != mProfileLevel.second) {
+                    format.setInteger(MediaFormat.KEY_LEVEL, mProfileLevel.second);
                 }
+                formatList.add(format);
+                assertTrue("Device advertises support for encoding " + format + " but cannot"
+                                + " decode it. \n" + mTestConfig + mTestEnv,
+                        selectCodecs(mMediaType, formatList, null, false).size() > 0);
+                configsTested++;
             }
             mCodec.release();
+            Assume.assumeTrue("skipping test, formats not supported by component",
+                    configsTested > 0);
         }
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/ExtractorTest.java b/tests/media/src/android/mediav2/cts/ExtractorTest.java
index 216a7be..2458cb3 100644
--- a/tests/media/src/android/mediav2/cts/ExtractorTest.java
+++ b/tests/media/src/android/mediav2/cts/ExtractorTest.java
@@ -781,7 +781,7 @@
         @Rule
         public TestName testName = new TestName();
 
-        @Parameterized.Parameters(name = "{index}({0})")
+        @Parameterized.Parameters(name = "{index}_{0}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     {MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
@@ -1361,7 +1361,7 @@
             mTestFile = testFile;
         }
 
-        @Parameterized.Parameters(name = "{index}({0})")
+        @Parameterized.Parameters(name = "{index}_{0}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     {MediaFormat.MIMETYPE_AUDIO_FLAC,
@@ -1443,7 +1443,7 @@
             mHCh = hCh;
         }
 
-        @Parameterized.Parameters(name = "{index}({0})")
+        @Parameterized.Parameters(name = "{index}_{0}")
         public static Collection<Object[]> input() {
             // mediaType, clips, profile, level, width/sample rate, height/channel count
             List<Object[]> exhaustiveArgsList = new ArrayList<>();
diff --git a/tests/media/src/android/mediav2/cts/MuxerTest.java b/tests/media/src/android/mediav2/cts/MuxerTest.java
index 2d08265..0dac0a8 100644
--- a/tests/media/src/android/mediav2/cts/MuxerTest.java
+++ b/tests/media/src/android/mediav2/cts/MuxerTest.java
@@ -425,7 +425,7 @@
             new File(mOutPath).delete();
         }
 
-        @Parameterized.Parameters(name = "{index}({3})")
+        @Parameterized.Parameters(name = "{index}_{3}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "bbb_cif_768kbps_30fps_avc.mp4",
@@ -731,7 +731,7 @@
             new File(mOutPath).delete();
         }
 
-        @Parameterized.Parameters(name = "{index}({3})")
+        @Parameterized.Parameters(name = "{index}_{3}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     // audio, video are 3 sec
@@ -865,7 +865,7 @@
             new File(mOutPath).delete();
         }
 
-        @Parameterized.Parameters(name = "{index}({3})")
+        @Parameterized.Parameters(name = "{index}_{3}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
@@ -978,7 +978,7 @@
             new File(mOutPath).delete();
         }
 
-        @Parameterized.Parameters(name = "{index}({3})")
+        @Parameterized.Parameters(name = "{index}_{3}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
@@ -1090,7 +1090,7 @@
         private native boolean nativeTestSimpleAppend(String srcPath, String outPath,
                 String mediaType, String selector);
 
-        @Parameterized.Parameters(name = "{index}({2})")
+        @Parameterized.Parameters(name = "{index}_{2}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     // Video Codecs
@@ -1250,7 +1250,7 @@
             return result;
         }
 
-        @Parameterized.Parameters(name = "{index}({0})")
+        @Parameterized.Parameters(name = "{index}_{0}")
         public static Collection<Object[]> input() {
             return Arrays.asList(new Object[][]{
                     // Video
diff --git a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
index 4888d03..1ec8981 100644
--- a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
@@ -108,7 +108,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java
index 7fa48a7..6ee7e01 100644
--- a/tests/media/src/android/mediav2/cts/WorkDir.java
+++ b/tests/media/src/android/mediav2/cts/WorkDir.java
@@ -24,6 +24,6 @@
  */
 class WorkDir extends WorkDirBase {
     static final String getMediaDirString() {
-        return getMediaDirString("CtsMediaV2TestCases-3.2");
+        return getMediaDirString("CtsMediaV2TestCases-3.4");
     }
 }
diff --git a/tests/mediapc/AndroidTest.xml b/tests/mediapc/AndroidTest.xml
index 2a2bfab..f3e24f8 100644
--- a/tests/mediapc/AndroidTest.xml
+++ b/tests/mediapc/AndroidTest.xml
@@ -39,7 +39,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-2.1" />
+        <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-2.2" />
         <option name="dynamic-config-module" value="CtsMediaPerformanceClassTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/mediapc/DynamicConfig.xml b/tests/mediapc/DynamicConfig.xml
index d1a7b1f..c9e3d34 100644
--- a/tests/mediapc/DynamicConfig.xml
+++ b/tests/mediapc/DynamicConfig.xml
@@ -1,6 +1,6 @@
 <dynamicConfig>
     <entry key="media_files_url">
-      <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-2.1.zip</value>
+      <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-2.2.zip</value>
     </entry>
 </dynamicConfig>
 
diff --git a/tests/mediapc/README.md b/tests/mediapc/README.md
index d212c32..82d701b 100644
--- a/tests/mediapc/README.md
+++ b/tests/mediapc/README.md
@@ -1,7 +1,7 @@
 ## Media Performance Class CTS Tests
 Current folder comprises of files necessary for testing media performance class.
 
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-2.1.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-2.2.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
 
 ### Commands
 #### To run all tests in CtsMediaPerformanceClassTestCases
diff --git a/tests/mediapc/common/README.md b/tests/mediapc/common/README.md
new file mode 100644
index 0000000..77f1de8
--- /dev/null
+++ b/tests/mediapc/common/README.md
@@ -0,0 +1,181 @@
+# Writing an MPC Test
+
+Using
+[this CL](https://android-review.googlesource.com/c/platform/cts/+/2128521) as a
+guide focusing on requirement
+[8.2/H-1-1](https://source.android.com/docs/compatibility/13/android-13-cdd#2274_performance):
+
+-   R: MUST ensure a sequential write performance of at least 100MB/s.
+-   S and Tiramisu: MUST ensure a sequential write performance of at least
+    125MB/s.
+
+## Define Requirements
+
+### Define Constants Under RequirementConstants
+
+For our requirement,
+[8.2/H-1-1](https://source.android.com/docs/compatibility/13/android-13-cdd#2274_performance),
+we have one required measurement, so we will create one constant,
+`FILESYSTEM_IO_RATE`, to track that. This constant eventually will make its way
+to the internal cts_media_performance_class_test_metrics.proto, so the
+string-value we choose for it needs to structured like a proto field name and
+should include units at the end:
+
+```
+public static final String FILESYSTEM_IO_RATE = "filesystem_io_rate_mbps";
+```
+
+Additionally, we may need to create a new BiPredicate for our requirement. The
+BiPredicate defines the operator to test measurements for our requirement with.
+For our case, we want to test if an I/O rate is at or above a certain value, so
+we will use a GTE operator. We will additionally be storing I/O rates as
+doubles, leading us to define the BiPredicate DOUBLE_GTE:
+
+```
+public static final BiPredicate<Double, Double> DOUBLE_GTE = RequirementConstants.gte();
+```
+
+### Define Requirement Class Under PerformanceClassEvaluator
+
+In PerformanceClassEvaluator.java, we will define a new requirement class. This
+class should be defined as nested class under PerformanceClassEvaluator:
+
+```
+// used for requirements [8.2/H-1-1], [8.2/H-1-2], [8.2/H-1-3], [8.2/H-1-4]
+public static class FileSystemRequirement extends Requirement {
+
+  private static final String TAG = FileSystemRequirement.class.getSimpleName();
+
+  ...
+
+}
+```
+
+#### Define Constructor
+
+The constructors for requirement classes are very standardized. They are always
+private; they always take in two inputs: `String id, RequiredMeasurement<?> ...
+reqs`; and they always contain one line: `super(id, reqs)`:
+
+```
+private FileSystemRequirement(String id, RequiredMeasurement<?> ... reqs) {
+  super(id, reqs);
+}
+```
+
+#### Define Set Measured Value Method(s)
+
+Requirement classes need to define a method for each required measurement. These
+methods always contain one line: a function call to Requirement’s
+`setMeausredValue` method. For
+[8.2/H-1-1](https://source.android.com/docs/compatibility/13/android-13-cdd#2274_performance),
+we only have one required measurement so only need to make one method for it:
+
+```
+/**
+ * Set the Filesystem I/O Rate in MB/s.
+ */
+public void setFilesystemIoRate(double filesystemIoRate) {
+  this.setMeasuredValue(RequirementConstants.FILESYSTEM_IO_RATE, filesystemIoRate);
+}
+```
+
+#### Define Create Method
+
+The last thing we need to make for our requirement class is a create method.
+This method defines each of the required measurements. Each
+RequiredMeasurement.java is created through a builder and defining the
+following:
+
+*   The datatype of the measurement. This is during the call to the
+    RequiredMeasurement’s builder function, ex: `<Double>builder()`
+*   The ID for the measurement. This is the String constant we defined earlier.
+*   The predicate for the measurement. This is the BiPredicate we defined
+    earlier.
+*   A required value for each achievable performance class. For example, using
+    the GTE a BiPredicate:
+    *   `addRequiredValue(Build.VERSION_CODES.R, 100.0)` says that if a
+        requirement measurement is greater than or equal to to 100, the device
+        makes performance class R
+    *   `addRequiredValue(Build.VERSION_CODES.TIRAMISU, 125.0)` says that if a
+        requirement measurement is greater than or equal to to 125, the device
+        makes performance class Tiramisu
+
+Note: if a device meets multiple performance classes for a requirement, the
+system automatically chooses to record the higher classification
+
+For requirement
+[8.2/H-1-1](https://source.android.com/docs/compatibility/13/android-13-cdd#2274_performance)
+we define the following create method:
+
+```
+/**
+ * [8.2/H-1-1] MUST ensure a sequential write performance of
+ * at least 100(R) / 125(S & T) MB/s.
+ */
+public static FileSystemRequirement createR8_2__H_1_1() {
+  RequiredMeasurement<Double> filesystem_io_rate =
+      RequiredMeasurement.<Double>builder()
+      .setId(RequirementConstants.FILESYSTEM_IO_RATE)
+      .setPredicate(RequirementConstants.DOUBLE_GTE)
+      .addRequiredValue(Build.VERSION_CODES.R, 100.0)
+      .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 125.0)
+      .build();
+
+  return new FileSystemRequirement(RequirementConstants.R8_2__H_1_1,
+      filesystem_io_rate);
+}
+```
+
+Note: a requirement class can be and often is used for multiple requirements. If
+so, a create method must be defined for each.
+
+#### Define Add Method at the Bottom of PerformanceClassEvaluator
+
+After all of that we just need to define an add method at the bottom of
+PerformacneClassEvaluator for our requirement. All it does is call
+PerformanceClassEvaluator’s `addRequirement` method using the create method we
+defined earlier.
+
+```
+public FileSystemRequirement addR8_2__H_1_1() {
+  return this.addRequirement(FileSystemRequirement.createR8_2__H_1_1());
+}
+```
+
+## Update Test to Report Data Using PerformanceClassEvaluator
+
+Now that we have a requirement defined we just need to update our test to use
+PerformanceClassEvaluator.
+
+First we need to add the following to our test class: @Rule public final
+TestName mTestName = new TestName();
+
+Next we will create the evaluator and add our newly defined requirement. This
+can be done at any point during the test, but typically test writers choose to
+do this at the end of the test:
+
+```
+PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+PerformanceClassEvaluator.FileSystemRequirement r8_2__H_1_1 = pce.addR8_2__H_1_1();
+```
+
+After the test, once our required measurement(s) have been calculated, we use
+the set measurement method(s) we defined to report them:
+
+```
+r8_2__H_1_1.setFilesystemIoRate(stat.mAverage);
+```
+
+Finally, we just need to submit our results. The submit method should be called
+only once at the very end of the test. If we are writing our test CTS, we should
+use `submitAndCheck`; if we are writing our test under CTS-Verifier or ITS, we
+should use `submitAndVerify`. Ex:
+
+```
+pce.submitAndCheck();
+```
+
+The test results are then processed and reported creating a file
+cts_media_performance_class_test_cases.reportlog.json which will eventually have
+its data upload and processed.
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 1e803c2..5d7ccc9 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -543,6 +543,32 @@
             return new FrameDropRequirement(RequirementConstants.R5_3__H_1_2, frameDropped,
                 frameRate);
         }
+
+        /**
+         * [2.2.7.1/5.3/H-1-2] MUST NOT drop more than 1 frames in 10 seconds during a
+         * video resolution change in a 4k 60 fps video session under load. Load is defined as a
+         * concurrent 1080p to 720p video-only transcoding session using hardware video codecs,
+         * as well as a 128Kbps AAC audio playback.
+         */
+        public static FrameDropRequirement createR5_3__H_1_2_U() {
+            RequiredMeasurement<Integer> frameDropped = RequiredMeasurement
+                    .<Integer>builder()
+                    .setId(RequirementConstants.FRAMES_DROPPED)
+                    .setPredicate(RequirementConstants.INTEGER_LTE)
+                    // MUST NOT drop more than 1 frame in 10 seconds so 3 frames for 30 seconds
+                    .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, 3)
+                    .build();
+
+            RequiredMeasurement<Double> frameRate = RequiredMeasurement
+                    .<Double>builder()
+                    .setId(RequirementConstants.FRAME_RATE)
+                    .setPredicate(RequirementConstants.DOUBLE_EQ)
+                    .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, 60.0)
+                    .build();
+
+            return new FrameDropRequirement(RequirementConstants.R5_3__H_1_2, frameDropped,
+                    frameRate);
+        }
     }
 
     public static class VideoCodecRequirement extends Requirement {
@@ -564,6 +590,10 @@
             this.setMeasuredValue(RequirementConstants.NUM_4k_HW_ENC, num4kHwEncoders);
         }
 
+        public void setAVIFDecoderReq(boolean avifDecoderReqSatisfied) {
+            this.setMeasuredValue(RequirementConstants.AVIF_DEC_REQ, avifDecoderReqSatisfied);
+        }
+
         /**
          * [2.2.7.1/5.1/H-1-15] Must have at least 1 HW video decoder supporting 4K60
          */
@@ -605,6 +635,20 @@
 
             return new VideoCodecRequirement(RequirementConstants.R5_1__H_1_14, requirement);
         }
+
+        /**
+         * [5.1/H-1-17] MUST have at least 1 Hw image decoder supporting AVIF Baseline profile.
+         */
+        public static VideoCodecRequirement createRAVIFDecoderReq() {
+            RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+                    .<Boolean>builder()
+                    .setId(RequirementConstants.AVIF_DEC_REQ)
+                    .setPredicate(RequirementConstants.BOOLEAN_EQ)
+                    .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, true)
+                    .build();
+
+            return new VideoCodecRequirement(RequirementConstants.R5_1__H_1_17, requirement);
+        }
     }
 
     // used for requirements [2.2.7.1/5.1/H-1-1], [2.2.7.1/5.1/H-1-2], [2.2.7.1/5.1/H-1-3],
@@ -1621,6 +1665,10 @@
         return this.addRequirement(FrameDropRequirement.createR5_3__H_1_2_ST());
     }
 
+    public FrameDropRequirement addR5_3__H_1_2_U() {
+        return this.addRequirement(FrameDropRequirement.createR5_3__H_1_2_U());
+    }
+
     public CodecInitLatencyRequirement addR5_1__H_1_7() {
         return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7());
     }
@@ -1649,6 +1697,10 @@
         return this.addRequirement(VideoCodecRequirement.createRAV1DecoderReq());
     }
 
+    public VideoCodecRequirement addRAVIFDecoderReq() {
+        return this.addRequirement(VideoCodecRequirement.createRAVIFDecoderReq());
+    }
+
     public SecureCodecRequirement addR5_1__H_1_11() {
         return this.addRequirement(SecureCodecRequirement.createR5_1__H_1_11());
     }
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
index 6893e62..c265b18 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -41,6 +41,7 @@
     public static final String R5_1__H_1_14 = "r5_1__h_1_14"; // 5.1/H-1-14
     public static final String R5_1__H_1_15 = "r5_1__h_1_15"; // 5.1/H-1-16
     public static final String R5_1__H_1_16 = "r5_1__h_1_16"; // 5.1/H-1-16
+    public static final String R5_1__H_1_17 = "r5_1__h_1_17"; // 5.1/H-1-17
     public static final String R5_3__H_1_1 = "r5_3__h_1_1"; // 5.3/H-1-1
     public static final String R5_3__H_1_2 = "r5_3__h_1_2"; // 5.3/H-1-2
     public static final String R5_6__H_1_1 = "r5_6__h_1_1"; // 5.6/H-1-1
@@ -91,6 +92,7 @@
     public static final String PHYSICAL_MEMORY = "physical_memory_mb";
     public static final String CODEC_INIT_LATENCY = "codec_initialization_latency_ms";
     public static final String AV1_DEC_REQ = "av1_decoder_requirement_boolean";
+    public static final String AVIF_DEC_REQ = "AVIF_image_decoder";
     public static final String NUM_4k_HW_DEC = "number_4k_hw_decoders";
     public static final String NUM_4k_HW_ENC = "number_4k_hw_encoders";
     public static final String SECURE_REQ_SATISFIED = "secure_requirement_satisfied_boolean";
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
index 2a4ece0..175ff54 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -136,10 +136,14 @@
         return sPc == Build.VERSION_CODES.TIRAMISU;
     }
 
+    public static boolean isUPerfClass() {
+        return sPc == Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+    }
+
     /**
      * Latest defined media performance class.
      */
-    private static final int LAST_PERFORMANCE_CLASS = Build.VERSION_CODES.TIRAMISU;
+    private static final int LAST_PERFORMANCE_CLASS = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
 
     public static boolean isHandheld() {
         // handheld nature is not exposed to package manager, for now
diff --git a/tests/mediapc/copy_media.sh b/tests/mediapc/copy_media.sh
index 25d98ce..ee1704c 100644
--- a/tests/mediapc/copy_media.sh
+++ b/tests/mediapc/copy_media.sh
@@ -17,7 +17,7 @@
 ## script to install media performance class test files manually
 
 adbOptions=" "
-resLabel=CtsMediaPerformanceClassTestCases-2.1
+resLabel=CtsMediaPerformanceClassTestCases-2.2
 srcDir="/tmp/$resLabel"
 tgtDir="/sdcard/test"
 usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java b/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
index c520c5c..386fd6f 100644
--- a/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
@@ -51,16 +51,13 @@
     // Returns the list of parameters with mimeTypes and their hardware decoders supporting the
     // AdaptivePlayback feature combining with sync and async modes.
     // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         return prepareArgumentsList(new String[]{
                 MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback});
     }
 
-    private int testAdaptivePlaybackFrameDrop(int frameRate) throws Exception {
-        String[] testFiles = frameRate == 30 ?
-                new String[]{m1080p30FpsTestFiles.get(mMime), m540p30FpsTestFiles.get(mMime)} :
-                new String[]{m1080p60FpsTestFiles.get(mMime), m540p60FpsTestFiles.get(mMime)};
+    private int testAdaptivePlaybackFrameDrop(int frameRate, String[] testFiles) throws Exception {
         PlaybackFrameDrop playbackFrameDrop = new PlaybackFrameDrop(mMime, mDecoderName, testFiles,
                 mSurface, frameRate, mIsAsync);
 
@@ -85,7 +82,9 @@
         PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
         PerformanceClassEvaluator.FrameDropRequirement r5_3__H_1_2_R = pce.addR5_3__H_1_2_R();
 
-        int framesDropped = testAdaptivePlaybackFrameDrop(frameRate);
+        String[] testFiles =
+                new String[]{m1080p30FpsTestFiles.get(mMime), m540p30FpsTestFiles.get(mMime)};
+        int framesDropped = testAdaptivePlaybackFrameDrop(frameRate, testFiles);
 
         r5_3__H_1_2_R.setFramesDropped(framesDropped);
         r5_3__H_1_2_R.setFrameRate(frameRate);
@@ -110,10 +109,39 @@
         PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
         PerformanceClassEvaluator.FrameDropRequirement r5_3__H_1_2_ST = pce.addR5_3__H_1_2_ST();
 
-        int framesDropped = testAdaptivePlaybackFrameDrop(frameRate);
+        String[] testFiles =
+                new String[]{m1080p60FpsTestFiles.get(mMime), m540p60FpsTestFiles.get(mMime)};
+        int framesDropped = testAdaptivePlaybackFrameDrop(frameRate, testFiles);
 
         r5_3__H_1_2_ST.setFramesDropped(framesDropped);
         r5_3__H_1_2_ST.setFrameRate(frameRate);
         pce.submitAndCheck();
     }
+
+    /**
+     * This test validates that the Adaptive Playback of 3840x2160 and 1920x1080 resolution
+     * assets of 3 seconds duration each at 60 fps for U perf class,
+     * playing alternatively, for at least 30 seconds worth of frames or for 31 seconds of elapsed
+     * time, must not drop more than 3 frames for U perf class .
+     */
+    @LargeTest
+    @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+    @CddTest(requirement = "2.2.7.1/5.3/H-1-2")
+    public void test4k() throws Exception {
+        Assume.assumeTrue("Test is limited to U performance class devices or devices that do not " +
+                        "advertise performance class",
+            Utils.isUPerfClass() || !Utils.isPerfClass());
+        int frameRate = 60;
+
+        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+        PerformanceClassEvaluator.FrameDropRequirement r5_3__H_1_2_U = pce.addR5_3__H_1_2_U();
+
+        String[] testFiles =
+                new String[]{m2160p60FpsTestFiles.get(mMime), m1080p60FpsTestFiles.get(mMime)};
+        int framesDropped = testAdaptivePlaybackFrameDrop(frameRate, testFiles);
+
+        r5_3__H_1_2_U.setFramesDropped(framesDropped);
+        r5_3__H_1_2_U.setFrameRate(frameRate);
+        pce.submitAndCheck();
+    }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
index 514e8ea..4ff5f6b 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
@@ -168,7 +168,7 @@
      *
      * @return Collection of Parameters {0}_{1} -- MIME_CodecName
      */
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> inputParams() {
         // Prepares the params list with the required Hardware video codecs and all available
         // audio codecs present in the device.
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
index 5f88524..8d87c88 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
@@ -50,7 +50,7 @@
     // Returns the list of parameters with mimeTypes and their hardware decoders
     // combining with sync and async modes.
     // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         return prepareArgumentsList(null);
     }
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
index 5568f59..aad1c62 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
@@ -77,6 +77,7 @@
     static Map<String, String> m1080p30FpsTestFiles = new HashMap<>();
     static Map<String, String> m540p60FpsTestFiles = new HashMap<>();
     static Map<String, String> m1080p60FpsTestFiles = new HashMap<>();
+    static Map<String, String> m2160p60FpsTestFiles = new HashMap<>();
     static {
         m540p60FpsTestFiles.put(AVC, "bbb_960x540_3mbps_60fps_avc.mp4");
         m540p60FpsTestFiles.put(HEVC, "bbb_960x540_3mbps_60fps_hevc.mp4");
@@ -90,6 +91,12 @@
         m1080p60FpsTestFiles.put(VP9, "bbb_1920x1080_6mbps_60fps_vp9.webm");
         m1080p60FpsTestFiles.put(AV1, "bbb_1920x1080_6mbps_60fps_av1.mp4");
 
+        m2160p60FpsTestFiles.put(AVC, "bbb_3840x2160_24mbps_60fps_avc.mp4");
+        m2160p60FpsTestFiles.put(HEVC, "bbb_3840x2160_18mbps_60fps_hevc.mkv");
+        m2160p60FpsTestFiles.put(VP8, "bbb_3840x2160_24mbps_60fps_vp8.webm");
+        m2160p60FpsTestFiles.put(VP9, "bbb_3840x2160_18mbps_60fps_vp9.webm");
+        m2160p60FpsTestFiles.put(AV1, "bbb_3840x2160_18mbps_60fps_av1.mp4");
+
         m540p30FpsTestFiles.put(AVC, "bbb_960x540_2mbps_30fps_avc.mp4");
         m540p30FpsTestFiles.put(HEVC, "bbb_960x540_2mbps_30fps_hevc.mp4");
         m540p30FpsTestFiles.put(VP8, "bbb_960x540_2mbps_30fps_vp8.webm");
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index 9e1af43..b128601 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -69,7 +69,7 @@
     // Returns the list of params with two hardware (mime - decoder) pairs in both
     // sync and async modes.
     // Parameters {0}_{1}_{2} -- Pair(Mime DecoderName)_Pair(Mime DecoderName)_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         final List<Object[]> argsList = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index fc33361..4d9a249 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -63,7 +63,7 @@
     // Returns the params list with the mime and corresponding hardware decoders in
     // both sync and async modes.
     // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         final List<Object[]> argsList = new ArrayList<>();
         for (String mime : mMimeList) {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
index e51935d..a63f570 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
@@ -67,7 +67,7 @@
     // Returns the list of params with two hardware (mime - encoder) pairs in both
     // sync and async modes.
     // Parameters {0}_{1}_{2} -- Pair(Mime EncoderName)_Pair(Mime EncoderName)_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         final List<Object[]> argsList = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeEncoderPairs = new ArrayList<>();
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index bb52553..291f004 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -63,7 +63,7 @@
     // Returns the params list with the mime and their hardware encoders in
     // both sync and async modes.
     // Parameters {0}_{2}_{3} -- Mime_EncoderName_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         final List<Object[]> argsList = new ArrayList<>();
         for (String mime : mMimeList) {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index 8ae7e8a..668a4fa 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -74,7 +74,7 @@
     public final TestName mTestName = new TestName();
 
     // Parameters {0}_{1}_{2} -- Pair(Mime DecoderName)_Pair(Mime EncoderName)_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> inputParams() {
         // Prepares the params list with the supported Hardware decoders/encoders in the device
         final List<Object[]> argsList = new ArrayList<>();
diff --git a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
index 4aac947..87eb01d 100644
--- a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
@@ -16,6 +16,9 @@
 
 package android.mediapc.cts;
 
+import static android.media.MediaCodecInfo.CodecProfileLevel.AV1Level51;
+import static android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10;
+import static android.media.MediaCodecInfo.CodecProfileLevel.AV1ProfileMain8;
 import static android.media.MediaFormat.MIMETYPE_VIDEO_AV1;
 import static android.mediapc.cts.CodecTestBase.SELECT_HARDWARE;
 import static android.mediapc.cts.CodecTestBase.SELECT_VIDEO;
@@ -24,6 +27,8 @@
 
 import static org.junit.Assert.assertTrue;
 
+import android.graphics.Bitmap;
+import android.graphics.ImageDecoder;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo.CodecCapabilities;
 import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
@@ -41,6 +46,7 @@
 import org.junit.Test;
 import org.junit.rules.TestName;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -51,6 +57,7 @@
     private static final String LOG_TAG = VideoCodecRequirementsTest.class.getSimpleName();
     private static final String FILE_AV1_REQ_SUPPORT =
             "dpov_1920x1080_60fps_av1_10bit_film_grain.mp4";
+    private static final String INPUT_FILE = "bbb_3840x2160_AVIF.avif";
 
     @Rule
     public final TestName mTestName = new TestName();
@@ -60,6 +67,12 @@
         Utils.assumeDeviceMeetsPerformanceClassPreconditions();
     }
 
+    private boolean decodeAVIF(File inputfile) throws IOException {
+        ImageDecoder.Source src = ImageDecoder.createSource(inputfile);
+        Bitmap bm = ImageDecoder.decodeBitmap(src);
+        return true;
+    }
+
     private Set<String> get4k60HwCodecSet(boolean isEncoder) throws IOException {
         Set<String> codecSet = new HashSet<>();
         Set<String> codecMediaTypes = getMimesOfAvailableCodecs(SELECT_VIDEO, SELECT_HARDWARE);
@@ -148,4 +161,34 @@
 
         pce.submitAndCheck();
     }
+
+    /**
+     * MUST have at least 1 hardware image decoder supporting AVIF Baseline Profile.
+     */
+    @LargeTest
+    @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+    @CddTest(requirement = "5.1/H-1-17")
+    public void testAVIFHwDecoderRequirements() throws Exception {
+        int[] profiles = {AV1ProfileMain8, AV1ProfileMain10};
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        for (int profile : profiles) {
+            MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AV1, 3840, 2160);
+            format.setInteger(MediaFormat.KEY_PROFILE, profile);
+            format.setInteger(MediaFormat.KEY_LEVEL, AV1Level51);
+            formats.add(format);
+        }
+        ArrayList<String> av1HwDecoders =
+                selectHardwareCodecs(MIMETYPE_VIDEO_AV1, formats, null, false);
+        boolean isDecoded = false;
+        if (av1HwDecoders.size() != 0) {
+            isDecoded = decodeAVIF(new File(WorkDir.getMediaDirString() + INPUT_FILE));
+        }
+
+        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+        PerformanceClassEvaluator.VideoCodecRequirement rAVIFDecoderReq =
+                pce.addRAVIFDecoderReq();
+        rAVIFDecoderReq.setAVIFDecoderReq(isDecoded);
+
+        pce.submitAndCheck();
+    }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/WorkDir.java b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
index 4076e88..b4752e0 100644
--- a/tests/mediapc/src/android/mediapc/cts/WorkDir.java
+++ b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
@@ -40,7 +40,7 @@
             // user has specified the mediaDirString via instrumentation-arg
             return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
         } else {
-            return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-2.1/");
+            return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-2.2/");
         }
     }
 }
diff --git a/tests/netlegacy22.permission/AndroidManifest.xml b/tests/netlegacy22.permission/AndroidManifest.xml
index 85979c9..d440335 100644
--- a/tests/netlegacy22.permission/AndroidManifest.xml
+++ b/tests/netlegacy22.permission/AndroidManifest.xml
@@ -45,8 +45,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
          android:targetPackage="android.netlegacy22.permission.cts"
          android:label="CTS tests of legacy android.net permissions as of API 22">
-        <meta-data android:name="listener"
-             android:value="com.android.cts.runner.CtsTestRunListener"/>
     </instrumentation>
 
 </manifest>
diff --git a/tests/quicksettings/Android.bp b/tests/quicksettings/Android.bp
index 7246788..df7b7dc 100644
--- a/tests/quicksettings/Android.bp
+++ b/tests/quicksettings/Android.bp
@@ -30,6 +30,7 @@
         "androidx.test.ext.junit",
         "androidx.test.uiautomator_uiautomator",
         "compatibility-device-util-axt",
+        "SystemUI-proto",
      ],
 
     libs: [
diff --git a/tests/quicksettings/src/android/quicksettings/cts/BaseTileServiceTest.java b/tests/quicksettings/src/android/quicksettings/cts/BaseTileServiceTest.java
index 8ef5807..3030546 100644
--- a/tests/quicksettings/src/android/quicksettings/cts/BaseTileServiceTest.java
+++ b/tests/quicksettings/src/android/quicksettings/cts/BaseTileServiceTest.java
@@ -22,9 +22,11 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assume.assumeTrue;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.os.ParcelFileDescriptor;
 import android.service.quicksettings.TileService;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
@@ -35,11 +37,18 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.SystemUtil;
+import com.android.systemui.dump.nano.SystemUIProtoDump;
+import com.android.systemui.qs.nano.QsTileState;
+import com.android.systemui.util.nano.ComponentNameProto;
+
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.runner.RunWith;
 
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
 import java.io.IOException;
 
 @RunWith(AndroidJUnit4.class)
@@ -52,8 +61,8 @@
     protected abstract void waitForListening(boolean state) throws InterruptedException;
     protected Context mContext;
 
-    final static String DUMP_COMMAND =
-            "dumpsys activity service com.android.systemui/.SystemUIService QSTileHost";
+    static final String PROTO_DUMP_COMMAND =
+            "dumpsys statusbar QSTileHost --proto";
 
     // Time between checks for state we expect.
     protected static final long CHECK_DELAY = 250;
@@ -138,4 +147,46 @@
         }
         return null;
     }
+
+    protected final QsTileState findTileState() {
+        QsTileState[] tiles = getTilesStates();
+        for (int i = 0; i < tiles.length; i++) {
+            QsTileState tile = tiles[i];
+            if (tile.hasComponentName()) {
+                ComponentNameProto componentName = tile.getComponentName();
+                ComponentName c = ComponentName.createRelative(
+                        componentName.packageName, componentName.className);
+                if (c.flattenToString().equals(getComponentName())) {
+                    return tile;
+                }
+            }
+        }
+        return null;
+    }
+
+    private QsTileState[] getTilesStates() {
+        try {
+            return SystemUIProtoDump.parseFrom(getProtoDump()).tiles;
+        } catch (InvalidProtocolBufferNanoException e) {
+            throw new IllegalStateException("Couldn't parse proto dump", e);
+        }
+    }
+
+    private byte[] getProtoDump() {
+        try {
+            ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation()
+                    .getUiAutomation().executeShellCommand(PROTO_DUMP_COMMAND);
+            byte[] buf = new byte[512];
+            int bytesRead;
+            FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+            ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+            while ((bytesRead = fis.read(buf)) != -1) {
+                stdout.write(buf, 0, bytesRead);
+            }
+            fis.close();
+            return stdout.toByteArray();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/tests/quicksettings/src/android/quicksettings/cts/BooleanTileServiceTest.java b/tests/quicksettings/src/android/quicksettings/cts/BooleanTileServiceTest.java
index 0f6d56e..67a1f40 100644
--- a/tests/quicksettings/src/android/quicksettings/cts/BooleanTileServiceTest.java
+++ b/tests/quicksettings/src/android/quicksettings/cts/BooleanTileServiceTest.java
@@ -17,12 +17,15 @@
 package android.quicksettings.cts;
 
 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.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
 
+import com.android.systemui.qs.nano.QsTileState;
+
 import org.junit.Test;
 
 public class BooleanTileServiceTest extends BaseTileServiceTest {
@@ -39,12 +42,9 @@
     public void testTileInDumpAndHasBooleanState() throws Exception {
         initializeAndListen();
 
-        final CharSequence tileLabel = mTileService.getQsTile().getLabel();
-
-        final String[] dumpLines = executeShellCommand(DUMP_COMMAND).split("\n");
-        final String line = findLine(dumpLines, tileLabel);
-        assertNotNull(line);
-        assertTrue(line.trim().startsWith("BooleanState"));
+        final QsTileState tileState = findTileState();
+        assertNotNull(tileState);
+        assertTrue(tileState.hasBooleanState());
     }
 
     @Test
@@ -58,13 +58,10 @@
     public void testValueTracksState() throws Exception {
         initializeAndListen();
 
-        final CharSequence tileLabel = mTileService.getQsTile().getLabel();
-
-        String[] dumpLines = executeShellCommand(DUMP_COMMAND).split("\n");
-        String line = findLine(dumpLines, tileLabel);
+        QsTileState tileState = findTileState();
 
         // Tile starts inactive
-        assertTrue(line.contains("value=false"));
+        assertFalse(tileState.getBooleanState());
 
         ((ToggleableTestTileService) mTileService).toggleState();
 
@@ -76,10 +73,9 @@
 
         assertEquals(Tile.STATE_ACTIVE, mTileService.getQsTile().getState());
 
-        dumpLines = executeShellCommand(DUMP_COMMAND).split("\n");
-        line = findLine(dumpLines, tileLabel);
+        tileState = findTileState();
 
-        assertTrue(line.contains("value=true"));
+        assertTrue(tileState.getBooleanState());
     }
 
     @Override
diff --git a/tests/quicksettings/src/android/quicksettings/cts/TileServiceTest.java b/tests/quicksettings/src/android/quicksettings/cts/TileServiceTest.java
index 2ccab0c..64b6ce4 100644
--- a/tests/quicksettings/src/android/quicksettings/cts/TileServiceTest.java
+++ b/tests/quicksettings/src/android/quicksettings/cts/TileServiceTest.java
@@ -27,6 +27,8 @@
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
 
+import com.android.systemui.qs.nano.QsTileState;
+
 import org.junit.Test;
 
 public class TileServiceTest extends BaseTileServiceTest {
@@ -115,15 +117,32 @@
     }
 
     @Test
-    public void testTileInDumpAndHasState() throws Exception {
+    public void testTileInDumpAndHasNonBooleanState() throws Exception {
         initializeAndListen();
+        final QsTileState tileState = findTileState();
+        assertNotNull(tileState);
+        assertFalse(tileState.hasBooleanState());
+    }
 
-        final CharSequence tileLabel = mTileService.getQsTile().getLabel();
+    @Test
+    public void testTileInDumpAndHasCorrectState() throws Exception {
+        initializeAndListen();
+        CharSequence label = "test_label";
+        CharSequence subtitle = "test_subtitle";
 
-        final String[] dumpLines = executeShellCommand(DUMP_COMMAND).split("\n");
-        final String line = findLine(dumpLines, tileLabel);
-        assertNotNull(line);
-        assertTrue(line.trim().startsWith("State")); // Not BooleanState
+        Tile tile = mTileService.getQsTile();
+        tile.setState(Tile.STATE_ACTIVE);
+        tile.setLabel(label);
+        tile.setSubtitle(subtitle);
+        tile.updateTile();
+
+        Thread.sleep(200);
+
+        final QsTileState tileState = findTileState();
+        assertNotNull(tileState);
+        assertEquals(Tile.STATE_ACTIVE,  tileState.state);
+        assertEquals(label,  tileState.getLabel());
+        assertEquals(subtitle,  tileState.getSecondaryLabel());
     }
 
     private void clickTile(String componentName) throws Exception {
diff --git a/tests/tests/accounts/AndroidTest.xml b/tests/tests/accounts/AndroidTest.xml
index 7c04659..872ecc3 100644
--- a/tests/tests/accounts/AndroidTest.xml
+++ b/tests/tests/accounts/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS Accounts test cases">
     <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="component" value="auth" />
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/TEST_MAPPING b/tests/tests/app.usage/src/android/app/usage/cts/TEST_MAPPING
index 40a042b..4832ee6 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/TEST_MAPPING
+++ b/tests/tests/app.usage/src/android/app/usage/cts/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit-large": [
+  "presubmit": [
     {
       "name": "CtsUsageStatsTestCases",
       "options": [
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 6a48261..1d4aade 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -550,6 +550,10 @@
         Map<String,UsageStats> events = mUsageStatsManager.queryAndAggregateUsageStats(
                 startTime, endTime);
         UsageStats stats = events.get(mTargetPackage);
+        if (stats == null) {
+            fail("Querying UsageStats for " + mTargetPackage + " returned empty; list of packages "
+                 + "with events: " + Arrays.toString(events.keySet().toArray(new String[0])));
+        }
         int startingCount = stats.getAppLaunchCount();
         // Launch count is updated by UsageStatsService depending on last background package.
         // When running this test on single screen device (where tasks are launched in the same
diff --git a/tests/tests/gwp-asan/enabled/Android.bp b/tests/tests/batteryhealth/Android.bp
similarity index 70%
rename from tests/tests/gwp-asan/enabled/Android.bp
rename to tests/tests/batteryhealth/Android.bp
index a78598e..d017e57 100644
--- a/tests/tests/gwp-asan/enabled/Android.bp
+++ b/tests/tests/batteryhealth/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 The Android Open Source Project
+// Copyright (C) 2023 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.
@@ -17,26 +17,28 @@
 }
 
 android_test {
-    name: "CtsGwpAsanTestCases",
+    name: "CtsBatteryHealthTestCases",
     defaults: ["cts_defaults"],
-    compile_multilib: "both",
-    // When built, explicitly put it in the data partition.
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.legacy_legacy-support-v4",
+        "mockito-target-minus-junit4",
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
+        "platformprotosnano",
+        "truth-prebuilt",
+        "ub-uiautomator",
     ],
     libs: [
         "android.test.runner",
         "android.test.base",
     ],
-    static_libs: [
-        "ctstestrunner-axt",
-        "androidx.test.rules",
-        "androidx.test.core",
-        "androidx.test.ext.junit",
+    srcs: [
+        "src/**/*.java",
     ],
-    srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    use_embedded_native_libs: false,
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    per_testcase_directory: true,
 }
diff --git a/tests/tests/batteryhealth/AndroidManifest.xml b/tests/tests/batteryhealth/AndroidManifest.xml
new file mode 100755
index 0000000..5aee337
--- /dev/null
+++ b/tests/tests/batteryhealth/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.os.cts.batteryhealth">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.os.cts.batteryhealth"
+        android:label="CTS tests for battery health features">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
diff --git a/tests/tests/batteryhealth/AndroidTest.xml b/tests/tests/batteryhealth/AndroidTest.xml
new file mode 100644
index 0000000..11007d0
--- /dev/null
+++ b/tests/tests/batteryhealth/AndroidTest.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Config for Battery Health CTS test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <!-- Disable keyguard -->
+        <!-- Though keyguard is disabled globally in cts-preconditions.xml, the
+             following line should be kept to make atest behave correctly. -->
+        <option name="run-command" value="locksettings set-disabled true" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" /> <!-- DO NOT SUBMIT WITH FALSE -->
+        <option name="test-file-name" value="CtsBatteryHealthTestCases.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="settings put global device_config_sync_disabled 0" />
+        <option name="run-command" value="cmd thermalservice override-status 0" />
+        <option name="teardown-command" value="cmd thermalservice reset" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.os.cts.batteryhealth" />
+        <option name="runtime-hint" value="10m00s" />
+    </test>
+
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="android.scheduling"/>
+    </object>
+</configuration>
diff --git a/tests/tests/batteryhealth/OWNERS b/tests/tests/batteryhealth/OWNERS
new file mode 100644
index 0000000..5ab6e92
--- /dev/null
+++ b/tests/tests/batteryhealth/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 320875
+apelosi@google.com
+yangken@google.com
+wjack@google.com
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatteryHealthTest.java b/tests/tests/batteryhealth/src/android/os/cts/batteryhealth/BatteryHealthTest.java
similarity index 82%
rename from tests/tests/batterysaving/src/android/os/cts/batterysaving/BatteryHealthTest.java
rename to tests/tests/batteryhealth/src/android/os/cts/batteryhealth/BatteryHealthTest.java
index d6625c6..0454059 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatteryHealthTest.java
+++ b/tests/tests/batteryhealth/src/android/os/cts/batteryhealth/BatteryHealthTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.os.cts.batterysaving;
+package android.os.cts.batteryhealth;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -22,14 +22,19 @@
 import static org.junit.Assert.fail;
 
 import android.app.UiAutomation;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.BatteryManager;
 
+import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiTest;
+
 import org.junit.Before;
 import org.junit.Test;
 
-public class BatteryHealthTest extends BatterySavingTestBase {
+public class BatteryHealthTest {
     private static final String TAG = "BatteryHealthTest";
 
     // Battery usage date: check the range from 2020-12-01 to 2038-01-19
@@ -49,10 +54,13 @@
 
     @Before
     public void setUp() {
-        mBatteryManager = getContext().getSystemService(BatteryManager.class);
+        final Context context = InstrumentationRegistry.getContext();
+
+        mBatteryManager = context.getSystemService(BatteryManager.class);
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_MANUFACTURING_DATE"})
     public void testManufacturingDate_dataInRange() {
         mAutomation = getInstrumentation().getUiAutomation();
         mAutomation.adoptShellPermissionIdentity(android.Manifest.permission.BATTERY_STATS);
@@ -68,6 +76,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_FIRST_USAGE_DATE"})
     public void testFirstUsageDate_dataInRange() {
         mAutomation = getInstrumentation().getUiAutomation();
         mAutomation.adoptShellPermissionIdentity(android.Manifest.permission.BATTERY_STATS);
@@ -83,6 +92,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_CHARGING_POLICY"})
     public void testChargingPolicy_dataInRange() {
         mAutomation = getInstrumentation().getUiAutomation();
         mAutomation.adoptShellPermissionIdentity(android.Manifest.permission.BATTERY_STATS);
@@ -97,6 +107,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_STATE_OF_HEALTH"})
     public void testBatteryStateOfHealth_dataInRange() {
         mAutomation = getInstrumentation().getUiAutomation();
         mAutomation.adoptShellPermissionIdentity(android.Manifest.permission.BATTERY_STATS);
@@ -112,8 +123,10 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#EXTRA_CYCLE_COUNT"})
     public void testBatteryCycleCount_dataInRange() {
-        final Intent batteryInfo = getContext().registerReceiver(null,
+        final Context context = InstrumentationRegistry.getContext();
+        final Intent batteryInfo = context.registerReceiver(null,
                                     new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
         final int batteryCycleCount = batteryInfo.getIntExtra(BatteryManager
                 .EXTRA_CYCLE_COUNT, -1);
@@ -122,6 +135,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_MANUFACTURING_DATE"})
     public void testManufacturingDate_noPermission() {
         try {
             final long manufacturingDate = mBatteryManager.getLongProperty(BatteryManager
@@ -133,6 +147,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_FIRST_USAGE_DATE"})
     public void testFirstUsageDate_noPermission() {
         try {
             final long firstUsageDate = mBatteryManager.getLongProperty(BatteryManager
@@ -144,6 +159,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_CHARGING_POLICY"})
     public void testChargingPolicy_noPermission() {
         try {
             final int chargingPolicy = mBatteryManager.getIntProperty(BatteryManager
@@ -155,6 +171,7 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.os.BatteryManager#BATTERY_PROPERTY_STATE_OF_HEALTH"})
     public void testBatteryStateOfHealth_noPermission() {
         try {
             final int stateOfHealth = mBatteryManager.getIntProperty(BatteryManager
diff --git a/tests/tests/bionic/Android.bp b/tests/tests/bionic/Android.bp
index a0458d7..c6bc68c 100644
--- a/tests/tests/bionic/Android.bp
+++ b/tests/tests/bionic/Android.bp
@@ -45,12 +45,6 @@
         "libz",
         "libutils",
         "libgtest",
-        "libLLVMObject",
-        "libLLVMBitReader",
-        "libLLVMMC",
-        "libLLVMMCParser",
-        "libLLVMCore",
-        "libLLVMSupport",
     ],
 
     // Use the bootstrap version of bionic because some tests call private APIs
diff --git a/tests/tests/bluetooth/TEST_MAPPING b/tests/tests/bluetooth/TEST_MAPPING
index cfb28d3..9f91f8e 100644
--- a/tests/tests/bluetooth/TEST_MAPPING
+++ b/tests/tests/bluetooth/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit-large": [
+  "presubmit": [
     {
       "name": "CtsBluetoothTestCases"
     }
@@ -8,5 +8,81 @@
     {
       "name": "CtsBluetoothTestCases"
     }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "CtsBluetoothTestCases",
+      "options": [
+        {
+          // TODO(b/255288185)
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testCloseProfileProxy"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testGetAllGroupIds"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testGetConnectedDevices"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testGetDevicesMatchingConnectionStates"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testGetGroupUuidMapByDevice"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testLockUnlockGroup"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothCsipSetCoordinatorTest#testTestLockCallback"
+        },
+        {
+          // TODO(b/171462068)
+          "exclude-filter": "android.bluetooth.cts.LeL2capSocketTest#testOpenInsecureLeL2capServerSocketOnce"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.LeL2capSocketTest#testOpenInsecureLeL2capServerSocketRepeatedly"
+        },
+        {
+          // TODO(b/202542782)
+          "exclude-filter": "android.bluetooth.cts.BluetoothLeScanTest#testBasicBleScan"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BasicAdapterTest#test_enableDisable"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BasicAdapterTest#test_getBondedDevices"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BasicAdapterTest#test_getName"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BasicAdapterTest#test_listenUsingRfcommWithServiceRecord"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.HearingAidProfileTest#test_getConnectionState"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.HearingAidProfileTest#test_getConnectionStateChangedIntent"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.HearingAidProfileTest#test_getProxyServiceConnect"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.HearingAidProfileTest#test_getDevicesMatchingConnectionStates"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.LeL2capSocketTest#testOpenSecureLeL2capServerSocketOnce"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.LeL2capSocketTest#testOpenSecureLeL2capServerSocketRepeatedly"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BluetoothLeScanTest#testScanFilter"
+        },
+        {
+          "exclude-filter": "android.bluetooth.cts.BasicAdapterTest#test_setName_getName"
+        }
+      ]
+    }
   ]
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java
index 27708a6..a653bc5 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java
@@ -48,8 +48,8 @@
     private BluetoothA2dpSink mBluetoothA2dpSink;
     private boolean mIsA2dpSinkSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -68,8 +68,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothA2dpSink = null;
 
@@ -92,6 +92,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsA2dpSinkSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothA2dpSink);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.A2DP_SINK, mBluetoothA2dpSink);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsA2dpSinkSupported)) return;
 
@@ -189,11 +201,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -203,28 +215,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothA2dpSinkServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothA2dpSink = (BluetoothA2dpSink) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
index 21a5cad..1d3c00a 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
@@ -49,8 +49,8 @@
     private BluetoothA2dp mBluetoothA2dp;
     private boolean mIsA2dpSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private ReentrantLock mProfileConnectionlock;
+    private Condition mConditionProfileConnection;
 
     @Override
     public void setUp() throws Exception {
@@ -69,8 +69,9 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+
         mIsProfileReady = false;
         mBluetoothA2dp = null;
 
@@ -93,6 +94,18 @@
         mUiAutomation.dropShellPermissionIdentity();
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothA2dp);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsA2dpSupported)) return;
 
@@ -329,11 +342,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -343,28 +356,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothA2dpServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothA2dp = (BluetoothA2dp) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java
index 24f8c12..e2eba73 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java
@@ -21,23 +21,19 @@
 
 import static org.junit.Assert.assertThrows;
 
-import android.app.UiAutomation;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothManager;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.bluetooth.BluetoothUuid;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.os.Build;
 import android.os.ParcelUuid;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
-
 import com.android.compatibility.common.util.ApiLevelUtil;
 
 import java.util.List;
@@ -59,8 +55,8 @@
     private BluetoothCsipSetCoordinator mBluetoothCsipSetCoordinator;
     private boolean mIsCsipSetCoordinatorSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
     private boolean mGroupLockCallbackCalled;
     private TestCallback mTestCallback;
     private Executor mTestExecutor;
@@ -94,8 +90,8 @@
             mAdapter = manager.getAdapter();
             assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-            mProfileConnectedlock = new ReentrantLock();
-            mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+            mProfileConnectionlock = new ReentrantLock();
+            mConditionProfileConnection = mProfileConnectionlock.newCondition();
             mIsProfileReady = false;
             mBluetoothCsipSetCoordinator = null;
 
@@ -140,6 +136,19 @@
         }
     }
 
+    public void testCloseProfileProxy() {
+        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothCsipSetCoordinator);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(
+                BluetoothProfile.CSIP_SET_COORDINATOR, mBluetoothCsipSetCoordinator);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void testGetConnectedDevices() {
         if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;
 
@@ -167,6 +176,18 @@
         assertTrue(connectedDevices.isEmpty());
     }
 
+    public void testGetConnectionState() {
+        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothCsipSetCoordinator);
+
+        mTestDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+        int state = mBluetoothCsipSetCoordinator.getConnectionState(mTestDevice);
+        assertEquals(BluetoothProfile.STATE_DISCONNECTED, state);
+    }
+
     public void testGetGroupUuidMapByDevice() {
         if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;
 
@@ -263,11 +284,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -277,28 +298,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothCsipServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothCsipSetCoordinator = (BluetoothCsipSetCoordinator) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
index e5bf5a3..a55df67 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
@@ -548,5 +548,10 @@
         mFakeDevice.createBond();
         assertEquals(getContext().getPackageName(),
                 mFakeDevice.getPackageNameOfBondingApplication());
+
+        // Clean up create bond
+        // Either cancel the bonding process or remove bond
+        mFakeDevice.cancelBondProcess();
+        mFakeDevice.removeBond();
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
index 9a486a7..9e13d26 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
@@ -70,8 +70,8 @@
     private BluetoothHapClient mBluetoothHapClient;
     private boolean mIsHapClientSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     private boolean mOnPresetSelected = false;
     private boolean mOnPresetSelectionFailed = false;
@@ -108,8 +108,8 @@
         mAdapter = TestUtils.getBluetoothAdapterOrDie();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothHapClient = null;
 
@@ -132,6 +132,21 @@
     }
 
     @Test
+    public void test_closeProfileProxy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHapClient);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.HAP_CLIENT, mBluetoothHapClient);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
+    @Test
     public void testGetConnectedDevices() {
         if (shouldSkipTest()) {
             return;
@@ -549,11 +564,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -563,28 +578,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothHapClientServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothHapClient = (BluetoothHapClient) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java
index 439e217..bac21ae 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java
@@ -49,8 +49,8 @@
     private BluetoothHeadsetClient mBluetoothHeadsetClient;
     private boolean mIsHeadsetClientSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -69,8 +69,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothHeadsetClient = null;
 
@@ -93,6 +93,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsHeadsetClientSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadsetClient);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.HEADSET_CLIENT, mBluetoothHeadsetClient);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsHeadsetClientSupported)) return;
 
@@ -216,11 +228,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -230,28 +242,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothHeadsetClientServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
index 5315f33..cf683b4 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
@@ -49,8 +49,8 @@
     private BluetoothHeadset mBluetoothHeadset;
     private boolean mIsHeadsetSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -69,8 +69,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothHeadset = null;
 
@@ -93,6 +93,18 @@
         mUiAutomation.dropShellPermissionIdentity();
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsHeadsetSupported)) return;
 
@@ -373,11 +385,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -387,28 +399,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothHeadsetServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothHeadset = (BluetoothHeadset) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java
index f09ef85..030ee8d 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java
@@ -59,8 +59,8 @@
     private boolean mIsProfileReady;
     private BluetoothAdapter mAdapter;
     private UiAutomation mUiAutomation;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
     private BluetoothHidDevice mBluetoothHidDevice;
 
 
@@ -81,8 +81,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothHidDevice = null;
 
@@ -105,6 +105,18 @@
         mUiAutomation.dropShellPermissionIdentity();
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsHidSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHidDevice);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.HID_DEVICE, mBluetoothHidDevice);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getDevicesMatchingConnectionStates() {
         if (!(mHasBluetooth && mIsHidSupported)) return;
 
@@ -202,13 +214,12 @@
                 testDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN));
     }
 
-
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -218,28 +229,54 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothHidServiceListener implements
             BluetoothProfile.ServiceListener {
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothHidDevice = (BluetoothHidDevice) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
-
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java
index f401ba7..c4fe6b6 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java
@@ -50,8 +50,8 @@
     private UiAutomation mUiAutomation;
 
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -71,8 +71,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mHidHost = null;
 
@@ -93,6 +93,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsHidHostSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mHidHost);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.HID_HOST, mHidHost);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsHidHostSupported)) return;
 
@@ -199,11 +211,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -213,28 +225,54 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothHidHostListener implements BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             try {
                 mHidHost = (BluetoothHidHost) proxy;
                 mIsProfileReady = true;
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
-            // Do nothing
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
index 74247b2..fa10736 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
@@ -55,8 +55,8 @@
     private BluetoothLeAudio mBluetoothLeAudio;
     private boolean mIsLeAudioSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
     private Executor mTestExecutor;
     private TestCallback mTestCallback;
     private boolean mCodecConfigChangedCalled;
@@ -123,8 +123,8 @@
             mAdapter = manager.getAdapter();
             assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-            mProfileConnectedlock = new ReentrantLock();
-            mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+            mProfileConnectionlock = new ReentrantLock();
+            mConditionProfileConnection = mProfileConnectionlock.newCondition();
             mIsProfileReady = false;
             mBluetoothLeAudio = null;
 
@@ -155,6 +155,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsLeAudioSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeAudio);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.LE_AUDIO, mBluetoothLeAudio);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsLeAudioSupported)) return;
 
@@ -389,11 +401,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -403,28 +415,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothLeAudioServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothLeAudio = (BluetoothLeAudio) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
index cc63436..95c5a73 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
@@ -103,8 +103,8 @@
     private BluetoothLeBroadcastAssistant mBluetoothLeBroadcastAssistant;
     private boolean mIsBroadcastAssistantSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedLock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Mock
     BluetoothLeBroadcastAssistant.Callback mCallbacks;
@@ -125,8 +125,8 @@
         mAdapter = TestUtils.getBluetoothAdapterOrDie();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedLock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedLock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothLeBroadcastAssistant = null;
 
@@ -158,6 +158,22 @@
     }
 
     @Test
+    public void testCloseProfileProxy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(
+                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, mBluetoothLeBroadcastAssistant);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
+    @Test
     public void testAddSource() {
         if (shouldSkipTest()) {
             return;
@@ -553,11 +569,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedLock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -567,27 +583,54 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedLock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class ServiceListener implements BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedLock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothLeBroadcastAssistant = (BluetoothLeBroadcastAssistant) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedLock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
index de32a42..19da11e 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
@@ -103,8 +103,8 @@
     private BluetoothLeBroadcast mBluetoothLeBroadcast;
     private boolean mIsLeBroadcastSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     private boolean mOnBroadcastStartedCalled = false;
     private boolean mOnBroadcastStartFailedCalled = false;
@@ -193,8 +193,8 @@
         mAdapter = TestUtils.getBluetoothAdapterOrDie();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothLeBroadcast = null;
 
@@ -230,6 +230,21 @@
     }
 
     @Test
+    public void testCloseProfileProxy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcast);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.LE_AUDIO_BROADCAST, mBluetoothLeBroadcast);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
+    @Test
     public void testGetConnectedDevices() {
         if (shouldSkipTest()) {
             return;
@@ -887,11 +902,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -901,28 +916,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class ServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothLeBroadcast = (BluetoothLeBroadcast) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java
index c0a3037..34f0f52 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java
@@ -62,8 +62,8 @@
     private BluetoothMapClient mBluetoothMapClient;
     private boolean mIsMapClientSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -83,8 +83,8 @@
             mAdapter = manager.getAdapter();
             assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-            mProfileConnectedlock = new ReentrantLock();
-            mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+            mProfileConnectionlock = new ReentrantLock();
+            mConditionProfileConnection = mProfileConnectionlock.newCondition();
             mIsProfileReady = false;
             mBluetoothMapClient = null;
 
@@ -108,6 +108,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsMapClientSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothMapClient);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.MAP_CLIENT, mBluetoothMapClient);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsMapClientSupported)) return;
 
@@ -222,11 +234,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -236,28 +248,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothMapClientServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothMapClient = (BluetoothMapClient) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java
index bdc5d42..0e5da68 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java
@@ -51,8 +51,8 @@
     private BluetoothMap mBluetoothMap;
     private boolean mIsMapSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -72,8 +72,8 @@
             mAdapter = manager.getAdapter();
             assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-            mProfileConnectedlock = new ReentrantLock();
-            mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+            mProfileConnectionlock = new ReentrantLock();
+            mConditionProfileConnection = mProfileConnectionlock.newCondition();
             mIsProfileReady = false;
             mBluetoothMap = null;
 
@@ -96,6 +96,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsMapSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothMap);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.MAP, mBluetoothMap);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsMapSupported)) return;
 
@@ -183,11 +195,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -197,28 +209,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothMapServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             try {
                 mBluetoothMap = (BluetoothMap) proxy;
                 mIsProfileReady = true;
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java
index 11954a3..aa4ca29 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java
@@ -46,8 +46,8 @@
     private BluetoothPan mBluetoothPan;
     private boolean mIsPanSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -66,8 +66,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothPan = null;
 
@@ -90,6 +90,18 @@
         TestUtils.dropPermissionAsShellUid();
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsPanSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothPan);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothPan);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsPanSupported)) return;
 
@@ -173,11 +185,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -187,27 +199,54 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothPanServiceListener implements BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothPan = (BluetoothPan) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java
index 1ce2b0b..dcdd677 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java
@@ -48,8 +48,8 @@
     private BluetoothPbapClient mBluetoothPbapClient;
     private boolean mIsPbapClientSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -68,8 +68,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothPbapClient = null;
 
@@ -92,6 +92,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsPbapClientSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothPbapClient);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.PBAP_CLIENT, mBluetoothPbapClient);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsPbapClientSupported)) return;
 
@@ -179,11 +191,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -193,28 +205,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothPbapClientServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothPbapClient = (BluetoothPbapClient) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
index fadffd9..05b6e91 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
@@ -49,8 +49,8 @@
     private BluetoothPbap mBluetoothPbap;
     private boolean mIsPbapSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     @Override
     public void setUp() throws Exception {
@@ -70,8 +70,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothPbap = null;
 
@@ -94,6 +94,18 @@
         mAdapter = null;
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsPbapSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothPbap);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.PBAP, mBluetoothPbap);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void test_getConnectedDevices() {
         if (!(mHasBluetooth && mIsPbapSupported)) return;
 
@@ -162,11 +174,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -176,28 +188,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothPbapServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             try {
                 mBluetoothPbap = (BluetoothPbap) proxy;
                 mIsProfileReady = true;
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothQualityReportTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothQualityReportTest.java
index dc033f2..649ac33 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothQualityReportTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothQualityReportTest.java
@@ -18,6 +18,11 @@
 
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothQualityReport;
+import android.bluetooth.BluetoothQualityReport.BqrCommon;
+import android.bluetooth.BluetoothQualityReport.BqrConnectFail;
+import android.bluetooth.BluetoothQualityReport.BqrVsA2dpChoppy;
+import android.bluetooth.BluetoothQualityReport.BqrVsLsto;
+import android.bluetooth.BluetoothQualityReport.BqrVsScoChoppy;
 import android.os.Parcel;
 import android.util.Log;
 
@@ -45,13 +50,15 @@
 
     private void assertBqrCommon(BQRParameters bqrp, BluetoothQualityReport bqr) {
         // BQR Common
-        BluetoothQualityReport.BqrCommon bqrCommon = bqr.getBqrCommon();
+        BqrCommon bqrCommon = bqr.getBqrCommon();
         Assert.assertNotNull(bqrCommon);
         Assert.assertEquals(bqr.getQualityReportId(), bqrp.getQualityReportId());
         Assert.assertEquals(bqrp.mPacketType, bqrCommon.getPacketType());
-        Assert.assertEquals("TYPE_NULL", bqrCommon.getPacketTypeString());
+        Assert.assertEquals("TYPE_NULL", BqrCommon.packetTypeToString(bqrCommon.getPacketType()));
         Assert.assertEquals(bqrp.mConnectionHandle, bqrCommon.getConnectionHandle());
-        Assert.assertTrue(bqrp.mConnectionRoleCentral.equals(bqrCommon.getConnectionRoleString()));
+        Assert.assertTrue(
+                bqrp.mConnectionRoleCentral.equals(
+                        BqrCommon.connectionRoleToString(bqrCommon.getConnectionRole())));
         Assert.assertEquals(bqrp.mConnectionRole, bqrCommon.getConnectionRole());
         Assert.assertEquals(bqrp.mTxPowerLevel, bqrCommon.getTxPowerLevel());
         Assert.assertEquals(bqrp.mRssi, bqrCommon.getRssi());
@@ -74,12 +81,14 @@
 
     private void assertBqrApproachLsto(BQRParameters bqrp, BluetoothQualityReport bqr) {
         // BQR VS LSTO
-        BluetoothQualityReport.BqrVsLsto bqrVsLsto =
-                (BluetoothQualityReport.BqrVsLsto) bqr.getBqrEvent();
+        BqrVsLsto bqrVsLsto = (BqrVsLsto) bqr.getBqrEvent();
         Assert.assertNotNull(bqrVsLsto);
-        Assert.assertEquals("Approaching LSTO", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "Approaching LSTO",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
         Assert.assertEquals(bqrp.mConnState & 0xFF, bqrVsLsto.getConnState());
-        Assert.assertEquals("CONN_UNPARK_ACTIVE", bqrVsLsto.getConnStateString());
+        Assert.assertEquals(
+                "CONN_UNPARK_ACTIVE", BqrVsLsto.connStateToString(bqrVsLsto.getConnState()));
         Assert.assertEquals(bqrp.mBasebandStats, bqrVsLsto.getBasebandStats());
         Assert.assertEquals(bqrp.mSlotsUsed, bqrVsLsto.getSlotsUsed());
         Assert.assertEquals(bqrp.mCxmDenials, bqrVsLsto.getCxmDenials());
@@ -92,10 +101,11 @@
 
     private void assertBqrA2dpChoppy(BQRParameters bqrp, BluetoothQualityReport bqr) {
         // BQR VS A2DP Choppy
-        BluetoothQualityReport.BqrVsA2dpChoppy bqrVsA2dpChoppy =
-                (BluetoothQualityReport.BqrVsA2dpChoppy) bqr.getBqrEvent();
+        BqrVsA2dpChoppy bqrVsA2dpChoppy = (BqrVsA2dpChoppy) bqr.getBqrEvent();
         Assert.assertNotNull(bqrVsA2dpChoppy);
-        Assert.assertEquals("A2DP choppy", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "A2DP choppy",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
         Assert.assertEquals(bqrp.mArrivalTime, bqrVsA2dpChoppy.getArrivalTime());
         Assert.assertEquals(bqrp.mScheduleTime, bqrVsA2dpChoppy.getScheduleTime());
         Assert.assertEquals(bqrp.mGlitchCountA2dp, bqrVsA2dpChoppy.getGlitchCount());
@@ -103,21 +113,24 @@
         Assert.assertEquals(bqrp.mRxCxmDenialsA2dp, bqrVsA2dpChoppy.getRxCxmDenials());
         Assert.assertEquals(bqrp.mAclTxQueueLength, bqrVsA2dpChoppy.getAclTxQueueLength());
         Assert.assertEquals(bqrp.mLinkQuality, bqrVsA2dpChoppy.getLinkQuality());
-        Assert.assertEquals("MEDIUM", bqrVsA2dpChoppy.getLinkQualityString());
+        Assert.assertEquals(
+                "MEDIUM", BqrVsA2dpChoppy.linkQualityToString(bqrVsA2dpChoppy.getLinkQuality()));
         Assert.assertEquals(0, bqrVsA2dpChoppy.describeContents());
     }
 
     private void assertBqrScoChoppy(BQRParameters bqrp, BluetoothQualityReport bqr) {
         // BQR VS SCO Choppy
-        BluetoothQualityReport.BqrVsScoChoppy bqrVsScoChoppy =
-                (BluetoothQualityReport.BqrVsScoChoppy) bqr.getBqrEvent();
+        BqrVsScoChoppy bqrVsScoChoppy = (BqrVsScoChoppy) bqr.getBqrEvent();
         Assert.assertNotNull(bqrVsScoChoppy);
-        Assert.assertEquals("SCO choppy", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "SCO choppy",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
         Assert.assertEquals(bqrp.mGlitchCountSco, bqrVsScoChoppy.getGlitchCount());
         Assert.assertEquals(bqrp.mIntervalEsco, bqrVsScoChoppy.getIntervalEsco());
         Assert.assertEquals(bqrp.mWindowEsco, bqrVsScoChoppy.getWindowEsco());
         Assert.assertEquals(bqrp.mAirFormat, bqrVsScoChoppy.getAirFormat());
-        Assert.assertEquals("CVSD", bqrVsScoChoppy.getAirFormatString());
+        Assert.assertEquals(
+                "CVSD", BqrVsScoChoppy.airFormatToString(bqrVsScoChoppy.getAirFormat()));
         Assert.assertEquals(bqrp.mInstanceCount, bqrVsScoChoppy.getInstanceCount());
         Assert.assertEquals(bqrp.mTxCxmDenialsSco, bqrVsScoChoppy.getTxCxmDenials());
         Assert.assertEquals(bqrp.mRxCxmDenialsSco, bqrVsScoChoppy.getRxCxmDenials());
@@ -137,10 +150,11 @@
 
     private void assertBqrConnectFail(BQRParameters bqrp, BluetoothQualityReport bqr) {
         // BQR VS Connect Fail
-        BluetoothQualityReport.BqrConnectFail bqrConnectFail =
-                (BluetoothQualityReport.BqrConnectFail) bqr.getBqrEvent();
+        BqrConnectFail bqrConnectFail = (BqrConnectFail) bqr.getBqrEvent();
         Assert.assertNotNull(bqrConnectFail);
-        Assert.assertEquals("Connect fail", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "Connect fail",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
         Assert.assertEquals(bqrp.mFailReason, bqrConnectFail.getFailReason());
         Assert.assertEquals(0, bqrConnectFail.describeContents());
     }
@@ -296,31 +310,28 @@
 
         assertBqrConnectFail(bqrp, bqr);
 
-        BluetoothQualityReport.BqrConnectFail bqrConnectFail =
-                (BluetoothQualityReport.BqrConnectFail) bqr.getBqrEvent();
+        BqrConnectFail bqrConnectFail = (BqrConnectFail) bqr.getBqrEvent();
         Assert.assertNotNull(bqrConnectFail);
 
         Assert.assertEquals(
                 "No error",
-                bqrConnectFail.getConnectFailIdString(
-                        BluetoothQualityReport.BqrConnectFail.CONNECT_FAIL_ID_NO_ERROR));
+                BqrConnectFail.connectFailIdToString(BqrConnectFail.CONNECT_FAIL_ID_NO_ERROR));
         Assert.assertEquals(
                 "Page Timeout",
-                bqrConnectFail.getConnectFailIdString(
-                        BluetoothQualityReport.BqrConnectFail.CONNECT_FAIL_ID_PAGE_TIMEOUT));
+                BqrConnectFail.connectFailIdToString(BqrConnectFail.CONNECT_FAIL_ID_PAGE_TIMEOUT));
         Assert.assertEquals(
                 "Connection Timeout",
-                bqrConnectFail.getConnectFailIdString(
-                        BluetoothQualityReport.BqrConnectFail.CONNECT_FAIL_ID_CONNECTION_TIMEOUT));
+                BqrConnectFail.connectFailIdToString(
+                        BqrConnectFail.CONNECT_FAIL_ID_CONNECTION_TIMEOUT));
         Assert.assertEquals(
                 "ACL already exists",
-                bqrConnectFail.getConnectFailIdString(
-                        BluetoothQualityReport.BqrConnectFail.CONNECT_FAIL_ID_ACL_ALREADY_EXIST));
+                BqrConnectFail.connectFailIdToString(
+                        BqrConnectFail.CONNECT_FAIL_ID_ACL_ALREADY_EXIST));
         Assert.assertEquals(
                 "Controller busy",
-                bqrConnectFail.getConnectFailIdString(
-                        BluetoothQualityReport.BqrConnectFail.CONNECT_FAIL_ID_CONTROLLER_BUSY));
-        Assert.assertEquals("INVALID", bqrConnectFail.getConnectFailIdString(0xFF));
+                BqrConnectFail.connectFailIdToString(
+                        BqrConnectFail.CONNECT_FAIL_ID_CONTROLLER_BUSY));
+        Assert.assertEquals("INVALID", BqrConnectFail.connectFailIdToString(0xFF));
     }
 
     @Test
@@ -518,22 +529,25 @@
                         mRemoteName,
                         mRemoteCoD);
 
-        Assert.assertEquals("Quality monitor", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "Quality monitor",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
 
         Parcel parcel = Parcel.obtain();
         bqr.getBqrCommon().writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        BluetoothQualityReport.BqrCommon bqrCommonFromParcel =
-                BluetoothQualityReport.BqrCommon.CREATOR.createFromParcel(parcel);
+        BqrCommon bqrCommonFromParcel = BqrCommon.CREATOR.createFromParcel(parcel);
 
         // BQR Common
         Assert.assertNotNull(bqrCommonFromParcel);
         Assert.assertEquals(bqrp.mPacketType, bqrCommonFromParcel.getPacketType());
-        Assert.assertEquals("TYPE_NULL", bqrCommonFromParcel.getPacketTypeString());
+        Assert.assertEquals(
+                "TYPE_NULL", BqrCommon.packetTypeToString(bqrCommonFromParcel.getPacketType()));
         Assert.assertEquals(bqrp.mConnectionHandle, bqrCommonFromParcel.getConnectionHandle());
         Assert.assertTrue(
-                bqrp.mConnectionRoleCentral.equals(bqrCommonFromParcel.getConnectionRoleString()));
+                bqrp.mConnectionRoleCentral.equals(
+                        BqrCommon.connectionRoleToString(bqrCommonFromParcel.getConnectionRole())));
         Assert.assertEquals(bqrp.mTxPowerLevel, bqrCommonFromParcel.getTxPowerLevel());
         Assert.assertEquals(bqrp.mRssi, bqrCommonFromParcel.getRssi());
         Assert.assertEquals(bqrp.mSnr, bqrCommonFromParcel.getSnr());
@@ -575,22 +589,24 @@
                         mRemoteName,
                         mRemoteCoD);
 
-        Assert.assertEquals("Approaching LSTO", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "Approaching LSTO",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
 
-        BluetoothQualityReport.BqrVsLsto bqrVsLsto =
-                (BluetoothQualityReport.BqrVsLsto) bqr.getBqrEvent();
+        BqrVsLsto bqrVsLsto = (BqrVsLsto) bqr.getBqrEvent();
         Assert.assertNotNull(bqrVsLsto);
         Parcel parcel = Parcel.obtain();
         bqrVsLsto.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        BluetoothQualityReport.BqrVsLsto bqrVsLstoFromParcel =
-                BluetoothQualityReport.BqrVsLsto.CREATOR.createFromParcel(parcel);
+        BqrVsLsto bqrVsLstoFromParcel = BqrVsLsto.CREATOR.createFromParcel(parcel);
 
         // BQR VS LSTO
         Assert.assertNotNull(bqrVsLstoFromParcel);
         Assert.assertEquals(bqrp.mConnState & 0xFF, bqrVsLstoFromParcel.getConnState());
-        Assert.assertEquals("CONN_UNPARK_ACTIVE", bqrVsLstoFromParcel.getConnStateString());
+        Assert.assertEquals(
+                "CONN_UNPARK_ACTIVE",
+                BqrVsLsto.connStateToString(bqrVsLstoFromParcel.getConnState()));
         Assert.assertEquals(bqrp.mBasebandStats, bqrVsLstoFromParcel.getBasebandStats());
         Assert.assertEquals(bqrp.mSlotsUsed, bqrVsLstoFromParcel.getSlotsUsed());
         Assert.assertEquals(bqrp.mCxmDenials, bqrVsLstoFromParcel.getCxmDenials());
@@ -621,17 +637,18 @@
                         mRemoteName,
                         mRemoteCoD);
 
-        Assert.assertEquals("A2DP choppy", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "A2DP choppy",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
 
-        BluetoothQualityReport.BqrVsA2dpChoppy bqrVsA2dpChoppy =
-                (BluetoothQualityReport.BqrVsA2dpChoppy) bqr.getBqrEvent();
+        BqrVsA2dpChoppy bqrVsA2dpChoppy = (BqrVsA2dpChoppy) bqr.getBqrEvent();
         Assert.assertNotNull(bqrVsA2dpChoppy);
         Parcel parcel = Parcel.obtain();
         bqrVsA2dpChoppy.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        BluetoothQualityReport.BqrVsA2dpChoppy bqrVsA2dpChoppyFromParcel =
-                BluetoothQualityReport.BqrVsA2dpChoppy.CREATOR.createFromParcel(parcel);
+        BqrVsA2dpChoppy bqrVsA2dpChoppyFromParcel =
+                BqrVsA2dpChoppy.CREATOR.createFromParcel(parcel);
 
         // BQR VS A2DP Choppy
         Assert.assertNotNull(bqrVsA2dpChoppyFromParcel);
@@ -643,7 +660,9 @@
         Assert.assertEquals(
                 bqrp.mAclTxQueueLength, bqrVsA2dpChoppyFromParcel.getAclTxQueueLength());
         Assert.assertEquals(bqrp.mLinkQuality, bqrVsA2dpChoppyFromParcel.getLinkQuality());
-        Assert.assertEquals("MEDIUM", bqrVsA2dpChoppyFromParcel.getLinkQualityString());
+        Assert.assertEquals(
+                "MEDIUM",
+                BqrVsA2dpChoppy.linkQualityToString(bqrVsA2dpChoppyFromParcel.getLinkQuality()));
         Assert.assertEquals(0, bqrVsA2dpChoppyFromParcel.describeContents());
     }
 
@@ -666,17 +685,17 @@
                         mRemoteName,
                         mRemoteCoD);
 
-        Assert.assertEquals("SCO choppy", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "SCO choppy",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
 
-        BluetoothQualityReport.BqrVsScoChoppy bqrVsScoChoppy =
-                (BluetoothQualityReport.BqrVsScoChoppy) bqr.getBqrEvent();
+        BqrVsScoChoppy bqrVsScoChoppy = (BqrVsScoChoppy) bqr.getBqrEvent();
         Assert.assertNotNull(bqrVsScoChoppy);
         Parcel parcel = Parcel.obtain();
         bqrVsScoChoppy.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        BluetoothQualityReport.BqrVsScoChoppy bqrVsScoChoppyFromParcel =
-                BluetoothQualityReport.BqrVsScoChoppy.CREATOR.createFromParcel(parcel);
+        BqrVsScoChoppy bqrVsScoChoppyFromParcel = BqrVsScoChoppy.CREATOR.createFromParcel(parcel);
 
         // BQR VS SCO Choppy
         Assert.assertNotNull(bqrVsScoChoppyFromParcel);
@@ -684,7 +703,8 @@
         Assert.assertEquals(bqrp.mIntervalEsco, bqrVsScoChoppyFromParcel.getIntervalEsco());
         Assert.assertEquals(bqrp.mWindowEsco, bqrVsScoChoppyFromParcel.getWindowEsco());
         Assert.assertEquals(bqrp.mAirFormat, bqrVsScoChoppyFromParcel.getAirFormat());
-        Assert.assertEquals("CVSD", bqrVsScoChoppyFromParcel.getAirFormatString());
+        Assert.assertEquals(
+                "CVSD", BqrVsScoChoppy.airFormatToString(bqrVsScoChoppyFromParcel.getAirFormat()));
         Assert.assertEquals(bqrp.mInstanceCount, bqrVsScoChoppyFromParcel.getInstanceCount());
         Assert.assertEquals(bqrp.mTxCxmDenialsSco, bqrVsScoChoppyFromParcel.getTxCxmDenials());
         Assert.assertEquals(bqrp.mRxCxmDenialsSco, bqrVsScoChoppyFromParcel.getRxCxmDenials());
@@ -725,17 +745,17 @@
                         mRemoteName,
                         mRemoteCoD);
 
-        Assert.assertEquals("Connect fail", bqr.getQualityReportIdString());
+        Assert.assertEquals(
+                "Connect fail",
+                BluetoothQualityReport.qualityReportIdToString(bqr.getQualityReportId()));
 
-        BluetoothQualityReport.BqrConnectFail bqrConnectFail =
-                (BluetoothQualityReport.BqrConnectFail) bqr.getBqrEvent();
+        BqrConnectFail bqrConnectFail = (BqrConnectFail) bqr.getBqrEvent();
         Assert.assertNotNull(bqrConnectFail);
         Parcel parcel = Parcel.obtain();
         bqrConnectFail.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        BluetoothQualityReport.BqrConnectFail bqrConnFailFromParcel =
-                BluetoothQualityReport.BqrConnectFail.CREATOR.createFromParcel(parcel);
+        BqrConnectFail bqrConnFailFromParcel = BqrConnectFail.CREATOR.createFromParcel(parcel);
 
         // BQR VS Connect Fail
         Assert.assertNotNull(bqrConnFailFromParcel);
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
index 9dad13a..6da4b9a 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
@@ -48,8 +48,8 @@
 
     private BluetoothSap mBluetoothSap;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
 
     private boolean mIsSapSupported;
 
@@ -70,8 +70,8 @@
         mAdapter = getContext().getSystemService(BluetoothManager.class).getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothSap = null;
 
@@ -93,6 +93,18 @@
         }
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mHasBluetooth && mIsSapSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothSap);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.SAP, mBluetoothSap);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     @MediumTest
     public void test_getConnectedDevices() {
         if (!mHasBluetooth || !mIsSapSupported) return;
@@ -157,11 +169,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -171,27 +183,54 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothSapServiceListener implements BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothSap = (BluetoothSap) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSocketExceptionTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSocketExceptionTest.java
new file mode 100644
index 0000000..293bb4d
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSocketExceptionTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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.bluetooth.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.bluetooth.BluetoothSocketException;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/** Unit test to test APIs and functionality for {@link BluetoothSocketException}. */
+public final class BluetoothSocketExceptionTest extends AndroidTestCase {
+
+    @SmallTest
+    public void test_getErrorCode_returnsCorrectErrorCode() {
+        BluetoothSocketException exception =
+                new BluetoothSocketException(BluetoothSocketException.SOCKET_CONNECTION_FAILURE);
+
+        assertEquals(exception.getErrorCode(), BluetoothSocketException.SOCKET_CONNECTION_FAILURE);
+    }
+
+    @SmallTest
+    public void test_getMessage_returnsCustomErrorMsg() {
+        String customErrMsg = "This is a custom error message";
+        BluetoothSocketException exception =
+                new BluetoothSocketException(BluetoothSocketException.UNSPECIFIED, customErrMsg);
+
+        assertEquals(exception.getMessage(), customErrMsg);
+    }
+
+    @SmallTest
+    public void test_getMessage_returnsErrorMsgWhenOnlyCodeIsProvided() {
+        BluetoothSocketException exception =
+                new BluetoothSocketException(BluetoothSocketException.UNSPECIFIED);
+
+        assertNotNull(exception.getMessage());
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java
index 32eeb02..09c4308 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java
@@ -47,8 +47,8 @@
     private BluetoothVolumeControl mBluetoothVolumeControl;
     private boolean mIsVolumeControlSupported;
     private boolean mIsProfileReady;
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
     private boolean mVolumeOffsetChangedCallbackCalled;
     private TestCallback mTestCallback;
     private Executor mTestExecutor;
@@ -78,8 +78,8 @@
         mAdapter = manager.getAdapter();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mBluetoothVolumeControl = null;
 
@@ -122,6 +122,18 @@
         }
     }
 
+    public void testCloseProfileProxy() {
+        if (!(mHasBluetooth && mIsVolumeControlSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothVolumeControl);
+        assertTrue(mIsProfileReady);
+
+        mAdapter.closeProfileProxy(BluetoothProfile.VOLUME_CONTROL, mBluetoothVolumeControl);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     public void testGetConnectedDevices() {
         if (!(mHasBluetooth && mIsVolumeControlSupported)) return;
 
@@ -287,11 +299,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                         PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -301,28 +313,55 @@
         } catch (InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class BluetoothVolumeControlServiceListener implements
             BluetoothProfile.ServiceListener {
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mBluetoothVolumeControl = (BluetoothVolumeControl) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         @Override
         public void onServiceDisconnected(int profile) {
+            mProfileConnectionlock.lock();
+            mIsProfileReady = false;
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementManagerTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementManagerTest.java
index cf07c0b..9d02b46 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementManagerTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementManagerTest.java
@@ -102,7 +102,7 @@
     @Test
     public void testStartMeasurementSession() {
         DistanceMeasurementParams params = new DistanceMeasurementParams.Builder(mDevice)
-                .setDuration(15)
+                .setDurationSeconds(15)
                 .setFrequency(DistanceMeasurementParams.REPORT_FREQUENCY_LOW)
                 .build();
         CancellationSignal signal = mDistanceMeasurementManager.startMeasurementSession(params,
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementParamsTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementParamsTest.java
index ce20091..b886a82 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementParamsTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementParamsTest.java
@@ -107,9 +107,10 @@
             return;
         }
         DistanceMeasurementParams params = new DistanceMeasurementParams.Builder(mDevice).build();
-        assertEquals(DistanceMeasurementParams.getDefaultDuration(), params.getDuration());
+        assertEquals(DistanceMeasurementParams.getDefaultDurationSeconds(),
+                params.getDurationSeconds());
         assertEquals(REPORT_FREQUENCY_LOW, params.getFrequency());
-        assertEquals(DISTANCE_MEASUREMENT_METHOD_RSSI, params.getMethod());
+        assertEquals(DISTANCE_MEASUREMENT_METHOD_RSSI, params.getMethodId());
     }
 
     @Test
@@ -122,13 +123,13 @@
     }
 
     @Test
-    public void testSetGetDuration() {
+    public void testSetGetDurationSeconds() {
         if (shouldSkipTest()) {
             return;
         }
         DistanceMeasurementParams params = new DistanceMeasurementParams.Builder(mDevice)
-                .setDuration(120).build();
-        assertEquals(120, params.getDuration());
+                .setDurationSeconds(120).build();
+        assertEquals(120, params.getDurationSeconds());
     }
 
     @Test
@@ -142,13 +143,13 @@
     }
 
     @Test
-    public void testSetGetMethod() {
+    public void testSetGetMethodId() {
         if (shouldSkipTest()) {
             return;
         }
         DistanceMeasurementParams params = new DistanceMeasurementParams.Builder(mDevice)
-                .setMethod(DISTANCE_MEASUREMENT_METHOD_RSSI).build();
-        assertEquals(DISTANCE_MEASUREMENT_METHOD_RSSI, params.getMethod());
+                .setMethodId(DISTANCE_MEASUREMENT_METHOD_RSSI).build();
+        assertEquals(DISTANCE_MEASUREMENT_METHOD_RSSI, params.getMethodId());
     }
 
 
@@ -162,9 +163,9 @@
         }
 
         assertEquals(p.getDevice(), other.getDevice());
-        assertEquals(p.getDuration(), other.getDuration());
+        assertEquals(p.getDurationSeconds(), other.getDurationSeconds());
         assertEquals(p.getFrequency(), other.getFrequency());
-        assertEquals(p.getMethod(), other.getMethod());
+        assertEquals(p.getMethodId(), other.getMethodId());
     }
 
     private boolean shouldSkipTest() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementResultTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementResultTest.java
index 2a798d1..74b08aa 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementResultTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/DistanceMeasurementResultTest.java
@@ -99,13 +99,13 @@
     }
 
     @Test
-    public void testSetGetMeters() {
+    public void testSetGetResultMeters() {
         if (shouldSkipTest()) {
             return;
         }
         DistanceMeasurementResult result = new DistanceMeasurementResult.Builder(121.0, 120.0)
                 .build();
-        assertEquals(121.0, result.getMeters(), 0.0);
+        assertEquals(121.0, result.getResultMeters(), 0.0);
     }
 
     @Test
@@ -183,7 +183,7 @@
             fail("Cannot compare null with non-null value: p=" + p + ", other=" + other);
         }
 
-        assertEquals(p.getMeters(), other.getMeters(), 0.0);
+        assertEquals(p.getResultMeters(), other.getResultMeters(), 0.0);
         assertEquals(p.getErrorMeters(), other.getErrorMeters(), 0.0);
         assertEquals(p.getAzimuthAngle(), other.getAzimuthAngle(), 0.0);
         assertEquals(p.getErrorAzimuthAngle(), other.getErrorAzimuthAngle(), 0.0);
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
index 5da724c..253751d 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
@@ -17,6 +17,8 @@
 package android.bluetooth.cts;
 
 import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
 
 import static org.junit.Assert.assertThrows;
 
@@ -72,8 +74,8 @@
     private BroadcastReceiver mIntentReceiver;
     private UiAutomation mUiAutomation;;
 
-    private Condition mConditionProfileIsConnected;
-    private ReentrantLock mProfileConnectedlock;
+    private Condition mConditionProfileConnection;
+    private ReentrantLock mProfileConnectionlock;
     private boolean mIsProfileReady;
     private AdvertisementServiceData mAdvertisementData;
 
@@ -98,8 +100,8 @@
         mBluetoothAdapter = manager.getAdapter();
 
         assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
-        mProfileConnectedlock = new ReentrantLock();
-        mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+        mProfileConnectionlock = new ReentrantLock();
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
         mIsProfileReady = false;
         mService = null;
         mBluetoothAdapter.getProfileProxy(getContext(), new HearingAidsServiceListener(),
@@ -121,6 +123,18 @@
         mUiAutomation.dropShellPermissionIdentity();
     }
 
+    public void test_closeProfileProxy() {
+        if (!(mIsBleSupported && mIsHearingAidSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mService);
+        assertTrue(mIsProfileReady);
+
+        mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEARING_AID, mService);
+        assertTrue(waitForProfileDisconnect());
+        assertFalse(mIsProfileReady);
+    }
+
     /**
      * Basic test case to make sure that Hearing Aid Profile Proxy can connect.
      */
@@ -219,7 +233,7 @@
 
     /**
      * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data
-     * is an error.
+     * is null.
      */
     @MediumTest
     public void test_getAdvertisementServiceData() {
@@ -235,6 +249,8 @@
         final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
         assertNotNull(device);
 
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED);
+
         // Fake device should have no service data
         assertNull(mService.getAdvertisementServiceData(device));
     }
@@ -283,7 +299,28 @@
         assertEquals(BluetoothHearingAid.SIDE_LEFT, side);
     }
 
+    /**
+     * Basic test case to make sure that a fictional device's truncated HiSyncId is the
+     * expected value.
+     */
+    @MediumTest
+    public void test_getTruncatedHiSyncId() {
+        if (!(mIsBleSupported && mIsHearingAidSupported)) {
+            return;
+        }
 
+        waitForProfileConnect();
+        assertTrue(mIsProfileReady);
+        assertNotNull(mService);
+
+        // Create a fake advertisement data
+        AdvertisementServiceData data = mAdvertisementData;
+        assertNotNull(data);
+
+        final int id = data.getTruncatedHiSyncId();
+        // Fake device should be supported
+        assertEquals(1, id);
+    }
 
     /**
      * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data's CSIP
@@ -308,7 +345,6 @@
         assertEquals(true, supported);
     }
 
-
     /**
      * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data's CSIP
      * is not supported.
@@ -450,11 +486,11 @@
     }
 
     private boolean waitForProfileConnect() {
-        mProfileConnectedlock.lock();
+        mProfileConnectionlock.lock();
         try {
             // Wait for the Adapter to be disabled
             while (!mIsProfileReady) {
-                if (!mConditionProfileIsConnected.await(
+                if (!mConditionProfileConnection.await(
                     PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                     // Timeout
                     Log.e(TAG, "Timeout while waiting for Profile Connect");
@@ -464,30 +500,54 @@
         } catch(InterruptedException e) {
             Log.e(TAG, "waitForProfileConnect: interrrupted");
         } finally {
-            mProfileConnectedlock.unlock();
+            mProfileConnectionlock.unlock();
         }
         return mIsProfileReady;
     }
 
+    private boolean waitForProfileDisconnect() {
+        mConditionProfileConnection = mProfileConnectionlock.newCondition();
+        mProfileConnectionlock.lock();
+        try {
+            while (mIsProfileReady) {
+                if (!mConditionProfileConnection.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+        } finally {
+            mProfileConnectionlock.unlock();
+        }
+        return !mIsProfileReady;
+    }
+
     private final class HearingAidsServiceListener
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mService = (BluetoothHearingAid) proxy;
             mIsProfileReady = true;
             try {
-                mConditionProfileIsConnected.signal();
+                mConditionProfileConnection.signal();
             } finally {
-                mProfileConnectedlock.unlock();
+                mProfileConnectionlock.unlock();
             }
         }
 
         public void onServiceDisconnected(int profile) {
-            mProfileConnectedlock.lock();
+            mProfileConnectionlock.lock();
             mIsProfileReady = false;
             mService = null;
-            mProfileConnectedlock.unlock();
+            try {
+                mConditionProfileConnection.signal();
+            } finally {
+                mProfileConnectionlock.unlock();
+            }
         }
     }
 
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java
index 6bf37fc..4706bc0 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java
@@ -342,7 +342,7 @@
                 .setTdsFlags(tdsFlag, tdsFlagMask)
                 .setTransportData(transportData, transportDataMask).build();
 
-        if (mBluetoothAdapter.isOffloadedTransportDiscoveryDataScanSupported()
+        if (mBluetoothAdapter.getOffloadedTransportDiscoveryDataScanSupported()
                 != FEATURE_SUPPORTED) {
             assertThrows(IllegalArgumentException.class,
                     () -> mFilterBuilder.setTransportBlockFilter(transportBlockFilter));
diff --git a/tests/tests/car/AndroidManifest.xml b/tests/tests/car/AndroidManifest.xml
index 06c83bd..89a270d 100644
--- a/tests/tests/car/AndroidManifest.xml
+++ b/tests/tests/car/AndroidManifest.xml
@@ -25,6 +25,7 @@
     <uses-permission android:name="android.car.permission.CAR_SPEED" />
     <uses-permission android:name="android.car.permission.CONTROL_CAR_DISPLAY_UNITS" />
     <uses-permission android:name="android.car.permission.READ_CAR_DISPLAY_UNITS" />
+    <uses-permission android:name="android.car.permission.CAR_TEST_SERVICE" />
     <uses-permission android:name="android.car.permission.READ_CAR_POWER_POLICY" />
     <uses-permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/tests/tests/car/OWNERS b/tests/tests/car/OWNERS
index f4d9c58..eab9637 100644
--- a/tests/tests/car/OWNERS
+++ b/tests/tests/car/OWNERS
@@ -2,9 +2,9 @@
 include platform/packages/services/Car:/OWNERS
 
 # Vehicle property related CTS files
-per-file src/android/car/cts/CarPropertyManagerTest.java = shanyu@google.com
-per-file src/android/car/cts/VehiclePropertyIdsTest.java = shanyu@google.com
-per-file src/android/car/cts/utils/VehiclePropertyVerifier.java = shanyu@google.com
+per-file src/android/car/cts/CarPropertyManagerTest.java = shanyu@google.com, tylertrephan@google.com
+per-file src/android/car/cts/VehiclePropertyIdsTest.java = shanyu@google.com, tylertrephan@google.com
+per-file src/android/car/cts/utils/VehiclePropertyVerifier.java = shanyu@google.com, tylertrephan@google.com
 
 # Audio related CTS files
 per-file src/android/car/cts/CarAudioManagerTest.java = oscarazu@google.com
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index 99e1af0..a1707c2 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -1714,6 +1714,90 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig"})
+    public void testSeatMemorySelectIfSupported() {
+        adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> {
+            VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_MEMORY_SELECT,
+                            CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
+                            VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
+                            CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                            Integer.class).requireMinMaxValues().requireMinValuesToBeZero()
+                    .setCarPropertyConfigVerifier(carPropertyConfig -> {
+                        int[] areaIds = carPropertyConfig.getAreaIds();
+                        CarPropertyConfig<?> seatMemorySetCarPropertyConfig =
+                                mCarPropertyManager.getCarPropertyConfig(
+                                        VehiclePropertyIds.SEAT_MEMORY_SET);
+
+                        assertWithMessage("SEAT_MEMORY_SET must be implemented if "
+                                + "SEAT_MEMORY_SELECT is implemented").that(
+                                        seatMemorySetCarPropertyConfig).isNotNull();
+
+                        assertWithMessage("SEAT_MEMORY_SELECT area IDs must match the area IDs of "
+                                + "SEAT_MEMORY_SET").that(Arrays.stream(areaIds).boxed().collect(
+                                        Collectors.toList()))
+                                .containsExactlyElementsIn(Arrays.stream(
+                                        seatMemorySetCarPropertyConfig.getAreaIds()).boxed()
+                                        .collect(Collectors.toList()));
+
+                        for (int areaId : areaIds) {
+                            Integer seatMemorySetAreaIdMaxValue =
+                                    (Integer) seatMemorySetCarPropertyConfig.getMaxValue(areaId);
+                            assertWithMessage("SEAT_MEMORY_SET - area ID: " + areaId
+                                    + " must have max value defined")
+                                    .that(seatMemorySetAreaIdMaxValue).isNotNull();
+                            assertWithMessage("SEAT_MEMORY_SELECT - area ID: " + areaId
+                                    + "'s max value must be equal to SEAT_MEMORY_SET's max value"
+                                    + " under the same area ID")
+                                    .that(seatMemorySetAreaIdMaxValue)
+                                    .isEqualTo(carPropertyConfig.getMaxValue(areaId));
+                        }
+                    }).build().verify(mCarPropertyManager);
+        });
+    }
+
+    @Test
+    @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig"})
+    public void testSeatMemorySetIfSupported() {
+        adoptSystemLevelPermission(Car.PERMISSION_CONTROL_CAR_SEATS, () -> {
+            VehiclePropertyVerifier.newBuilder(VehiclePropertyIds.SEAT_MEMORY_SET,
+                            CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
+                            VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
+                            CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
+                            Integer.class).requireMinMaxValues().requireMinValuesToBeZero()
+                    .setCarPropertyConfigVerifier(carPropertyConfig -> {
+                        int[] areaIds = carPropertyConfig.getAreaIds();
+                        CarPropertyConfig<?> seatMemorySelectCarPropertyConfig =
+                                mCarPropertyManager.getCarPropertyConfig(
+                                        VehiclePropertyIds.SEAT_MEMORY_SELECT);
+
+                        assertWithMessage("SEAT_MEMORY_SELECT must be implemented if "
+                                + "SEAT_MEMORY_SET is implemented").that(
+                                seatMemorySelectCarPropertyConfig).isNotNull();
+
+                        assertWithMessage("SEAT_MEMORY_SET area IDs must match the area IDs of "
+                                + "SEAT_MEMORY_SELECT").that(Arrays.stream(areaIds).boxed().collect(
+                                        Collectors.toList()))
+                                .containsExactlyElementsIn(Arrays.stream(
+                                        seatMemorySelectCarPropertyConfig.getAreaIds()).boxed()
+                                        .collect(Collectors.toList()));
+
+                        for (int areaId : areaIds) {
+                            Integer seatMemorySelectAreaIdMaxValue =
+                                    (Integer) seatMemorySelectCarPropertyConfig.getMaxValue(areaId);
+                            assertWithMessage("SEAT_MEMORY_SELECT - area ID: " + areaId
+                                    + " must have max value defined")
+                                    .that(seatMemorySelectAreaIdMaxValue).isNotNull();
+                            assertWithMessage("SEAT_MEMORY_SET - area ID: " + areaId
+                                    + "'s max value must be equal to SEAT_MEMORY_SELECT's max value"
+                                    + " under the same area ID")
+                                    .that(seatMemorySelectAreaIdMaxValue)
+                                    .isEqualTo(carPropertyConfig.getMaxValue(areaId));
+                        }
+                    }).build().verify(mCarPropertyManager);
+        });
+    }
+
+    @Test
     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getCarPropertyConfig",
             "android.car.hardware.property.CarPropertyManager#getProperty",
             "android.car.hardware.property.CarPropertyManager#setProperty",
@@ -2199,14 +2283,22 @@
                                     powerDependentProperty)).that(
                             powerDependentCarPropertyConfig.getAreaType()).isEqualTo(
                             VehicleAreaType.VEHICLE_AREA_TYPE_SEAT);
-                    assertWithMessage(
-                            "HVAC_POWER_ON's area IDs must match the area IDs of power dependent "
-                                    + "property: " + VehiclePropertyIds.toString(
-                                    powerDependentProperty)).that(Arrays.stream(
-                            powerDependentCarPropertyConfig.getAreaIds()).boxed().collect(
-                            Collectors.toList())).containsExactlyElementsIn(Arrays.stream(
-                            hvacPowerOnCarPropertyConfig.getAreaIds()).boxed().collect(
-                            Collectors.toList()));
+                    for (int powerDependentAreaId : powerDependentCarPropertyConfig.getAreaIds()) {
+                        boolean powerDependentAreaIdIsContained = false;
+                        for (int hvacPowerOnAreaId : hvacPowerOnCarPropertyConfig.getAreaIds()) {
+                            if ((powerDependentAreaId & hvacPowerOnAreaId)
+                                    == powerDependentAreaId) {
+                                powerDependentAreaIdIsContained = true;
+                                break;
+                            }
+                        }
+                        assertWithMessage(
+                                "HVAC_POWER_ON's area IDs must contain the area IDs"
+                                        + " of power dependent property: "
+                                        + VehiclePropertyIds.toString(
+                                        powerDependentProperty)).that(
+                                        powerDependentAreaIdIsContained).isTrue();
+                    }
                 }
             }).build().verify(mCarPropertyManager);
         });
diff --git a/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java b/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
index 4c8b862..3948687 100644
--- a/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
+++ b/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
@@ -50,7 +50,6 @@
 
 import org.junit.Before;
 import org.junit.Rule;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import java.io.BufferedReader;
@@ -83,7 +82,6 @@
     @IgnoreInvalidApi(reason = "Class not in classpath as it's indirectly tested using dumpsys")
     @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_0,
             minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0)
-    @Ignore("b/234674080")
     public void testCarServiceHelperServiceDump() throws Exception {
         assumeSystemServerDumpSupported();
 
diff --git a/tests/tests/car/src/android/car/cts/CarVersionTest.java b/tests/tests/car/src/android/car/cts/CarVersionTest.java
index 4317a0b..8ce6681 100644
--- a/tests/tests/car/src/android/car/cts/CarVersionTest.java
+++ b/tests/tests/car/src/android/car/cts/CarVersionTest.java
@@ -94,6 +94,38 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.car.CarVersion.VERSION_CODES#TIRAMISU_2"})
+    public void testTiramisu_2() {
+        CarVersion version = CarVersion.VERSION_CODES.TIRAMISU_2;
+
+        assertWithMessage("TIRAMISU_2").that(version).isNotNull();
+        expectWithMessage("TIRAMISU_2.major").that(version.getMajorVersion())
+                .isEqualTo(TIRAMISU);
+        expectWithMessage("TIRAMISU_2.minor").that(version.getMinorVersion())
+                .isEqualTo(2);
+
+        CarVersion fromEnum = ApiRequirements.CarVersion.TIRAMISU_2.get();
+        assertWithMessage("TIRAMISU_2 from enum").that(fromEnum).isNotNull();
+        expectWithMessage("TIRAMISU_2 from enum").that(fromEnum).isSameInstanceAs(version);
+
+        String toString = version.toString();
+        expectWithMessage("TIRAMISU_2.toString()").that(toString)
+                .matches(".*CarVersion.*name=TIRAMISU_2.*major=" + TIRAMISU + ".*minor=2.*");
+        CarVersion clone = clone(version);
+        expectWithMessage("TIRAMISU_2.toString() from parcel").that(clone.toString())
+                .isEqualTo(toString);
+
+        CarVersion anonymous = CarVersion.forMajorAndMinorVersions(version.getMajorVersion(),
+                version.getMinorVersion());
+        expectWithMessage("TIRAMISU_2").that(version).isEqualTo(anonymous);
+        expectWithMessage("anonymous").that(anonymous).isEqualTo(version);
+        expectWithMessage("TIRAMISU_2's hashcode").that(version.hashCode())
+                .isEqualTo(anonymous.hashCode());
+        expectWithMessage("anonymous' hashcode").that(anonymous.hashCode())
+                .isEqualTo(version.hashCode());
+    }
+
+    @Test
     @ApiTest(apis = {"android.car.CarVersion#CREATOR"})
     public void testMarshalling() {
         CarVersion original = CarVersion.forMajorAndMinorVersions(66, 6);
diff --git a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
index e58aa1f..6b1869c 100644
--- a/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
+++ b/tests/tests/car/src/android/car/cts/utils/VehiclePropertyVerifier.java
@@ -91,6 +91,7 @@
     private final Optional<ConfigArrayVerifier> mConfigArrayVerifier;
     private final Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier;
     private final Optional<AreaIdsVerifier> mAreaIdsVerifier;
+    private final Optional<CarPropertyConfigVerifier> mCarPropertyConfigVerifier;
     private final ImmutableSet<Integer> mPossibleConfigArrayValues;
     private final ImmutableSet<T> mPossibleCarPropertyValues;
     private final boolean mRequirePropertyValueToBeInConfigArray;
@@ -105,6 +106,7 @@
             Optional<ConfigArrayVerifier> configArrayVerifier,
             Optional<CarPropertyValueVerifier> carPropertyValueVerifier,
             Optional<AreaIdsVerifier> areaIdsVerifier,
+            Optional<CarPropertyConfigVerifier> carPropertyConfigVerifier,
             ImmutableSet<Integer> possibleConfigArrayValues,
             ImmutableSet<T> possibleCarPropertyValues,
             boolean requirePropertyValueToBeInConfigArray,
@@ -123,6 +125,7 @@
         mConfigArrayVerifier = configArrayVerifier;
         mCarPropertyValueVerifier = carPropertyValueVerifier;
         mAreaIdsVerifier = areaIdsVerifier;
+        mCarPropertyConfigVerifier = carPropertyConfigVerifier;
         mPossibleConfigArrayValues = possibleConfigArrayValues;
         mPossibleCarPropertyValues = possibleCarPropertyValues;
         mRequirePropertyValueToBeInConfigArray = requirePropertyValueToBeInConfigArray;
@@ -203,7 +206,8 @@
                     carPropertyManager.getCarPropertyConfig(VehiclePropertyIds.HVAC_POWER_ON);
             if (hvacPowerOnCarPropertyConfig != null
                     && hvacPowerOnCarPropertyConfig.getConfigArray().contains(mPropertyId)) {
-                turnOnHvacPower(carPropertyManager, hvacPowerOnCarPropertyConfig);
+                turnOnHvacPower(carPropertyManager,
+                        (CarPropertyConfig<Boolean>) hvacPowerOnCarPropertyConfig);
             }
         }
 
@@ -213,20 +217,20 @@
     }
 
     private void turnOnHvacPower(CarPropertyManager carPropertyManager,
-            CarPropertyConfig<?> hvacPowerOnCarPropertyConfig) {
+            CarPropertyConfig<Boolean> hvacPowerOnCarPropertyConfig) {
         for (int areaId : hvacPowerOnCarPropertyConfig.getAreaIds()) {
             if (carPropertyManager.getProperty(VehiclePropertyIds.HVAC_POWER_ON,
                     areaId).getValue().equals(true)) {
                 continue;
             }
-            verifySetProperty((CarPropertyConfig<Boolean>) hvacPowerOnCarPropertyConfig,
-                    carPropertyManager, areaId, Boolean.TRUE);
+            setPropertyAndWaitForChange(carPropertyManager, VehiclePropertyIds.HVAC_POWER_ON,
+                    hvacPowerOnCarPropertyConfig.getPropertyType(), areaId, Boolean.TRUE);
         }
     }
 
     private void verifyCarPropertyValueSetter(CarPropertyConfig<?> carPropertyConfig,
             CarPropertyManager carPropertyManager) {
-        if (carPropertyConfig.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ) {
+        if (carPropertyConfig.getAccess() != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
             return;
         }
         if (Boolean.class.equals(carPropertyConfig.getPropertyType())) {
@@ -278,7 +282,7 @@
     private void verifySetterWithMinMaxValues(CarPropertyConfig<?> carPropertyConfig,
             CarPropertyManager carPropertyManager) {
         for (int areaId : carPropertyConfig.getAreaIds()) {
-            if (carPropertyConfig.getMinValue(areaId) == null || carPropertyConfig.getMinValue(
+            if (carPropertyConfig.getMinValue(areaId) == null || carPropertyConfig.getMaxValue(
                     areaId) == null) {
                 continue;
             }
@@ -304,29 +308,25 @@
 
     private <T> void verifySetProperty(CarPropertyConfig<T> carPropertyConfig,
             CarPropertyManager carPropertyManager, int areaId, T valueToSet) {
-        CarPropertyValue<T> currentCarPropertyValue = carPropertyManager.getProperty(
-                mPropertyId, areaId);
+        CarPropertyValue<T> currentCarPropertyValue = carPropertyManager.getProperty(mPropertyId,
+                areaId);
         verifyCarPropertyValue(carPropertyConfig, currentCarPropertyValue, areaId,
                 CAR_PROPERTY_VALUE_SOURCE_GETTER);
         if (valueEquals(valueToSet, currentCarPropertyValue.getValue())) {
             return;
         }
-        SetterCallback setterCallback = new SetterCallback(mPropertyId, mPropertyName, areaId,
+        CarPropertyValue<T> updatedCarPropertyValue = setPropertyAndWaitForChange(
+                carPropertyManager, mPropertyId, carPropertyConfig.getPropertyType(), areaId,
                 valueToSet);
-        assertWithMessage("Failed to register setter callback for " + mPropertyName).that(
-                carPropertyManager.registerCallback(setterCallback, mPropertyId,
-                        CarPropertyManager.SENSOR_RATE_FASTEST)).isTrue();
-        carPropertyManager.setProperty(carPropertyConfig.getPropertyType(), mPropertyId, areaId,
-                valueToSet);
-        CarPropertyValue<?> updatedCarPropertyValue =
-                setterCallback.waitForUpdatedCarPropertyValue();
         verifyCarPropertyValue(carPropertyConfig, updatedCarPropertyValue, areaId,
                 CAR_PROPERTY_VALUE_SOURCE_CALLBACK);
-        carPropertyManager.unregisterCallback(setterCallback, mPropertyId);
     }
 
     private void verifyCarPropertyValueCallback(CarPropertyConfig<?> carPropertyConfig,
             CarPropertyManager carPropertyManager) {
+        if (carPropertyConfig.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE) {
+            return;
+        }
         int updatesPerAreaId = 1;
         long timeoutMillis = 1500;
         if (mChangeMode == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) {
@@ -393,9 +393,8 @@
                 carPropertyConfig.getAreaIds())).that(ImmutableSet.copyOf(Arrays.stream(
                 carPropertyConfig.getAreaIds()).boxed().collect(Collectors.toList())).size()
                 == carPropertyConfig.getAreaIds().length).isTrue();
-        if (mAreaIdsVerifier.isPresent()) {
-            mAreaIdsVerifier.get().verify(carPropertyConfig.getAreaIds());
-        } else if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) {
+
+        if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) {
             assertWithMessage(
                     mPropertyName + "'s AreaIds must contain a single 0 since it is "
                             + areaTypeToString(mAreaType))
@@ -409,10 +408,14 @@
         } else if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR) {
             verifyValidAreaIdsForAreaType(carPropertyConfig, ALL_POSSIBLE_MIRROR_AREA_IDS);
             verifyNoAreaOverlapInAreaIds(carPropertyConfig, MIRROR_AREAS);
-        } else if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_SEAT) {
+        } else if (mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_SEAT
+                && mPropertyId != VehiclePropertyIds.INFO_DRIVER_SEAT) {
             verifyValidAreaIdsForAreaType(carPropertyConfig, ALL_POSSIBLE_SEAT_AREA_IDS);
             verifyNoAreaOverlapInAreaIds(carPropertyConfig, SEAT_AREAS);
         }
+        if (mAreaIdsVerifier.isPresent()) {
+            mAreaIdsVerifier.get().verify(carPropertyConfig.getAreaIds());
+        }
 
         if (mChangeMode == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) {
             verifyContinuousCarPropertyConfig(carPropertyConfig);
@@ -420,6 +423,9 @@
             verifyNonContinuousCarPropertyConfig(carPropertyConfig);
         }
 
+        mCarPropertyConfigVerifier.ifPresent(carPropertyConfigVerifier ->
+                carPropertyConfigVerifier.verify(carPropertyConfig));
+
         if (!mPossibleConfigArrayValues.isEmpty()) {
             assertWithMessage(
                     mPropertyName + " configArray must specify supported values")
@@ -525,6 +531,9 @@
 
     private void verifyCarPropertyValueGetter(CarPropertyConfig<?> carPropertyConfig,
             CarPropertyManager carPropertyManager) {
+        if (carPropertyConfig.getAccess() == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE) {
+            return;
+        }
         for (int areaId : carPropertyConfig.getAreaIds()) {
             CarPropertyValue<?> carPropertyValue =
                     carPropertyManager.getProperty(
@@ -684,6 +693,10 @@
         void verify(int[] areaIds);
     }
 
+    public interface CarPropertyConfigVerifier {
+        void verify(CarPropertyConfig<?> carPropertyConfig);
+    }
+
     public static class Builder<T> {
         private final int mPropertyId;
         private final int mAccess;
@@ -694,6 +707,7 @@
         private Optional<ConfigArrayVerifier> mConfigArrayVerifier = Optional.empty();
         private Optional<CarPropertyValueVerifier> mCarPropertyValueVerifier = Optional.empty();
         private Optional<AreaIdsVerifier> mAreaIdsVerifier = Optional.empty();
+        private Optional<CarPropertyConfigVerifier> mCarPropertyConfigVerifier = Optional.empty();
         private ImmutableSet<Integer> mPossibleConfigArrayValues = ImmutableSet.of();
         private ImmutableSet<T> mPossibleCarPropertyValues = ImmutableSet.of();
         private boolean mRequirePropertyValueToBeInConfigArray = false;
@@ -733,6 +747,12 @@
             return this;
         }
 
+        public Builder<T> setCarPropertyConfigVerifier(
+                CarPropertyConfigVerifier carPropertyConfigVerifier) {
+            mCarPropertyConfigVerifier = Optional.of(carPropertyConfigVerifier);
+            return this;
+        }
+
         public Builder<T> setPossibleConfigArrayValues(
                 ImmutableSet<Integer> possibleConfigArrayValues) {
             mPossibleConfigArrayValues = possibleConfigArrayValues;
@@ -778,11 +798,11 @@
         public VehiclePropertyVerifier<T> build() {
             return new VehiclePropertyVerifier<>(mPropertyId, mAccess, mAreaType, mChangeMode,
                     mPropertyType, mRequiredProperty, mConfigArrayVerifier,
-                    mCarPropertyValueVerifier, mAreaIdsVerifier, mPossibleConfigArrayValues,
-                    mPossibleCarPropertyValues, mRequirePropertyValueToBeInConfigArray,
-                    mVerifySetterWithConfigArrayValues, mRequireMinMaxValues,
-                    mRequireMinValuesToBeZero, mRequireZeroToBeContainedInMinMaxRanges,
-                    mPossiblyDependentOnHvacPowerOn);
+                    mCarPropertyValueVerifier, mAreaIdsVerifier, mCarPropertyConfigVerifier,
+                    mPossibleConfigArrayValues, mPossibleCarPropertyValues,
+                    mRequirePropertyValueToBeInConfigArray, mVerifySetterWithConfigArrayValues,
+                    mRequireMinMaxValues, mRequireMinValuesToBeZero,
+                    mRequireZeroToBeContainedInMinMaxRanges, mPossiblyDependentOnHvacPowerOn);
         }
     }
 
@@ -873,9 +893,9 @@
         private final long mCreationTimeNanos = SystemClock.elapsedRealtimeNanos();
         private CarPropertyValue<?> mUpdatedCarPropertyValue = null;
 
-        SetterCallback(int propertyId, String propertyName, int areaId, T expectedSetValue) {
+        SetterCallback(int propertyId, int areaId, T expectedSetValue) {
             mPropertyId = propertyId;
-            mPropertyName = propertyName;
+            mPropertyName = VehiclePropertyIds.toString(propertyId);
             mAreaId = areaId;
             mExpectedSetValue = expectedSetValue;
         }
@@ -919,4 +939,17 @@
     private static boolean floatEquals(float f1, float f2) {
         return Math.abs(f1 - f2) < FLOAT_INEQUALITY_THRESHOLD;
     }
+
+    private static <U> CarPropertyValue<U> setPropertyAndWaitForChange(
+            CarPropertyManager carPropertyManager, int propertyId, Class<U> propertyType,
+            int areaId, U valueToSet) {
+        SetterCallback setterCallback = new SetterCallback(propertyId, areaId, valueToSet);
+        assertWithMessage("Failed to register setter callback for " + VehiclePropertyIds.toString(
+                propertyId)).that(carPropertyManager.registerCallback(setterCallback, propertyId,
+                CarPropertyManager.SENSOR_RATE_FASTEST)).isTrue();
+        carPropertyManager.setProperty(propertyType, propertyId, areaId, valueToSet);
+        CarPropertyValue<U> carPropertyValue = setterCallback.waitForUpdatedCarPropertyValue();
+        carPropertyManager.unregisterCallback(setterCallback, propertyId);
+        return carPropertyValue;
+    }
 }
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
index 36c1217..de74595 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
@@ -390,6 +390,34 @@
     }
 
     @Test
+    public void testRequestNetworkScanWithRenounceWithoutChannels() {
+        boolean isLocationSwitchOn = getAndSetLocationSwitch(true);
+        try {
+            mNetworkScanRequest = buildNetworkScanRequest(/*includeBandsAndChannels=*/false);
+            mNetworkScanCallback = new NetworkScanCallbackImpl();
+            Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RENOUNCE_START,
+                    false);
+            setReady(false);
+            startNetworkScan.sendToTarget();
+            waitUntilReady();
+
+            Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
+            assertWithMessage(
+                    "The final scan status is "
+                            + mNetworkScanStatus
+                            + " with error code "
+                            + mErrorCode
+                            + ", not ScanCompleted"
+                            + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
+                            + " ERROR_UNSUPPORTED")
+                    .that(isScanStatusValid())
+                    .isTrue();
+        } finally {
+            getAndSetLocationSwitch(isLocationSwitchOn);
+        }
+    }
+
+    @Test
     public void testRequestNetworkScanLocationOffPass() {
         requestNetworkScanLocationOffHelper(false, true);
     }
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt
index ca63dd2..a37ced0 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt
@@ -8,6 +8,7 @@
 import android.companion.cts.common.RecordingCallback.OnAssociationCreated
 import android.content.Intent
 import android.platform.test.annotations.AppModeFull
+import com.android.compatibility.common.util.FeatureUtil
 import org.junit.Assume.assumeFalse
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -34,6 +35,7 @@
     override fun setUp() {
         super.setUp()
 
+        assumeFalse(FeatureUtil.isWatch())
         // TODO(b/211602270): Add support for WATCH and "null" profiles in the
         // confirmation UI (the "self-managed" flow variant).
         assumeFalse(profile == null)
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt
index 92e1b49..d1cee82 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt
@@ -5,6 +5,7 @@
 import android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER
 
 import android.platform.test.annotations.AppModeFull
+import com.android.compatibility.common.util.FeatureUtil
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -28,6 +29,7 @@
     override fun setUp() {
         super.setUp()
 
+        assumeFalse(FeatureUtil.isWatch())
         // TODO(b/211722613): Add support for DEVICE_PROFILE_APP_STREAMING
         // DEVICE_PROFILE_COMPUTER and DEVICE_PROFILE_AUTOMOTIVE_PROJECTION
         // profiles in the confirmation UI (the "single_device" flow variant).
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt
index ffc52eb..8da92e6 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt
@@ -20,6 +20,7 @@
 import android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION
 import android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER
 import android.platform.test.annotations.AppModeFull
+import com.android.compatibility.common.util.FeatureUtil
 import org.junit.Assume.assumeFalse
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -41,6 +42,7 @@
     override fun setUp() {
         super.setUp()
 
+        assumeFalse(FeatureUtil.isWatch())
         // TODO(b/211590680): Add support for APP_STREAMING, AUTOMOTIVE_PROJECTION and COMPUTER
         // in the confirmation UI (the "multiple devices" flow variant).
         assumeFalse(profile == DEVICE_PROFILE_COMPUTER)
diff --git a/tests/tests/content/Android.bp b/tests/tests/content/Android.bp
index d7d1424..b152b0f 100644
--- a/tests/tests/content/Android.bp
+++ b/tests/tests/content/Android.bp
@@ -78,25 +78,6 @@
         "src/**/*.kt",
         "BinderPermissionTestService/**/I*.aidl",
     ],
-    required: [
-        "HelloWorld5",
-        "HelloWorld5Profileable",
-        "HelloWorld7",
-        "HelloWorldNoAppStorage",
-        "HelloWorldResHardening",
-        "HelloWorldSdk1",
-        "HelloWorldSdk1DifferentSigner",
-        "HelloWorldSdk1MajorVersion2",
-        "HelloWorldSdk1Updated",
-        "HelloWorldSdk2",
-        "HelloWorldSdk2Updated",
-        "HelloWorldSdk3UsingSdk1",
-        "HelloWorldSdk3UsingSdk1And2",
-        "HelloWorldShell",
-        "HelloWorldUsingSdk1",
-        "HelloWorldUsingSdk1And2",
-        "HelloWorldUsingSdk3",
-    ],
     per_testcase_directory: true,
     data: [
         ":CtsContentDirectBootUnawareTestApp",
@@ -132,6 +113,23 @@
         "data/HelloWorld5_mdpi-v4.digests.signature",
         "data/malformed.apk.idsig",
         "data/test-cert.x509.pem",
+        ":HelloWorld5",
+        ":HelloWorld5Profileable",
+        ":HelloWorld7",
+        ":HelloWorldNoAppStorage",
+        ":HelloWorldResHardening",
+        ":HelloWorldSdk1",
+        ":HelloWorldSdk1DifferentSigner",
+        ":HelloWorldSdk1MajorVersion2",
+        ":HelloWorldSdk1Updated",
+        ":HelloWorldSdk2",
+        ":HelloWorldSdk2Updated",
+        ":HelloWorldSdk3UsingSdk1",
+        ":HelloWorldSdk3UsingSdk1And2",
+        ":HelloWorldShell",
+        ":HelloWorldUsingSdk1",
+        ":HelloWorldUsingSdk1And2",
+        ":HelloWorldUsingSdk3",
     ],
     java_resources: [
         ":PackagePropertyTestApp1",
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 6ae7045..3d7ea21 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -49,9 +49,6 @@
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <!-- idsig files might not be found, ignore the push failure -->
-        <!-- TODO(b/152888086): remove this after cts build process enables idsig files -->
-        <option name="abort-on-push-failure" value="false" />
         <option name="push-file" key="HelloWorld5.apk" value="/data/local/tmp/cts/content/HelloWorld5.apk" />
         <option name="push-file" key="HelloWorld5.apk.idsig" value="/data/local/tmp/cts/content/HelloWorld5.apk.idsig" />
         <option name="push-file" key="HelloWorld5_hdpi-v4.apk" value="/data/local/tmp/cts/content/HelloWorld5_hdpi-v4.apk" />
diff --git a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
index 68edc76..58a4011 100644
--- a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
@@ -72,7 +72,7 @@
         }
 
         // Managed profiles only required for handheld devices
-        if (!isHandheldDevice()) {
+        if (!isHandheldOrTabletDevice()) {
             return;
         }
 
@@ -91,12 +91,20 @@
     }
 
     /**
-     * The CDD defines a handheld device as one that has a battery and a screen size between
-     * 2.5 and 8 inches.
+     * The CDD defines:
+     * - A handheld device as one that has a battery and a screen size between 2.5 and 8 inches.
+     * - A tablet device as one that has a battery and a screen size between 7 and 18 inches.
      */
-    private boolean isHandheldDevice() throws Exception {
+    private boolean isHandheldOrTabletDevice() throws Exception {
+        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+                || mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+                || mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+                || mPackageManager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
+            return false;
+        }
+
         double screenInches = getScreenSizeInInches();
-        return deviceHasBattery() && screenInches >= 2.5 && screenInches <= 8.0;
+        return deviceHasBattery() && screenInches >= 2.5 && screenInches <= 18.0;
     }
 
     private boolean deviceHasBattery() {
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index 6d375a6..cee80cf 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -56,6 +56,7 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -525,6 +526,16 @@
         results = pi.queryIntentComponents(0);
         assertEquals(1, results.size());
         mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
+
+        intent = new Intent();
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setComponent(
+                new ComponentName("android", "com.android.internal.app.ResolverActivity"));
+        try {
+            mContext.startActivity(intent);
+        } catch (ActivityNotFoundException ignore) {
+
+        }
     }
 
     private void checkActivityInfoName(String expectedName, List<ResolveInfo> resolves) {
diff --git a/tests/tests/display/TEST_MAPPING b/tests/tests/display/TEST_MAPPING
new file mode 100644
index 0000000..86feee2
--- /dev/null
+++ b/tests/tests/display/TEST_MAPPING
@@ -0,0 +1,25 @@
+{
+  "kernel-presubmit": [
+    {
+      "name": "CtsDisplayTestCases",
+      "options": [
+        {
+          // TODO(b/247135992)
+          "exclude-filter": "android.display.cts.DisplayManagerTest#testCreateVirtualDisplayFromShell"
+        },
+        {
+          // TODO(b/184685560)
+          "exclude-filter": "android.display.cts.DisplayTest#testRefreshRateSwitchOnSecondaryDisplay"
+        },
+        {
+          // TODO(b/270222666)
+          "exclude-filter": "android.display.cts.VirtualDisplayTest#testVirtualDisplayWithRequestedRefreshRate"
+        },
+        {
+          // TODO(b/248273657)
+          "exclude-filter": "android.graphics.cts.SetFrameRateTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java b/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java
index b21edd5..3b92c16 100644
--- a/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java
@@ -31,6 +31,7 @@
 import junit.framework.Assert;
 
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,10 +54,17 @@
     boolean mFinitePaused = false;
     boolean mFinitePausedSet = false;
     boolean mResumed = false;
+    long mDefaultAnimatorPauseDelay = 10000L;
+
+    @Before
+    public void setup() {
+        mDefaultAnimatorPauseDelay = Animator.getBackgroundPauseDelay();
+    }
 
     @After
     public void cleanup() {
         Animator.setAnimatorPausingEnabled(true);
+        Animator.setBackgroundPauseDelay(mDefaultAnimatorPauseDelay);
     }
 
     /**
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index 574b9a1..b4be6a2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -1010,30 +1010,32 @@
 
     @Test
     @RequiresDevice
-    public void testDecode10BitHEIFTo10BitBitmap() {
+    public void testDecode10BitHEIF() {
         assumeTrue(
             "Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
         assumeTrue(
             "Test needs VNDK at least T.",
-            SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
+            SystemProperties.getInt("ro.vndk.version", Build.VERSION_CODES.CUR_DEVELOPMENT)
+                >= Build.VERSION_CODES.TIRAMISU);
         assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
 
+        Config preferredConfig = Config.RGBA_1010102;
+
         // For TVs, even if the device advertises that 10 bits profile is supported, the output
-        // format might not be 10 bits pixel format, but can still be displayed. So only when
-        // the TV is capable to output RGBA_1010102, this test can continue.
-        if (MediaUtils.isTv()) {
-            assumeTrue(
-                "The TV is unable to decode to RGBA_1010102 format, skip the test",
-                hasDecoderSupportsRGBA1010102());
+        // format might not be CPU readable, but can still be displayed. When the TV device is
+        // not capable to decode to YUVP010 format, it should be able to fall back to decode to
+        // RGB_565 format.
+        if (MediaUtils.isTv() && !hasHEVCDecoderSupportsYUVP010()) {
+            preferredConfig = Config.RGB_565;
         }
 
         BitmapFactory.Options opt = new BitmapFactory.Options();
-        opt.inPreferredConfig = Config.RGBA_1010102;
+        opt.inPreferredConfig = preferredConfig;
         Bitmap bm = BitmapFactory.decodeStream(obtainInputStream(R.raw.heifimage_10bit), null, opt);
         assertNotNull(bm);
         assertEquals(4096, bm.getWidth());
         assertEquals(3072, bm.getHeight());
-        assertEquals(Config.RGBA_1010102, bm.getConfig());
+        assertEquals(preferredConfig, bm.getConfig());
     }
 
     @Test
@@ -1043,16 +1045,18 @@
             "Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
         assumeTrue(
             "Test needs VNDK at least T.",
-            SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
+            SystemProperties.getInt("ro.vndk.version", Build.VERSION_CODES.CUR_DEVELOPMENT)
+                >= Build.VERSION_CODES.TIRAMISU);
         assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
 
         // For TVs, even if the device advertises that 10 bits profile is supported, the output
-        // format might not be 10 bits pixel format, but can still be displayed. So only when
-        // the TV is capable to output RGBA_1010102, this test can continue.
+        // format might not be CPU readable, but can still be displayed, and only when the TV
+        // is capable to decode to YUVP010 format, the image can be converted into RGBA_1010102,
+        // and this test can continue.
         if (MediaUtils.isTv()) {
             assumeTrue(
                 "The TV is unable to decode to RGBA_1010102 format, skip the test",
-                hasDecoderSupportsRGBA1010102());
+                hasHEVCDecoderSupportsYUVP010());
         }
 
         BitmapFactory.Options opt = new BitmapFactory.Options();
@@ -1132,7 +1136,7 @@
         return true;
     }
 
-    private static boolean hasDecoderSupportsRGBA1010102() {
+    private static boolean hasHEVCDecoderSupportsYUVP010() {
         MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
         for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) {
             if (mediaCodecInfo.isEncoder()) {
@@ -1144,7 +1148,7 @@
                             mediaCodecInfo.getCapabilitiesForType(mediaType);
                     for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) {
                         if (codecCapabilities.colorFormats[i]
-                                == MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010) {
+                                == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) {
                             return true;
                         }
                     }
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index f30f919..cc3fbc1 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -249,16 +249,18 @@
             "Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
         assumeTrue(
             "Test needs VNDK at least T.",
-            SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
+            SystemProperties.getInt("ro.vndk.version", Build.VERSION_CODES.CUR_DEVELOPMENT)
+                >= Build.VERSION_CODES.TIRAMISU);
         assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
 
         // For TVs, even if the device advertises that 10 bits profile is supported, the output
-        // format might not be 10 bits pixel format, but can still be displayed. So only when
-        // the TV is capable to output RGBA_1010102, this test can continue.
+        // format might not be CPU readable, but can still be displayed, and only when the TV
+        // is capable to decode to YUVP010 format, the image can be converted into RGBA_1010102,
+        // and this test can continue.
         if (MediaUtils.isTv()) {
             assumeTrue(
-                "The TV is unable to decode to RGBA_1010102 format, skip the test",
-                hasDecoderSupportsRGBA1010102());
+                "The TV is unable to decode to YUVP010 format, skip the test",
+                hasHEVCDecoderSupportsYUVP010());
         }
 
         try {
@@ -2799,7 +2801,7 @@
         return true;
     }
 
-    private static boolean hasDecoderSupportsRGBA1010102() {
+    private static boolean hasHEVCDecoderSupportsYUVP010() {
         MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
         for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) {
             if (mediaCodecInfo.isEncoder()) {
@@ -2811,7 +2813,7 @@
                             mediaCodecInfo.getCapabilitiesForType(mediaType);
                     for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) {
                         if (codecCapabilities.colorFormats[i]
-                                == MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010) {
+                                == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) {
                             return true;
                         }
                     }
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanTestActivity.java b/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanTestActivity.java
deleted file mode 100644
index 6cc1d43..0000000
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/GwpAsanTestActivity.java
+++ /dev/null
@@ -1,88 +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.gwpasan;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.Context;
-import android.os.Bundle;
-import android.util.Log;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-
-import java.lang.Override;
-
-import android.gwpasan.Utils;
-
-public class GwpAsanTestActivity extends Activity {
-    static final String TAG = "GwpAsanTestActivity";
-
-    private int mResult;
-    private final Object mFinishEvent = new Object();
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        mResult = resultCode;
-        synchronized (mFinishEvent) {
-            mFinishEvent.notify();
-        }
-    }
-
-    protected boolean callActivity(Class<?> cls) throws Exception {
-        Thread thread = new Thread() {
-            @Override
-            public void run() {
-                try {
-                    Context context = getApplicationContext();
-                    Intent intent = new Intent(context, cls);
-                    startActivityForResult(intent, 0);
-
-                    synchronized (mFinishEvent) {
-                        mFinishEvent.wait();
-                    }
-                } catch(Exception e) {
-                    Log.d(TAG, "callActivity got an exception " + e.toString());
-                }
-            }
-        };
-        thread.start();
-        thread.join(20000 /* millis */);
-
-        if (mResult == RESULT_OK) {
-          throw new Exception();
-        }
-        return (mResult - RESULT_FIRST_USER) == 1;
-    }
-
-    public void testGwpAsanEnabledActivity() throws Exception {
-        assertTrue(callActivity(GwpAsanEnabledActivity.class));
-    }
-
-    public void testGwpAsanDisabledActivity() throws Exception {
-        assertFalse(callActivity(GwpAsanDisabledActivity.class));
-    }
-
-    public void testGwpAsanDefaultActivity() throws Exception {
-        // GwpAsanDefaultActivity inherits the application attribute.
-        assertTrue(callActivity(GwpAsanDefaultActivity.class));
-    }
-}
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/Utils.java b/tests/tests/gwp-asan/enabled/src/android/gwpasan/Utils.java
deleted file mode 100644
index 395eea4..0000000
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/Utils.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package android.gwpasan;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-
-public class Utils {
-
-    public static boolean isGwpAsanEnabled() throws IOException {
-      BufferedReader reader = new BufferedReader(new FileReader("proc/self/maps"));
-      String line;
-      while ((line = reader.readLine()) != null) {
-        if (line.contains("GWP-ASan Guard Page")) {
-          return true;
-        }
-      }
-      return false;
-    }
-}
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/cts/GwpAsanActivityTest.java b/tests/tests/gwp-asan/enabled/src/android/gwpasan/cts/GwpAsanActivityTest.java
deleted file mode 100644
index 3d6d834..0000000
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/cts/GwpAsanActivityTest.java
+++ /dev/null
@@ -1,54 +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.gwpasan.cts;
-
-import android.test.ActivityInstrumentationTestCase2;
-import static org.junit.Assert.assertTrue;
-import android.util.Log;
-import android.gwpasan.GwpAsanTestActivity;
-import android.gwpasan.Utils;
-
-public class GwpAsanActivityTest extends ActivityInstrumentationTestCase2<GwpAsanTestActivity> {
-
-    private GwpAsanTestActivity mActivity;
-
-    public GwpAsanActivityTest() {
-      super(GwpAsanTestActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mActivity = getActivity();
-    }
-
-    public void testGwpAsanEnabledApplication() throws Exception {
-        assertTrue(Utils.isGwpAsanEnabled());
-    }
-
-    public void testGwpAsanEnabledActivity() throws Exception {
-        mActivity.testGwpAsanEnabledActivity();
-    }
-
-    public void testGwpAsanDisabledActivity() throws Exception {
-        mActivity.testGwpAsanDisabledActivity();
-    }
-
-    public void testGwpAsanDefaultActivity() throws Exception {
-        mActivity.testGwpAsanDefaultActivity();
-    }
-}
diff --git a/tests/tests/gwp-asan/enabled/src/android/gwpasan/cts/GwpAsanServiceTest.java b/tests/tests/gwp-asan/enabled/src/android/gwpasan/cts/GwpAsanServiceTest.java
deleted file mode 100644
index a7beaa4..0000000
--- a/tests/tests/gwp-asan/enabled/src/android/gwpasan/cts/GwpAsanServiceTest.java
+++ /dev/null
@@ -1,74 +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.gwpasan.cts;
-
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.Parcel;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.rule.ServiceTestRule;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.TimeoutException;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-
-import android.gwpasan.GwpAsanEnabledService;
-import android.gwpasan.GwpAsanDisabledService;
-import android.gwpasan.GwpAsanDefaultService;
-
-@RunWith(AndroidJUnit4.class)
-public class GwpAsanServiceTest {
-    @Rule
-    public final ServiceTestRule mServiceRule = new ServiceTestRule();
-
-    private boolean isGwpAsanEnabledInService(Class<?> cls) throws Exception {
-        Intent serviceIntent = new Intent(getApplicationContext(), cls);
-        IBinder binder = mServiceRule.bindService(serviceIntent);
-        final Parcel request = Parcel.obtain();
-        final Parcel reply = Parcel.obtain();
-        if (!binder.transact(42, request, reply, 0)) {
-          throw new Exception();
-        }
-        int res = reply.readInt();
-        if (res < 0) {
-          throw new Exception();
-        }
-        return res != 0;
-    }
-
-    @Test
-    public void testEnabledService() throws Exception {
-        assertTrue(isGwpAsanEnabledInService(GwpAsanEnabledService.class));
-    }
-
-    @Test
-    public void testDisabledService() throws Exception {
-        assertFalse(isGwpAsanEnabledInService(GwpAsanDisabledService.class));
-    }
-
-    @Test
-    public void testDefaultService() throws Exception {
-        // GwpAsanDefaultService inherits the application attribute.
-        assertTrue(isGwpAsanEnabledInService(GwpAsanDefaultService.class));
-    }
-}
diff --git a/tests/tests/hardware/res/raw/sony_dualsense_edge_bluetooth_register.json b/tests/tests/hardware/res/raw/sony_dualsense_edge_bluetooth_register.json
new file mode 100644
index 0000000..95ab0b1
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualsense_edge_bluetooth_register.json
@@ -0,0 +1,52 @@
+{
+  "id": 1,
+  "command": "register",
+  "name": "Sony DualSense Edge (Bluetooth Test)",
+  "vid": 0x054c,
+  "pid": 0x0df2,
+  "bus": "bluetooth",
+  "source": "KEYBOARD | GAMEPAD | JOYSTICK",
+  "descriptor": [
+    0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35,
+    0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15, 0x00, 0x25,
+    0x07, 0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x65, 0x00,
+    0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e, 0x81, 0x02,
+    0x75, 0x06, 0x95, 0x01, 0x81, 0x01, 0x05, 0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff,
+    0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, 0x06, 0x00, 0xff, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
+    0x08, 0x95, 0x4d, 0x85, 0x31, 0x09, 0x31, 0x91, 0x02, 0x09, 0x3b, 0x81, 0x02, 0x85, 0x32, 0x09,
+    0x32, 0x95, 0x8d, 0x91, 0x02, 0x85, 0x33, 0x09, 0x33, 0x95, 0xcd, 0x91, 0x02, 0x85, 0x34, 0x09,
+    0x34, 0x96, 0x0d, 0x01, 0x91, 0x02, 0x85, 0x35, 0x09, 0x35, 0x96, 0x4d, 0x01, 0x91, 0x02, 0x85,
+    0x36, 0x09, 0x36, 0x96, 0x8d, 0x01, 0x91, 0x02, 0x85, 0x37, 0x09, 0x37, 0x96, 0xcd, 0x01, 0x91,
+    0x02, 0x85, 0x38, 0x09, 0x38, 0x96, 0x0d, 0x02, 0x91, 0x02, 0x85, 0x39, 0x09, 0x39, 0x96, 0x22,
+    0x02, 0x91, 0x02, 0x06, 0x80, 0xff, 0x85, 0x05, 0x09, 0x33, 0x95, 0x28, 0xb1, 0x02, 0x85, 0x08,
+    0x09, 0x34, 0x95, 0x2f, 0xb1, 0x02, 0x85, 0x09, 0x09, 0x24, 0x95, 0x13, 0xb1, 0x02, 0x85, 0x20,
+    0x09, 0x26, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x22, 0x09, 0x40, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x80,
+    0x09, 0x28, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x81, 0x09, 0x29, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x82,
+    0x09, 0x2a, 0x95, 0x09, 0xb1, 0x02, 0x85, 0x83, 0x09, 0x2b, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf1,
+    0x09, 0x31, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x32, 0x95, 0x0f, 0xb1, 0x02, 0x85, 0xf0,
+    0x09, 0x30, 0x95, 0x3f, 0xb1, 0x02, 0xc0
+  ],
+
+  "feature_reports": [
+    {
+      "id": 0x05,
+      "data":
+        [0x5, 0xff, 0xff, 0xf2, 0xff, 0x4, 0x0, 0x9d, 0x22, 0x5e, 0xdd, 0x92, 0x22, 0x52, 0xdd, 0xba, 0x22, 0x51, 0xdd, 0x1c, 0x2, 0x1c, 0x2, 0xfb, 0x1f, 0x5, 0xe0, 0x83, 0x1f, 0x99, 0xdf, 0x7, 0x20, 0xfc, 0xdf, 0x5, 0x0, 0x72, 0xad, 0x2c, 0x13]
+    },
+    {
+      "id": 0x09,
+      "data":
+        [0x09, 0xa9, 0x3e, 0x7a, 0x7e, 0x0b, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xdf, 0xec, 0xe0]
+    },
+    {
+      "id": 0x20,
+      "data": [
+        0x20, 0x53, 0x65, 0x70, 0x20, 0x20, 0x36, 0x20, 0x32, 0x30, 0x32, 0x32,
+        0x31, 0x30, 0x3a, 0x33, 0x31, 0x3a, 0x35, 0x36, 0x02, 0x00, 0x44, 0x00,
+        0x08, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xc1, 0xc8, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+        0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00,
+        0x2B, 0xF7, 0x22, 0x41]
+    }
+  ]
+}
diff --git a/tests/tests/hardware/res/raw/sony_dualsense_edge_bluetooth_vibratortests.json b/tests/tests/hardware/res/raw/sony_dualsense_edge_bluetooth_vibratortests.json
new file mode 100644
index 0000000..5f4bef9
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualsense_edge_bluetooth_vibratortests.json
@@ -0,0 +1,50 @@
+// Refer to
+//  - struct dualsense_output_report_bt
+//  - dualsense_init_output_report()
+//  - dualsense_output_worker()
+// in drivers/hid/hid-playstation.c
+[
+  {
+    "id": 1,
+    "durations" : [1000],
+    "amplitudes" : [192],
+    "leftFfIndex" : 6,
+    "rightFfIndex" : 5,
+    "output" :
+        [
+            {"index" : 0,
+             "data" : 0x31}   // DS_OUTPUT_REPORT_BT
+
+            //{"index" : 3,
+             // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT
+             //"data" : 0x02},
+
+            //{"index" : 41,
+             // DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2
+             //"data" : 0x04}
+        ]
+  },
+
+  {
+    "id": 1,
+    "durations" : [2000, 2000, 2000, 2000, 2000],
+    "amplitudes" : [16, 32, 64, 128, 255],
+    "leftFfIndex" : 6,
+    "rightFfIndex" : 5,
+    "output" :
+        [
+            {"index" : 0,
+             "data" : 0x31}   // DS_OUTPUT_REPORT_BT
+
+            //{"index" : 3,
+             // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT
+             //"data" : 0x02},
+
+            //{"index" : 41,
+             // DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2
+             //"data" : 0x04}
+        ]
+  }
+
+]
+
diff --git a/tests/tests/hardware/res/raw/sony_dualsense_edge_usb_register.json b/tests/tests/hardware/res/raw/sony_dualsense_edge_usb_register.json
new file mode 100644
index 0000000..29f97e3
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualsense_edge_usb_register.json
@@ -0,0 +1,54 @@
+{
+  "id": 1,
+  "command": "register",
+  "name": "Sony DualSense Edge (USB Test)",
+  "vid": 0x054c,
+  "pid": 0x0df2,
+  "bus": "usb",
+  "source": "KEYBOARD | GAMEPAD | JOYSTICK",
+  "descriptor": [
+    0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35,
+    0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x06, 0x81, 0x02, 0x06,
+    0x00, 0xff, 0x09, 0x20, 0x95, 0x01, 0x81, 0x02, 0x05, 0x01, 0x09, 0x39, 0x15, 0x00, 0x25, 0x07,
+    0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x65, 0x00, 0x05,
+    0x09, 0x19, 0x01, 0x29, 0x0f, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0f, 0x81, 0x02, 0x06,
+    0x00, 0xff, 0x09, 0x21, 0x95, 0x0d, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x22, 0x15, 0x00, 0x26,
+    0xff, 0x00, 0x75, 0x08, 0x95, 0x34, 0x81, 0x02, 0x85, 0x02, 0x09, 0x23, 0x95, 0x2f, 0x91, 0x02,
+    0x85, 0x05, 0x09, 0x23, 0x95, 0x28, 0xb1, 0x02, 0x85, 0x08, 0x09, 0x24, 0x95, 0x2f, 0xb1, 0x02,
+    0x85, 0x09, 0x09, 0x24, 0x95, 0x13, 0xb1, 0x02, 0x85, 0x0a, 0x09, 0x25, 0x95, 0x1a, 0xb1, 0x02,
+    0x85, 0x20, 0x09, 0x26, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x21, 0x09, 0x27, 0x95, 0x04, 0xb1, 0x02,
+    0x85, 0x22, 0x09, 0x40, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x80, 0x09, 0x28, 0x95, 0x3f, 0xb1, 0x02,
+    0x85, 0x81, 0x09, 0x29, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x82, 0x09, 0x2a, 0x95, 0x09, 0xb1, 0x02,
+    0x85, 0x83, 0x09, 0x2b, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x84, 0x09, 0x2c, 0x95, 0x3f, 0xb1, 0x02,
+    0x85, 0x85, 0x09, 0x2d, 0x95, 0x02, 0xb1, 0x02, 0x85, 0xa0, 0x09, 0x2e, 0x95, 0x01, 0xb1, 0x02,
+    0x85, 0xe0, 0x09, 0x2f, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf0, 0x09, 0x30, 0x95, 0x3f, 0xb1, 0x02,
+    0x85, 0xf1, 0x09, 0x31, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x32, 0x95, 0x0f, 0xb1, 0x02,
+    0xc0],
+
+  "feature_reports": [
+    {
+      "id": 0x05,
+      "data": [
+        0x05, 0xff, 0xff, 0xf2, 0xff, 0x04, 0x00, 0x9d, 0x22, 0x5e, 0xdd, 0x92,
+        0x22, 0x52, 0xdd, 0xba, 0x22, 0x51, 0xdd, 0x1c, 0x02, 0x1c, 0x02, 0xfb,
+        0x1f, 0x05, 0xe0, 0x83, 0x1f, 0x99, 0xdf, 0x07, 0x20, 0xfc, 0xdf, 0x05,
+        0x00, 0x00, 0x00, 0x00, 0x00]
+    },
+    {
+      "id": 0x09,
+      "data": [
+        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+    },
+    {
+      "id": 0x20,
+      "data": [
+        0x20, 0x53, 0x65, 0x70, 0x20, 0x20, 0x36, 0x20, 0x32, 0x30, 0x32, 0x32,
+        0x31, 0x30, 0x3a, 0x33, 0x31, 0x3a, 0x35, 0x36, 0x02, 0x00, 0x44, 0x00,
+        0x08, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xc1, 0xc8, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+        0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00]
+    }
+  ]
+}
diff --git a/tests/tests/hardware/res/raw/sony_dualsense_edge_usb_vibratortests.json b/tests/tests/hardware/res/raw/sony_dualsense_edge_usb_vibratortests.json
new file mode 100644
index 0000000..52998c0
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualsense_edge_usb_vibratortests.json
@@ -0,0 +1,50 @@
+// Refer to
+//  - struct dualsense_output_report_usb
+//  - dualsense_init_output_report()
+//  - dualsense_output_worker()
+// in drivers/hid/hid-playstation.c
+[
+  {
+    "id": 1,
+    "durations" : [1000],
+    "amplitudes" : [192],
+    "leftFfIndex" : 4,
+    "rightFfIndex" : 3,
+    "output" :
+        [
+            {"index" : 0,
+             "data" : 0x02}   // DS_OUTPUT_REPORT_USB
+
+            //{"index" : 1,
+               // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT
+               //"data" : 0x02},
+
+            //{"index" : 39,
+               // DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2
+               //"data" : 0x04}
+        ]
+  },
+
+  {
+    "id": 1,
+    "durations" : [2000, 2000, 2000, 2000, 2000],
+    "amplitudes" : [16, 32, 64, 128, 255],
+    "leftFfIndex" : 4,
+    "rightFfIndex" : 3,
+    "output" :
+        [
+            {"index" : 0,
+             "data" : 0x02}   // DS_OUTPUT_REPORT_USB
+
+            //{"index" : 1,
+               // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT
+               //"data" : 0x02},
+
+            //{"index" : 39,
+               // DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2
+               //"data" : 0x04}
+        ]
+  }
+
+]
+
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseEdgeBluetoothTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseEdgeBluetoothTest.java
new file mode 100644
index 0000000..b27a2dc
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseEdgeBluetoothTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2023 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.input.cts.tests;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.hardware.cts.R;
+import android.view.InputDevice;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+
+import com.android.cts.kernelinfo.KernelInfo;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class SonyDualSenseEdgeBluetoothTest extends InputHidTestCase {
+
+    // Simulates the behavior of PlayStation DualSense Edge gamepad
+    public SonyDualSenseEdgeBluetoothTest() {
+        super(R.raw.sony_dualsense_edge_bluetooth_register);
+    }
+
+    @Override
+    protected int getAdditionalSources() {
+        if (KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION")) {
+            return InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_SENSOR;
+        }
+        return 0;
+    }
+
+    /**
+     * Basic support is required on all kernels. After kernel 4.19, devices must have
+     * CONFIG_HID_PLAYSTATION enabled, which supports advanced features like haptics.
+     */
+    @Test
+    public void kernelModule() {
+        if (KernelInfo.isKernelVersionGreaterThan("4.19")) {
+            assertTrue(KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION"));
+        }
+        assertTrue(KernelInfo.hasConfig("CONFIG_HID_GENERIC"));
+    }
+
+    @Test
+    public void testAllKeys() {
+        if (KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION")) {
+            testInputEvents(R.raw.sony_dualsense_bluetooth_keyeventtests);
+        } else {
+            testInputEvents(R.raw.sony_dualsense_bluetooth_keyeventtests_hid_generic);
+        }
+    }
+
+    @Test
+    public void testAllMotions() {
+        if (KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION")) {
+            testInputEvents(R.raw.sony_dualsense_bluetooth_motioneventtests);
+        } else {
+            testInputEvents(R.raw.sony_dualsense_bluetooth_motioneventtests_hid_generic);
+        }
+    }
+
+    @Test
+    public void testVibrator() throws Exception {
+        // hid-generic does not support vibration for this device
+        assumeTrue(KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION"));
+        testInputVibratorEvents(R.raw.sony_dualsense_edge_bluetooth_vibratortests);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseEdgeUsbTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseEdgeUsbTest.java
new file mode 100644
index 0000000..e2eb8c0
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseEdgeUsbTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 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.input.cts.tests;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.hardware.cts.R;
+import android.view.InputDevice;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.cts.kernelinfo.KernelInfo;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SonyDualSenseEdgeUsbTest extends InputHidTestCase {
+
+    // Simulates the behavior of PlayStation DualSense Edge gamepad
+    public SonyDualSenseEdgeUsbTest() {
+        super(R.raw.sony_dualsense_edge_usb_register);
+    }
+
+    @Override
+    protected int getAdditionalSources() {
+        if (KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION")) {
+            return InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_SENSOR;
+        }
+        return 0;
+    }
+
+    @Test
+    public void testAllKeys() {
+        testInputEvents(R.raw.sony_dualsense_usb_keyeventtests);
+    }
+
+    @Test
+    public void testAllMotions() {
+        testInputEvents(R.raw.sony_dualsense_usb_motioneventtests);
+    }
+
+    @Test
+    public void testVibrator() throws Exception {
+        assumeTrue(KernelInfo.hasConfig("CONFIG_HID_PLAYSTATION"));
+        testInputVibratorEvents(R.raw.sony_dualsense_edge_usb_vibratortests);
+        // hid-generic does not support vibration for this device
+    }
+}
diff --git a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
index 8a52393..9021f8e 100644
--- a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
+++ b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
@@ -40,6 +40,7 @@
 import android.util.Log
 import androidx.test.InstrumentationRegistry
 import com.android.compatibility.common.util.ExceptionUtils.wrappingExceptions
+import com.android.compatibility.common.util.FeatureUtil
 import com.android.compatibility.common.util.LogcatInspector
 import com.android.compatibility.common.util.SystemUtil.eventually
 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
@@ -68,6 +69,7 @@
 
 const val SYSUI_PKG_NAME = "com.android.systemui"
 const val NOTIF_LIST_ID = "com.android.systemui:id/notification_stack_scroller"
+const val NOTIF_LIST_ID_AUTOMOTIVE = "com.android.systemui:id/notifications"
 const val CLEAR_ALL_BUTTON_ID = "dismiss_text"
 // Time to find a notification. Unlikely, but in cases with a lot of notifications, it may take
 // time to find the notification we're looking for
@@ -278,7 +280,12 @@
     while (view == null && start + timeoutMs > System.currentTimeMillis()) {
         view = uiDevice.wait(Until.findObject(selector), VIEW_WAIT_TIMEOUT)
         if (view == null) {
-            val notificationList = UiScrollable(UiSelector().resourceId(NOTIF_LIST_ID))
+            val notificationListId = if (FeatureUtil.isAutomotive()) {
+                NOTIF_LIST_ID_AUTOMOTIVE
+            } else {
+                NOTIF_LIST_ID
+            }
+            val notificationList = UiScrollable(UiSelector().resourceId(notificationListId))
             wrappingExceptions({ cause: Throwable? -> UiDumpUtils.wrapWithUiDump(cause) }) {
                 Assert.assertTrue("Notification list view not found",
                     notificationList.waitForExists(VIEW_WAIT_TIMEOUT))
@@ -312,14 +319,18 @@
         val title = ui.depthFirstSearch { node ->
             node.viewIdResourceName?.contains("alertTitle") == true
         }
-        val okButton = ui.depthFirstSearch { node ->
-            node.textAsString?.equals("OK", ignoreCase = true) ?: false
+        val okCloseButton = ui.depthFirstSearch { node ->
+            (node.textAsString?.equals("OK", ignoreCase = true) ?: false)  ||
+                (node.textAsString?.equals("Close app", ignoreCase = true) ?: false)
         }
-
-        if (title?.text?.toString() == "Android System" && okButton != null) {
+        val titleString = title?.text?.toString()
+        if (okCloseButton != null &&
+            titleString != null &&
+            (titleString == "Android System" ||
+                titleString.endsWith("keeps stopping"))) {
             // Auto dismiss occasional system dialogs to prevent interfering with the test
             android.util.Log.w(AutoRevokeTest.LOG_TAG, "Ignoring exception", e)
-            okButton.click()
+            okCloseButton.click()
             return UiAutomatorUtils.waitFindObject(selector)
         } else {
             throw e
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 663b1c3..39793d2 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -619,16 +619,11 @@
         return (pm != null && pm.hasSystemFeature("android.software.leanback_only"));
     }
 
-    private boolean hasSecureLockScreen() {
-        PackageManager pm = getContext().getPackageManager();
-        return (pm != null && pm.hasSystemFeature("android.software.secure_lock_screen"));
-    }
-
     @Presubmit
     @Test
     public void testKeyguardLockAndUnlock()
             throws Exception {
-        if (!hasSecureLockScreen()) {
+        if (!TestUtils.hasSecureLockScreen(getContext())) {
             return;
         }
 
@@ -650,7 +645,7 @@
         final boolean isUnlockedDeviceRequired = true;
         final boolean isUserAuthRequired = false;
 
-        if (!hasSecureLockScreen()) {
+        if (!TestUtils.hasSecureLockScreen(getContext())) {
             return;
         }
 
@@ -1218,7 +1213,7 @@
         final boolean isUnlockedDeviceRequired = false;
         final boolean isUserAuthRequired = true;
 
-        if (!hasSecureLockScreen()) {
+        if (!TestUtils.hasSecureLockScreen(getContext())) {
             return;
         }
 
diff --git a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
index d55fb13..a703ce2 100644
--- a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
@@ -137,12 +137,18 @@
                 TestUtils.isPropertyEmptyOrUnknown(Build.BRAND_FOR_ATTESTATION)
                 ? Build.BRAND : Build.BRAND_FOR_ATTESTATION;
         assertThat(teeAttestation.getBrand()).isEqualTo(platformReportedBrand);
-        assertThat(teeAttestation.getDevice()).isEqualTo(Build.DEVICE);
+        final String platformReportedDevice =
+                TestUtils.isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION)
+                        ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION;
+        assertThat(teeAttestation.getDevice()).isEqualTo(platformReportedDevice);
         final String platformReportedProduct =
                 TestUtils.isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION)
                 ? Build.PRODUCT : Build.PRODUCT_FOR_ATTESTATION;
         assertThat(teeAttestation.getProduct()).isEqualTo(platformReportedProduct);
-        assertThat(teeAttestation.getManufacturer()).isEqualTo(Build.MANUFACTURER);
+        final String platformReportedManufacturer =
+                TestUtils.isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION)
+                        ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION;
+        assertThat(teeAttestation.getManufacturer()).isEqualTo(platformReportedManufacturer);
         final String platformReportedModel =
                 TestUtils.isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)
                 ? Build.MODEL : Build.MODEL_FOR_ATTESTATION;
@@ -209,14 +215,21 @@
                 ? Build.BRAND : Build.BRAND_FOR_ATTESTATION;
         assertThat(new String(teeAttestation.attestationIdBrand.get()))
                 .isEqualTo(platformReportedBrand);
-        assertThat(new String(teeAttestation.attestationIdDevice.get())).isEqualTo(Build.DEVICE);
+        final String platformReportedDevice =
+                TestUtils.isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION)
+                        ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION;
+        assertThat(new String(teeAttestation.attestationIdDevice.get()))
+                .isEqualTo(platformReportedDevice);
         final String platformReportedProduct =
                 TestUtils.isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION)
                 ? Build.PRODUCT : Build.PRODUCT_FOR_ATTESTATION;
         assertThat(new String(teeAttestation.attestationIdProduct.get()))
                 .isEqualTo(platformReportedProduct);
+        final String platformReportedManufacturer =
+                TestUtils.isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION)
+                        ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION;
         assertThat(new String(teeAttestation.attestationIdManufacturer.get()))
-                .isEqualTo(Build.MANUFACTURER);
+                .isEqualTo(platformReportedManufacturer);
         final String platformReportedModel =
                 TestUtils.isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)
                 ? Build.MODEL : Build.MODEL_FOR_ATTESTATION;
diff --git a/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java b/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
index e61d2b3..17b968d 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
@@ -30,6 +30,7 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -135,6 +136,55 @@
     }
 
     @Test
+    public void testKeyStore_ImportIncorrectWrappedKey() throws Exception {
+        testKeyStore_ImportIncorrectWrappedKey(false);
+    }
+
+    @Test
+    public void testKeyStore_ImportIncorrectWrappedKey_StrongBox() throws Exception {
+        testKeyStore_ImportIncorrectWrappedKey(true);
+    }
+
+    private void testKeyStore_ImportIncorrectWrappedKey(boolean isStrongBox) throws Exception {
+        if (isStrongBox) {
+            TestUtils.assumeStrongBox();
+        }
+        random.setSeed(0);
+
+        byte[] keyMaterial = new byte[32];
+        random.nextBytes(keyMaterial);
+        byte[] mask = new byte[32]; // Zero mask
+
+        KeyPair kp;
+        try {
+            kp = genKeyPair(WRAPPING_KEY_ALIAS, isStrongBox);
+        } catch (SecureKeyImportUnavailableException e) {
+            return;
+        }
+
+        KeyStoreException exception = null;
+        try {
+            importWrappedKey(wrapKey(
+                    kp.getPublic(),
+                    keyMaterial,
+                    mask,
+                    makeAuthList(keyMaterial.length * 8, KM_ALGORITHM_AES),
+                    false /* incorrect wrapping required*/));
+        } catch (SecureKeyImportUnavailableException e) {
+            return;
+        } catch (KeyStoreException e) {
+            exception = e;
+        }
+        assertWithMessage("Did not hit a failure but expected one").that(exception).isNotNull();
+        assertThat(exception.getCause()).isInstanceOf(android.security.KeyStoreException.class);
+        android.security.KeyStoreException ksException =
+                (android.security.KeyStoreException) exception.getCause();
+        assertFalse("Importing incorrectly wrapped key should not cause transient failure in"
+                    + " Key{Mint/Master}. That means performing same operation will fail always.",
+                        ksException.isTransientFailure());
+    }
+
+    @Test
     public void testKeyStore_ImportWrappedKeyWrappingKeyMissing() throws Exception {
         final String EXPECTED_FAILURE = "Failed to import wrapped key. Keystore error code: 7";
         KeyStoreException exception = null;
@@ -319,7 +369,12 @@
     }
 
     public byte[] wrapKey(PublicKey publicKey, byte[] keyMaterial, byte[] mask,
-            DERSequence authorizationList)
+                          DERSequence authorizationList) throws Exception {
+        return wrapKey(publicKey, keyMaterial, mask, authorizationList, true);
+    }
+
+    public byte[] wrapKey(PublicKey publicKey, byte[] keyMaterial, byte[] mask,
+            DERSequence authorizationList, boolean correctWrappingRequired)
             throws Exception {
         // Build description
         DEREncodableVector descriptionItems = new DEREncodableVector();
@@ -338,7 +393,13 @@
         // Encrypt ephemeral keys
         OAEPParameterSpec spec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
         Cipher pkCipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
-        pkCipher.init(Cipher.ENCRYPT_MODE, publicKey, spec);
+        if (correctWrappingRequired) {
+            pkCipher.init(Cipher.ENCRYPT_MODE, publicKey, spec);
+        } else {
+            // Use incorrect OAEPParameters while initializing cipher. By default, main digest and
+            // MGF1 digest are SHA-1 here.
+            pkCipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        }
         byte[] encryptedEphemeralKeys = pkCipher.doFinal(aesKeyBytes);
 
         // Encrypt secure key
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 52da62e..93a2e39 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -62,6 +62,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -514,6 +515,9 @@
 
     @Test
     public void testEcAttestation_UniqueIdWorksWithCorrectPermission() throws Exception {
+        assumeTrue("Device doesn't have secure lock screen",
+                TestUtils.hasSecureLockScreen(getContext()));
+
         String keystoreAlias = "test_key";
         KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
                 .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
@@ -994,12 +998,18 @@
                     TestUtils.isPropertyEmptyOrUnknown(Build.BRAND_FOR_ATTESTATION)
                     ? Build.BRAND : Build.BRAND_FOR_ATTESTATION;
             assertThat(keyDetailsList.getBrand()).isEqualTo(platformReportedBrand);
-            assertEquals(Build.DEVICE, keyDetailsList.getDevice());
+            final String platformReportedDevice =
+                    TestUtils.isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION)
+                            ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION;
+            assertThat(keyDetailsList.getDevice()).isEqualTo(platformReportedDevice);
             final String platformReportedProduct =
                     TestUtils.isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION)
                     ? Build.PRODUCT : Build.PRODUCT_FOR_ATTESTATION;
             assertThat(keyDetailsList.getProduct()).isEqualTo(platformReportedProduct);
-            assertEquals(Build.MANUFACTURER, keyDetailsList.getManufacturer());
+            final String platformReportedManufacturer =
+                    TestUtils.isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION)
+                            ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION;
+            assertThat(keyDetailsList.getManufacturer()).isEqualTo(platformReportedManufacturer);
             final String platformReportedModel =
                     TestUtils.isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)
                     ? Build.MODEL : Build.MODEL_FOR_ATTESTATION;
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java
index bc99b75..88e4a9c 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java
@@ -27,23 +27,26 @@
 import android.security.keystore.KeyInfo;
 import android.security.keystore.KeyProperties;
 import android.test.MoreAsserts;
+import android.text.TextUtils;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.google.common.collect.ObjectArrays;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.Provider;
+import java.security.Provider.Service;
+import java.security.SecureRandom;
 import java.security.Security;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.ECGenParameterSpec;
-import java.security.Provider.Service;
-import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.HashSet;
@@ -52,11 +55,11 @@
 import java.util.Set;
 import java.util.TreeMap;
 
+import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
 import javax.crypto.SecretKey;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import javax.crypto.spec.IvParameterSpec;
 
 @RunWith(AndroidJUnit4.class)
 public class KeyGeneratorTest {
@@ -791,6 +794,117 @@
         }
     }
 
+    @Test
+    public void testUniquenessOfAesKeys() throws Exception {
+        testUniquenessOfAesKeys(false /* useStrongbox */);
+    }
+
+    @Test
+    public void testUniquenessOfAesKeysInStrongBox() throws Exception {
+        TestUtils.assumeStrongBox();
+        testUniquenessOfAesKeys(true /* useStrongbox */);
+    }
+
+    private void testUniquenessOfAesKeys(boolean useStrongbox) throws Exception {
+        assertUniqueAesEncryptionForNKeys("AES/ECB/NoPadding", useStrongbox);
+        assertUniqueAesEncryptionForNKeys("AES/CBC/NoPadding", useStrongbox);
+    }
+
+    private void assertUniqueAesEncryptionForNKeys(String algoTransform, boolean useStrongbox)
+            throws Exception {
+        byte[] randomMsg = new byte[16];
+        SecureRandom.getInstance("SHA1PRNG").nextBytes(randomMsg);
+        byte[][] msgArr = new byte[][]{
+                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+                {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+                "16 char message.".getBytes(StandardCharsets.UTF_8),
+                randomMsg
+        };
+        for (byte[] msg : msgArr) {
+            int numberOfKeysToTest = 10;
+            Set results = new HashSet();
+            boolean isCbcMode = algoTransform.contains("CBC");
+            byte[] iv = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+            for (int i = 0; i < numberOfKeysToTest; i++) {
+                KeyGenerator keyGenerator = getKeyGenerator("AES");
+                keyGenerator.init(getWorkingSpec(KeyProperties.PURPOSE_ENCRYPT)
+                        .setBlockModes(isCbcMode
+                                ? KeyProperties.BLOCK_MODE_CBC : KeyProperties.BLOCK_MODE_ECB)
+                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                        .setRandomizedEncryptionRequired(false)
+                        .setIsStrongBoxBacked(useStrongbox)
+                        .build());
+                SecretKey key = keyGenerator.generateKey();
+                Cipher cipher = Cipher.getInstance(algoTransform,
+                        TestUtils.EXPECTED_CRYPTO_OP_PROVIDER_NAME);
+                if (isCbcMode) {
+                    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
+                } else {
+                    cipher.init(Cipher.ENCRYPT_MODE, key);
+                }
+                byte[] cipherText = msg == null ? cipher.doFinal() : cipher.doFinal(msg);
+                // Add generated cipher text to HashSet so that only unique cipher text will be
+                // counted.
+                results.add(new String(cipherText));
+            }
+            // Verify unique cipher text is generated for all different keys
+            assertEquals(TextUtils.formatSimple("%d different cipher text should have been"
+                                + " generated for %d different keys. Failed for message \"%s\".",
+                            numberOfKeysToTest, numberOfKeysToTest, new String(msg)),
+                    numberOfKeysToTest, results.size());
+        }
+    }
+
+    @Test
+    public void testUniquenessOfHmacKeys() throws Exception {
+        testUniquenessOfHmacKeys(false /* useStrongbox */);
+    }
+
+    @Test
+    public void testUniquenessOfHmacKeysInStrongBox() throws Exception {
+        TestUtils.assumeStrongBox();
+        testUniquenessOfHmacKeys(true /* useStrongbox */);
+    }
+
+    private void testUniquenessOfHmacKeys(boolean useStrongbox)
+            throws Exception {
+        int numberOfKeysToTest = 10;
+        byte[] randomMsg = new byte[16];
+        SecureRandom.getInstance("SHA1PRNG").nextBytes(randomMsg);
+        byte[][] msgArr = new byte[][]{
+                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+                {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+                "dummymessage1234".getBytes(StandardCharsets.UTF_8),
+                randomMsg,
+                {},
+                null
+        };
+        for (byte[] msg : msgArr) {
+            Set results = new HashSet();
+            for (int i = 0; i < numberOfKeysToTest; i++) {
+                KeyGenerator keyGenerator = getKeyGenerator("HmacSHA256");
+                keyGenerator.init(getWorkingSpec(KeyProperties.PURPOSE_SIGN)
+                        .setIsStrongBoxBacked(useStrongbox)
+                        .build());
+                SecretKey key = keyGenerator.generateKey();
+                Mac mac = Mac.getInstance("HMACSHA256",
+                        TestUtils.EXPECTED_CRYPTO_OP_PROVIDER_NAME);
+                mac.init(key);
+                byte[] macSign = mac.doFinal(msg);
+                // Add generated mac signature to HashSet so that unique signatures will be counted
+                results.add(new String(macSign));
+            }
+            // Verify unique MAC is generated for all different keys
+            assertEquals(TextUtils.formatSimple("%d different MAC should have been generated for "
+                    + "%d different keys.", numberOfKeysToTest, numberOfKeysToTest),
+                    numberOfKeysToTest, results.size());
+        }
+    }
+
     private static KeyGenParameterSpec.Builder getWorkingSpec() {
         return getWorkingSpec(0);
     }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
index cd55afb..f934e15 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
@@ -29,6 +29,7 @@
 import android.security.keystore.KeyInfo;
 import android.security.keystore.KeyProperties;
 import android.test.MoreAsserts;
+import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -47,6 +48,7 @@
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
@@ -60,6 +62,7 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.Security;
+import java.security.Signature;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.ECKey;
@@ -85,6 +88,7 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
+import javax.crypto.KeyAgreement;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
@@ -2087,4 +2091,130 @@
     private KeyGenParameterSpec.Builder getWorkingSpec(int purposes) {
         return new KeyGenParameterSpec.Builder(TEST_ALIAS_1, purposes);
     }
+
+    @Test
+    public void testUniquenessOfRsaKeys() throws Exception {
+        KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN)
+                .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
+                .setDigests(KeyProperties.DIGEST_SHA256);
+        testUniquenessOfAsymmetricKeys("RSA", "SHA256WithRSA",
+                specBuilder.build());
+    }
+
+    @Test
+    public void testUniquenessOfRsaKeysInStrongBox() throws Exception {
+        TestUtils.assumeStrongBox();
+        KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN)
+                .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
+                .setDigests(KeyProperties.DIGEST_SHA256);
+        specBuilder.setIsStrongBoxBacked(true);
+        testUniquenessOfAsymmetricKeys("RSA", "SHA256WithRSA",
+                specBuilder.build());
+    }
+
+    @Test
+    public void testUniquenessOfEcKeys() throws Exception {
+        KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN)
+                .setDigests(KeyProperties.DIGEST_SHA256);
+        testUniquenessOfAsymmetricKeys("EC", "SHA256WithECDSA",
+                specBuilder.build());
+    }
+
+    @Test
+    public void testUniquenessOfEcKeysInStrongBox() throws Exception {
+        TestUtils.assumeStrongBox();
+        KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN)
+                .setDigests(KeyProperties.DIGEST_SHA256);
+        specBuilder.setIsStrongBoxBacked(true);
+        testUniquenessOfAsymmetricKeys("EC", "SHA256WithECDSA",
+                specBuilder.build());
+    }
+
+    @Test
+    public void testUniquenessOfEd25519Keys() throws Exception {
+        KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN)
+                .setAlgorithmParameterSpec(new ECGenParameterSpec("ed25519"))
+                .setDigests(KeyProperties.DIGEST_NONE);
+        testUniquenessOfAsymmetricKeys("EC", "Ed25519",
+                specBuilder.build());
+    }
+
+    private void testUniquenessOfAsymmetricKeys(String keyAlgo, String signAlgo,
+                                                KeyGenParameterSpec spec) throws Exception {
+        byte []randomMsg = new byte[20];
+        SecureRandom.getInstance("SHA1PRNG").nextBytes(randomMsg);
+        byte[][] msgArr = new byte[][]{
+                {},
+                "message".getBytes(StandardCharsets.UTF_8),
+                randomMsg
+        };
+        for (byte[] msg : msgArr) {
+            int numberOfKeysToTest = 10;
+            Set results = new HashSet();
+            for (int i = 0; i < numberOfKeysToTest; i++) {
+                KeyPairGenerator generator = getGenerator(keyAlgo);
+                generator.initialize(spec);
+                KeyPair keyPair = generator.generateKeyPair();
+                Signature signer = Signature.getInstance(signAlgo,
+                        TestUtils.EXPECTED_CRYPTO_OP_PROVIDER_NAME);
+                signer.initSign(keyPair.getPrivate());
+                signer.update(msg);
+                byte[] signature = signer.sign();
+                // Add generated signature to HashSet so that only unique signatures will be
+                // counted.
+                results.add(new String(signature));
+            }
+            // Verify different signatures are generated for fixed message with all different keys
+            assertEquals(TextUtils.formatSimple("%d different signature should have been generated"
+                    + " for %d different keys.", numberOfKeysToTest, numberOfKeysToTest),
+                    numberOfKeysToTest, results.size());
+        }
+    }
+
+    @Test
+    public void testUniquenessOfEcdhKeys() throws Exception {
+        testUniquenessOfECAgreementKeys("secp256r1", "ECDH", false /* useStrongbox */);
+    }
+
+    @Test
+    public void testUniquenessOfEcdhKeysInStrongBox() throws Exception {
+        TestUtils.assumeStrongBox();
+        testUniquenessOfECAgreementKeys("secp256r1", "ECDH", true /* useStrongbox */);
+    }
+
+    @Test
+    public void testUniquenessOfX25519Keys() throws Exception {
+        testUniquenessOfECAgreementKeys("x25519", "XDH", false /* useStrongbox */);
+    }
+
+    private void testUniquenessOfECAgreementKeys(String curve, String agreeAlgo,
+                                                        boolean useStrongbox) throws Exception {
+        int numberOfKeysToTest = 10;
+        Set results = new HashSet();
+        KeyGenParameterSpec spec = getWorkingSpec(KeyProperties.PURPOSE_AGREE_KEY)
+                .setIsStrongBoxBacked(useStrongbox)
+                .setAlgorithmParameterSpec(new ECGenParameterSpec(curve))
+                .build();
+        // Generate a local key pair
+        KeyPairGenerator generator = getGenerator("EC");
+        generator.initialize(spec);
+        KeyPair keyPairA = generator.generateKeyPair();
+
+        for (int i = 0; i < numberOfKeysToTest; i++) {
+            // Generate remote key
+            generator.initialize(spec);
+            KeyPair keyPairB = generator.generateKeyPair();
+            KeyAgreement keyAgreement = KeyAgreement.getInstance(agreeAlgo,
+                    EXPECTED_PROVIDER_NAME);
+            keyAgreement.init(keyPairB.getPrivate());
+            keyAgreement.doPhase(keyPairA.getPublic(), true);
+            byte[] secret = keyAgreement.generateSecret();
+            // Add generated secret to HashSet so that only unique secrets will be counted.
+            results.add(new String(secret));
+        }
+        // Verify different key agreement secrets generated for all different keys
+        assertEquals(TextUtils.formatSimple("%d different secrets should have been generated for "
+                + "%d different keys.", numberOfKeysToTest, numberOfKeysToTest),
+                numberOfKeysToTest, results.size());
+    }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java
index 255287b..5082127 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java
@@ -27,7 +27,13 @@
 import libcore.java.security.StandardNames;
 import libcore.java.security.TestKeyStore;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -68,6 +74,7 @@
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 
+@RunWith(Parameterized.class)
 public class KeyStoreTest {
 
     private static final HashMap<String, PrivateKeyEntry> sPrivateKeys
@@ -107,6 +114,24 @@
     private static final ProtectionParameter PARAM_KEY = new PasswordProtection(PASSWORD_KEY);
     private static final ProtectionParameter PARAM_BAD = new PasswordProtection(PASSWORD_BAD);
 
+    @Parameters
+    public static Object[] data() {
+        return new Object[] {"true", "false"};
+    }
+
+    @Parameter
+    public String mApexCertsEnabled;
+
+    @Before
+    public void setUp() {
+        System.setProperty("system.certs.enabled", mApexCertsEnabled);
+    }
+
+    @After
+    public void tearDown() {
+        System.clearProperty("system.certs.enabled");
+    }
+
     private static PrivateKeyEntry getPrivateKey() {
         return getPrivateKey("RSA");
     }
diff --git a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
index 90c5894..c57086c 100644
--- a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
+++ b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
@@ -1167,4 +1167,9 @@
     public static boolean isPropertyEmptyOrUnknown(String property) {
         return TextUtils.isEmpty(property) || property.equals(Build.UNKNOWN);
     }
+
+    public static boolean hasSecureLockScreen(Context context) {
+        PackageManager pm = context.getPackageManager();
+        return (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN));
+    }
 }
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
index 1309d60..948583d 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
@@ -108,7 +108,7 @@
     private static final String TAG = "AudioManagerTest";
 
     private static final long ASYNC_TIMING_TOLERANCE_MS = 50;
-    private static final long POLL_TIME_VOLUME_ADJUST = 200;
+    private static final long POLL_TIME_VOLUME_ADJUST = 400;
     private static final long POLL_TIME_UPDATE_INTERRUPTION_FILTER = 5000;
     private static final int MP3_TO_PLAY = R.raw.testmp3; // ~ 5 second mp3
     private static final long POLL_TIME_PLAY_MUSIC = 2000;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
index 212642b..b584643 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
@@ -42,6 +42,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Before;
@@ -229,7 +230,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{4}_{5})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}_{3}_{4}_{5}")
     public static Collection<Object[]> input() {
         final List<Object[]> baseArgsList = Arrays.asList(new Object[][]{
                 // width, height, bitrate
@@ -270,6 +271,15 @@
         mUseHighBitDepth = useHighBitDepth;
     }
 
+    @ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
+            "android.opengl.GLES20#glReadPixels",
+            "android.opengl.GLES30#glReadPixels",
+            "android.media.format.MediaFormat#KEY_ALLOW_FRAME_DROP",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_Format32bitABGR2101010",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testVideoEdit() throws Throwable {
         VideoEditWrapper.runTest(this);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
index 30e8477..894d4b1 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
@@ -44,6 +44,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Before;
@@ -181,7 +182,7 @@
         assumeTrue(MediaUtils.supports(mDecoderName, format));
     }
 
-    @Parameterized.Parameters(name = "{index}({0}:{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // Mime, width, height, bit-rate, allow bt601, allow bt709
@@ -1268,6 +1269,11 @@
      * a series of byte[] buffers and decoded into ByteBuffers.  The output is checked for
      * validity.
      */
+    @ApiTest(apis = {"android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Planar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedSemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_TI_FormatYUV420PackedSemiPlanar"})
     @Test
     public void testEncodeDecodeVideoFromBufferToBuffer() throws Exception {
         encodeDecodeVideoFromBuffer(false);
@@ -1285,6 +1291,16 @@
      * the test thread, so we have to hand control off to a new thread for the duration of
      * the test.
      */
+    @ApiTest(apis = {"android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Planar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedSemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_TI_FormatYUV420PackedSemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromBufferToSurface() throws Throwable {
         BufferToSurfaceWrapper.runTest(this);
@@ -1294,11 +1310,22 @@
      * Tests streaming of AVC through the encoder and decoder.  Data is provided through
      * a Surface and decoded onto a Surface.  The output is checked for validity.
      */
+    @ApiTest(apis = {"android.media.MediaCodec#createInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToSurface() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, false, false);
     }
-
+    @ApiTest(apis = {"AMediaCodec_createInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToSurfaceNdk() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, false, USE_NDK);
@@ -1308,11 +1335,25 @@
      * Tests streaming of video through the encoder and decoder.  Data is provided through
      * a PersistentSurface and decoded onto a Surface.  The output is checked for validity.
      */
+    @ApiTest(apis = {"android.media.MediaCodec#createPersistentInputSurface",
+            "android.media.MediaCodec#setInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToPersistentSurface() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, true, false);
     }
 
+    @ApiTest(apis = {"AMediaCodec_createPersistentInputSurface",
+            "AMediaCodec_setInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToPersistentSurfaceNdk() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, true, USE_NDK);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
old mode 100755
new mode 100644
index 96f05c6..fa4e2ac
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -48,6 +48,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Before;
@@ -172,7 +173,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}:{6})")
+    @Parameterized.Parameters(name = "{index}_{0}_{6}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // mediaType, width, height,  bitrate, framerate, level
@@ -189,6 +190,13 @@
      *
      * @throws Exception
      */
+    @ApiTest(apis = {"AMediaCodec_createInputSurface",
+            "android.hardware.display.DisplayManager#createVirtualDisplay",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeVirtualDisplay() throws Throwable {
         if (!MediaUtils.check(sIsAtLeastR, "test needs Android 11")) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
index 67c3ce8..1225822 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -41,7 +41,7 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.Preconditions;
 
 import org.junit.After;
@@ -69,6 +69,30 @@
  * <p>It also tests the way the codec config buffers need to be passed from the MediaCodec to the
  * MediaMuxer.
  */
+@ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
+        "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+        "android.media.MediaFormat#KEY_BIT_RATE",
+        "android.media.MediaFormat#KEY_COLOR_FORMAT",
+        "android.media.MediaFormat#KEY_FRAME_RATE",
+        "android.media.MediaFormat#KEY_I_FRAME_INTERVAL",
+        "android.media.MediaFormat#KEY_SAMPLE_RATE",
+        "android.media.MediaFormat#KEY_CHANNEL_COUNT",
+        "android.media.MediaFormat#KEY_PROFILE",
+        "android.media.MediaFormat#KEY_AAC_PROFILE",
+        "android.media.MediaExtractor#setDataSource",
+        "android.media.MediaExtractor#getTrackCount",
+        "android.media.MediaExtractor#getTrackFormat",
+        "android.media.MediaExtractor#selectTrack",
+        "android.media.MediaExtractor#readSampleData",
+        "android.media.MediaExtractor#getSampleTime",
+        "android.media.MediaExtractor#getSampleFlags",
+        "android.media.MediaExtractor#advance",
+        "android.media.MediaExtractor#release",
+        "android.media.MediaMuxer#start",
+        "android.media.MediaMuxer#stop",
+        "android.media.MediaMuxer#addTrack",
+        "android.media.MediaMuxer#writeSampleData",
+        "android.media.MediaMuxer#release"})
 @TargetApi(18)
 @AppModeFull(reason = "Instant apps cannot access the SD card")
 @RunWith(AndroidJUnit4.class)
@@ -145,7 +169,6 @@
         super.tearDown();
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMuxQCIF() throws Throwable {
         if(!setSize(176, 144)) return;
@@ -155,7 +178,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMuxQVGA() throws Throwable {
         if(!setSize(320, 240)) return;
@@ -165,7 +187,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMux720p() throws Throwable {
         if(!setSize(1280, 720)) return;
@@ -175,7 +196,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMux2160pHevc() throws Throwable {
         if(!setSize(3840, 2160)) return;
@@ -185,7 +205,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.1.1", "5.1.2"})
     @Test
     public void testExtractDecodeEditEncodeMuxAudio() throws Throwable {
         if(!setSize(1280, 720)) return;
@@ -195,7 +214,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.1.1", "5.1.2", "5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMuxAudioVideo() throws Throwable {
         if(!setSize(1280, 720)) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
index 29a14a0..5822063 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
@@ -41,6 +41,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.NonMainlineTest;
 import com.android.compatibility.common.util.Preconditions;
@@ -92,6 +93,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testDecodeShortVideo() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -112,6 +114,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testDecodeShortAudio() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -132,6 +135,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testEncodeShortAudio() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -145,6 +149,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testEncodeShortVideo() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
index bb769ca..b94f2de8 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
@@ -45,6 +45,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ApiTest;
+
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -80,6 +82,7 @@
         public final int uid;
     }
 
+    @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
     @Test
     public void testCreateCodecForAnotherProcessWithoutPermissionsThrows() throws Exception {
         CodecInfo codecInfo = getFirstVideoHardwareDecoder();
@@ -102,6 +105,7 @@
 
     // A process with lower priority (e.g. background app) should not be able to reclaim
     // MediaCodec resources from a process with higher priority (e.g. foreground app).
+    @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
     @Test
     public void testLowerPriorityProcessFailsToReclaimResources() throws Exception {
         CodecInfo codecInfo = getFirstVideoHardwareDecoder();
@@ -188,6 +192,7 @@
 
     // A process with higher priority (e.g. foreground app) should be able to reclaim
     // MediaCodec resources from a process with lower priority (e.g. background app).
+    @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
     @Test
     public void testHigherPriorityProcessReclaimsResources() throws Exception {
         CodecInfo codecInfo = getFirstVideoHardwareDecoder();
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
index a7039d4..52d01b2 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
@@ -50,6 +50,7 @@
 import android.media.cts.TestUtils;
 import android.opengl.GLES20;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -67,6 +68,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.Preconditions;
 
@@ -141,6 +143,18 @@
      * A selective test to ensure proper exceptions are thrown from MediaCodec
      * methods when called in incorrect operational states.
      */
+    @ApiTest(apis = {"MediaCodec#createByCodecName", "MediaCodec#createDecoderByType",
+            "MediaCodec#createEncoderByType", "MediaCodec#start", "MediaCodec#flush",
+            "MediaCodec#configure", "MediaCodec#dequeueInputBuffer",
+            "MediaCodec#dequeueOutputBuffer", "MediaCodec#createInputSurface",
+            "MediaCodec#getInputBuffers", "MediaCodec#getQueueRequest",
+            "MediaCodec#getOutputFrame", "MediaCodec#stop", "MediaCodec#release",
+            "MediaCodec#getCodecInfo", "MediaCodec#getSupportedVendorParameters",
+            "MediaCodec#getParameterDescriptor",
+            "MediaCodec#subscribeToVendorParameters",
+            "MediaCodec#unsubscribeFromVendorParameters",
+            "MediaCodec#getInputBuffer", "MediaCodec#getOutputBuffer",
+            "MediaCodec#setCallback", "MediaCodec#getName"})
     @Test
     public void testException() throws Exception {
         boolean tested = false;
@@ -244,6 +258,7 @@
             fail("flush should not return MediaCodec.CodecException on wrong state");
         } catch (IllegalStateException e) { // expected
         }
+
         MediaCodecInfo codecInfo = codec.getCodecInfo(); // obtaining the codec info now is fine.
         try {
             int bufIndex = codec.dequeueInputBuffer(0);
@@ -542,6 +557,7 @@
      * <br> calling createInputSurface() after start() throws exception
      * <br> calling createInputSurface() with a non-Surface color format is not required to throw exception
      */
+    @ApiTest(apis = "MediaCodec#createInputSurface")
     @Test
     public void testCreateInputSurfaceErrors() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -593,6 +609,7 @@
      * <br> signaling EOS twice throws exception
      * <br> submitting a frame after EOS throws exception [TODO]
      */
+    @ApiTest(apis = "MediaCodec#signalEndOfInputStream")
     @Test
     public void testSignalSurfaceEOS() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -651,6 +668,7 @@
      * Tests:
      * <br> stopping with buffers in flight doesn't crash or hang
      */
+    @ApiTest(apis = "MediaCodec#stop")
     @Test
     public void testAbruptStop() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -707,6 +725,7 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodec#flush", "MediaCodec#release"})
     @Test
     public void testReleaseAfterFlush() throws IOException, InterruptedException {
         String mimes[] = new String[] { MIME_TYPE, MIME_TYPE_AUDIO};
@@ -770,11 +789,13 @@
         callbackThread.join();
     }
 
+    @ApiTest(apis = {"MediaCodec#setCallback", "MediaCodec#flush", "MediaCodec#reset"})
     @Test
     public void testAsyncFlushAndReset() throws Exception, InterruptedException {
         testAsyncReset(false /* testStop */);
     }
 
+    @ApiTest(apis = {"MediaCodec#setCallback", "MediaCodec#stop", "MediaCodec#reset"})
     @Test
     public void testAsyncStopAndReset() throws Exception, InterruptedException {
         testAsyncReset(true /* testStop */);
@@ -1105,6 +1126,7 @@
      * Tests:
      * <br> dequeueInputBuffer() fails when encoder configured with an input Surface
      */
+    @ApiTest(apis = {"MediaCodec#dequeueInputBuffer", "MediaCodec#getMetrics"})
     @Test
     public void testDequeueSurface() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -1164,6 +1186,8 @@
      * <br> configure() encoder with Surface, re-configure() without Surface works
      * <br> sending EOS with signalEndOfInputStream on non-Surface encoder fails
      */
+    @ApiTest(apis = {"MediaCodec#configure", "MediaCodec#signalEndOfInputStream",
+            "MediaCodec#getMetrics"})
     @Test
     public void testReconfigureWithoutSurface() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -1233,6 +1257,7 @@
         }
     }
 
+    @ApiTest(apis = "MediaCodec#flush")
     @Test
     public void testDecodeAfterFlush() throws InterruptedException {
         testDecodeAfterFlush(true /* audio */);
@@ -1414,6 +1439,7 @@
      * Tests whether decoding a short group-of-pictures succeeds. The test queues a few video frames
      * then signals end-of-stream. The test fails if the decoder doesn't output the queued frames.
      */
+    @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
     @Test
     public void testDecodeShortInput() throws InterruptedException {
         // Input buffers from this input video are queued up to and including the video frame with
@@ -1525,6 +1551,10 @@
     /**
      * Tests creating two decoders for {@link #MIME_TYPE_AUDIO} at the same time.
      */
+    @ApiTest(apis = {"MediaCodec#createDecoderByType",
+            "android.media.MediaFormat#KEY_MIME",
+            "android.media.MediaFormat#KEY_SAMPLE_RATE",
+            "android.media.MediaFormat#KEY_CHANNEL_COUNT"})
     @Test
     public void testCreateTwoAudioDecoders() {
         final MediaFormat format = MediaFormat.createAudioFormat(
@@ -1572,6 +1602,10 @@
     /**
      * Tests creating an encoder and decoder for {@link #MIME_TYPE_AUDIO} at the same time.
      */
+    @ApiTest(apis = {"MediaCodec#createDecoderByType", "MediaCodec#createEncoderByType",
+            "android.media.MediaFormat#KEY_MIME",
+            "android.media.MediaFormat#KEY_SAMPLE_RATE",
+            "android.media.MediaFormat#KEY_CHANNEL_COUNT"})
     @Test
     public void testCreateAudioDecoderAndEncoder() {
         if (!supportsCodec(MIME_TYPE_AUDIO, true)) {
@@ -1630,6 +1664,12 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodec#createEncoderByType",
+            "android.media.MediaFormat#KEY_MIME",
+            "android.media.MediaFormat#KEY_SAMPLE_RATE",
+            "android.media.MediaFormat#KEY_CHANNEL_COUNT",
+            "android.media.MediaFormat#KEY_WIDTH",
+            "android.media.MediaFormat#KEY_HEIGHT"})
     @Test
     public void testConcurrentAudioVideoEncodings() throws InterruptedException {
         if (!supportsCodec(MIME_TYPE_AUDIO, true)) {
@@ -1678,6 +1718,7 @@
         public int mBitRate;
     }
 
+    @ApiTest(apis = {"MediaCodec#CryptoInfo", "MediaCodec#CryptoInfo#Pattern"})
     @Test
     public void testCryptoInfoPattern() {
         CryptoInfo info = new CryptoInfo();
@@ -1978,6 +2019,7 @@
     /**
      * Tests MediaCodec.CryptoException
      */
+    @ApiTest(apis = "MediaCodec#CryptoException")
     @Test
     public void testCryptoException() {
         int errorCode = CryptoException.ERROR_KEY_EXPIRED;
@@ -1996,6 +2038,8 @@
      *
      * As of Q, any codec of type "audio/raw" must support PCM encoding float.
      */
+    @ApiTest(apis = {"android.media.AudioFormat#ENCODING_PCM_16BIT",
+            "android.media.AudioFormat#ENCODING_PCM_FLOAT"})
     @MediumTest
     @Test
     public void testPCMEncoding() throws Exception {
@@ -2121,6 +2165,7 @@
         return actualEncoding;
     }
 
+    @ApiTest(apis = "android.media.AudioFormat#KEY_FLAC_COMPRESSION_LEVEL")
     @SmallTest
     @Test
     public void testFlacIdentity() throws Exception {
@@ -2174,6 +2219,7 @@
         }
     }
 
+    @ApiTest(apis = "MediaCodec#release")
     @Test
     public void testAsyncRelease() throws Exception {
         OutputSurface outputSurface = new OutputSurface(1, 1);
@@ -2261,6 +2307,7 @@
         }
     }
 
+    @ApiTest(apis = "MediaCodec#setAudioPresentation")
     @Test
     public void testSetAudioPresentation() throws Exception {
         MediaFormat format = MediaFormat.createAudioFormat(
@@ -2276,6 +2323,7 @@
                 (new AudioPresentation.Builder(42 /* presentationId */)).build());
     }
 
+    @ApiTest(apis = "android.media.MediaFormat#KEY_PREPEND_HEADER_TO_SYNC_FRAMES")
     @Test
     public void testPrependHeadersToSyncFrames() throws IOException {
         MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -2350,6 +2398,7 @@
      * codec is flushed after the first buffer is queued, so this test walks
      * through the scenario.
      */
+    @ApiTest(apis = "MediaCodec#flush")
     @Test
     public void testFlushAfterFirstBuffer() throws Exception {
         if (MediaUtils.check(mIsAtLeastR, "test needs Android 11")) {
@@ -2447,6 +2496,10 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodec#getSupportedVendorParameters",
+            "MediaCodec#getParameterDescriptor",
+            "MediaCodec#subscribeToVendorParameters",
+            "MediaCodec#unsubscribeFromVendorParameters"})
     @Test
     public void testVendorParameters() {
         if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) {
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
index effc3eb..6c67812 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
@@ -26,6 +26,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Assume;
@@ -125,7 +126,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}:{1}:{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 {VP8_MIME, VIDEO_ControlRateConstant},
@@ -625,41 +626,65 @@
         }
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testBasic() throws Exception {
         internalTestBasic(mCodecName, mCodecMimeType, mBitRateMode);
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testAsyncEncode() throws Exception {
         internalTestAsyncEncoding(mCodecName, mCodecMimeType, mBitRateMode);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
     @Test
     public void testSyncFrame() throws Exception {
         internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, false);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
     @Test
     public void testSyncFrameNdk() throws Exception {
         internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, true);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
     @Test
     public void testDynamicBitrateChange() throws Exception {
         internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, false);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
     @Test
     public void testDynamicBitrateChangeNdk() throws Exception {
         internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, true);
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testEncoderQuality() throws Exception {
         internalTestEncoderQuality(mCodecName, mCodecMimeType, mBitRateMode);
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testParallelEncodingAndDecoding() throws Exception {
         Assume.assumeTrue("Parallel Encode Decode test is run only for VBR mode",
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
index 78021f4..fb61f78 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.NonMainlineTest;
 
 import org.junit.Test;
@@ -96,6 +97,7 @@
         return testParams;
     }
 
+    @ApiTest(apis = "android.media.MediaFormat#KEY_ROTATION")
     @Test
     public void testRendering800x480Rotated() throws Throwable {
         if (mImpl.isConcurrentEncodingDecodingSupported(
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
index aae5727..4239679 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
@@ -26,6 +26,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Assume;
@@ -96,7 +97,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}:{1}:{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 {AVC_MIME, VIDEO_ControlRateConstant},
@@ -195,6 +196,9 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#FEATURE_EncodingStatistics",
+            "android.media.MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL",
+            "android.media.MediaFormat#KEY_VIDEO_QP_AVERAGE"})
     @Test
     public void testEncodingStatisticsAvgQp() throws Exception {
        testEncStatRateAvgQp(mCodecName, mCodecMimeType, mBitRateMode);
diff --git a/tests/tests/media/decoder/AndroidTest.xml b/tests/tests/media/decoder/AndroidTest.xml
index 55fe608..7519a5c 100644
--- a/tests/tests/media/decoder/AndroidTest.xml
+++ b/tests/tests/media/decoder/AndroidTest.xml
@@ -40,7 +40,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaDecoderTestCases-1.1" />
+        <option name="media-folder-name" value="CtsMediaDecoderTestCases-2.0" />
         <option name="dynamic-config-module" value="CtsMediaDecoderTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/decoder/DynamicConfig.xml b/tests/tests/media/decoder/DynamicConfig.xml
index f7df099..ab6d882 100644
--- a/tests/tests/media/decoder/DynamicConfig.xml
+++ b/tests/tests/media/decoder/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-    <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/decoder/CtsMediaDecoderTestCases-1.1.zip</value>
+    <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/decoder/CtsMediaDecoderTestCases-2.0.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/tests/media/decoder/copy_media.sh b/tests/tests/media/decoder/copy_media.sh
index d5392e5..3d245e2 100755
--- a/tests/tests/media/decoder/copy_media.sh
+++ b/tests/tests/media/decoder/copy_media.sh
@@ -17,4 +17,4 @@
 [ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
 source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
 get_adb_options "$@"
-copy_media "decoder" "CtsMediaDecoderTestCases-1.1"
+copy_media "decoder" "CtsMediaDecoderTestCases-2.0"
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
index 288288a..fa9c4a2 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
@@ -277,7 +277,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}_{0}")
     public static Collection<Object[]> input() {
         final List<Object> exhaustiveArgsList = Arrays.asList(new Object[]{
                 H264(), HEVC(), VP8(), VP9(), AV1(), Mpeg2(), Mpeg4(), H263()
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java
index c7d46fc..e96d05a 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java
@@ -86,7 +86,7 @@
 
     private DeviceReportLog mReportLog;
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    @Parameterized.Parameters(name = "{index}_{0}")
     public static Collection<Object[]> input() throws Exception {
         final String[] mediaTypeList = new String[] {MediaFormat.MIMETYPE_VIDEO_VP9};
         final List<Object[]> argsList = new ArrayList<>();
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderRenderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderRenderTest.java
new file mode 100644
index 0000000..e91cf54
--- /dev/null
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderRenderTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2023 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.media.decoder.cts;
+
+import static android.media.decoder.cts.DecoderSetup.createCodecFor;
+import static android.media.decoder.cts.DecoderSetup.createMediaExtractor;
+import static android.media.decoder.cts.DecoderSetup.getFirstVideoTrack;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.cts.MediaHeavyPresubmitTest;
+import android.media.cts.MediaTestBase;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
+
+import com.android.compatibility.common.util.ApiTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class verifies video frames are rendered and the app is notified.
+ * <p>
+ * This test uses MediaCodec to decode short videos, renders each video frame to the display using a
+ * SurfaceView, and then verifies the {@link MediaCodec.OnFramerenderedListener#onFrameRendered)
+ * callback is fired for each of these video frames in a reasonable amount of time.
+ * </p>
+ */
+@MediaHeavyPresubmitTest
+@AppModeFull(reason = "Instant apps behave the same as full apps when it comes to decoders")
+@RunWith(AndroidJUnit4.class)
+public class DecoderRenderTest extends MediaTestBase {
+    private static final String TAG = "DecoderRenderTest";
+    private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
+
+    @Before
+    @Override
+    public void setUp() throws Throwable {
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        super.tearDown();
+    }
+
+    /*
+     * Tests that {@link MediaCodec.OnFramerenderedListener#onFrameRendered) is called for every
+     * video frame when playing back a full VP9 video.
+     */
+    @Test
+    @ApiTest(apis = {"android.media.MediaCodec.OnFrameRenderedListener#onFrameRendered"})
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+    public void onFrameRendered_indicatesAllFramesRendered_vp9() throws Exception {
+        onFrameRendered_indicatesAllFramesRendered(
+                "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
+    }
+
+    public class MutableData {
+        public long renderTimeNs = 0;
+        public long previousPresentationTimeUs = -1;
+    }
+
+    // TODO(b/234833109): Run this test against a variety of video files and codecs.
+    private void onFrameRendered_indicatesAllFramesRendered(String fileName) throws Exception {
+        // TODO(b/268212517): Preplay one video frame to prime the video and graphics pipeline to
+        // simulate a device in its normal steady-state (less chances for dropped frames). This
+        // avoids problems, for example, with GPU shaders being compiled when rendering the first
+        // video frame after boot which can cause subsequent frames to be delayed and dropped.
+        preplayOneVideoFrame(fileName);
+
+        MediaExtractor videoExtractor = createMediaExtractor(fileName);
+        int videoTrackIndex = getFirstVideoTrack(videoExtractor);
+        videoExtractor.selectTrack(videoTrackIndex);
+        MediaFormat videoFormat = videoExtractor.getTrackFormat(videoTrackIndex);
+        MediaCodec videoCodec = createCodecFor(videoFormat);
+        assumeFalse("No video codec found for " + fileName, videoCodec == null);
+        videoCodec.configure(videoFormat, getActivity().getSurfaceHolder().getSurface(), null, 0);
+
+        VideoDecoderCallback videoDecoderCallback = new VideoDecoderCallback(videoExtractor);
+        videoCodec.setCallback(videoDecoderCallback);
+
+        final MutableData data = new MutableData();
+        videoDecoderCallback.setOnInputBufferAvailable(
+                (index, sampleSize, presentationTimeUs, flags) -> {
+                    if (sampleSize == -1) {
+                        flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                        sampleSize = 0;
+                    }
+                    videoCodec.queueInputBuffer(index, 0, sampleSize, presentationTimeUs, flags);
+                });
+
+        final Object done = new Object();
+        final List<Long> releasedFrames = new LinkedList<Long>();
+        videoDecoderCallback.setOnOutputBufferAvailable(
+                (index, info) -> {
+                    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                        synchronized (done) {
+                            done.notify();
+                        }
+                        return;
+                    }
+                    if (data.renderTimeNs == 0) {
+                        // the first frame should be rendered within 200 milliseconds, if it isn't,
+                        // it will appear in the frame-dropped list
+                        data.renderTimeNs = System.nanoTime() + 200 * 1000 * 1000;
+                    } else {
+                        // frames should be rendered based on the presentation time delta
+                        data.renderTimeNs +=
+                                (info.presentationTimeUs - data.previousPresentationTimeUs) * 1000L;
+                        // well-formed streams have monotonically-increasing presentation times
+                        assertTrue(info.presentationTimeUs > data.previousPresentationTimeUs);
+                    }
+                    Log.d(TAG, "releasing frame " + releasedFrames.size());
+                    videoCodec.releaseOutputBuffer(index, data.renderTimeNs);
+                    data.previousPresentationTimeUs = info.presentationTimeUs;
+                    releasedFrames.add(info.presentationTimeUs);
+                });
+
+        final List<Long> renderedFrames = new LinkedList<Long>();
+        videoCodec.setOnFrameRenderedListener(
+                (codec, presentationTimeUs, nanoTime) -> {
+                    renderedFrames.add(presentationTimeUs);
+                }, null);
+
+        videoCodec.start();
+        synchronized (done) {
+            done.wait();
+        }
+
+        // sleep until 200ms after the last frame's render time to verify we get a somewhat-timely
+        // onFrameRendered callback
+        long sleepUntilMs = 200 + (data.renderTimeNs - System.nanoTime()) / 1000 / 1000;
+        if (sleepUntilMs > 0) {
+            Thread.sleep(sleepUntilMs);
+        }
+        videoCodec.flush();
+        videoCodec.stop();
+        videoCodec.release();
+
+        // Compare the presentation timestamps of the released frames with the rendered frames to
+        // detect which frame numbers were skipped
+        List<Integer> skippedFrames = new LinkedList<Integer>();
+        int renderedFrameIndex = 0;
+        int releasedFrameIndex = 0;
+        for (; releasedFrameIndex < releasedFrames.size(); ++releasedFrameIndex) {
+            // we have no more rendered frames, so the last few frames must have been dropped
+            if (renderedFrameIndex >= renderedFrames.size()) {
+                skippedFrames.add(releasedFrameIndex);
+                continue;
+            }
+            long releasedTime = releasedFrames.get(releasedFrameIndex);
+            long renderedTime = renderedFrames.get(renderedFrameIndex);
+            if (releasedTime < renderedTime) {
+                // we have one or more missing rendered frames in the beginning or the middle
+                skippedFrames.add(releasedFrameIndex);
+            } else if (releasedTime == renderedTime) {
+                // the next released frame should match the next rendered frame
+                renderedFrameIndex++;
+            }
+        }
+        // add the total number of frames to the skipped frame list and the expected list, to
+        // indicate to the test operator how many total frames we had, so they know where in the
+        // sequence frames were dropped
+        skippedFrames.add(releasedFrames.size());
+        assertEquals(List.of(releasedFrames.size()), skippedFrames);
+    }
+
+    private void preplayOneVideoFrame(String fileName) throws Exception {
+        MediaExtractor videoExtractor = createMediaExtractor(fileName);
+        int videoTrackIndex = getFirstVideoTrack(videoExtractor);
+        videoExtractor.selectTrack(videoTrackIndex);
+        MediaFormat videoFormat = videoExtractor.getTrackFormat(videoTrackIndex);
+        MediaCodec videoCodec = createCodecFor(videoFormat);
+        assumeFalse("No video codec found for " + fileName, videoCodec == null);
+        videoCodec.configure(videoFormat, getActivity().getSurfaceHolder().getSurface(), null, 0);
+        videoCodec.start();
+        int inputBufferId = videoCodec.dequeueInputBuffer(-1);
+        ByteBuffer inputBuffer = videoCodec.getInputBuffer(inputBufferId);
+        int sampleSize = videoExtractor.readSampleData(inputBuffer, 0);
+        long presentationTime = videoExtractor.getSampleTime();
+        int flags = videoExtractor.getSampleFlags();
+        videoCodec.queueInputBuffer(inputBufferId, 0, sampleSize, presentationTime, flags);
+        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+        int outputBufferId;
+        do {
+            outputBufferId = videoCodec.dequeueOutputBuffer(bufferInfo, -1);
+        } while (outputBufferId == MediaCodec.INFO_TRY_AGAIN_LATER
+                 || outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED
+                 || outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED);
+        videoCodec.releaseOutputBuffer(outputBufferId, true);
+        videoCodec.stop();
+        videoCodec.release();
+        videoExtractor.release();
+    }
+}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderSetup.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderSetup.java
new file mode 100644
index 0000000..fabf235
--- /dev/null
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderSetup.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 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.media.decoder.cts;
+
+import static org.junit.Assert.assertTrue;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+
+import com.android.compatibility.common.util.Preconditions;
+
+import java.io.IOException;
+
+public class DecoderSetup {
+    private static final String MIME_VIDEO_PREFIX = "video/";
+    private static final String MIME_AUDIO_PREFIX = "audio/";
+
+    public static MediaExtractor createMediaExtractor(String fileName) throws IOException {
+        String filePath = WorkDir.getMediaDirString() + fileName;
+        Preconditions.assertTestFileExists(filePath);
+        MediaExtractor mediaExtractor = new MediaExtractor();
+        mediaExtractor.setDataSource(filePath);
+        return mediaExtractor;
+    }
+
+    public static int getFirstVideoTrack(MediaExtractor extractor) {
+        return getFirstTrackWithMimePrefix(MIME_VIDEO_PREFIX, extractor);
+    }
+
+    public static int getFirstAudioTrack(MediaExtractor extractor) {
+        return getFirstTrackWithMimePrefix(MIME_AUDIO_PREFIX, extractor);
+    }
+
+    private static int getFirstTrackWithMimePrefix(String prefix, MediaExtractor extractor) {
+        int trackIndex = -1;
+        for (int i = 0; i < extractor.getTrackCount(); ++i) {
+            MediaFormat format = extractor.getTrackFormat(i);
+            if (format.getString(MediaFormat.KEY_MIME).startsWith(prefix)) {
+                trackIndex = i;
+                break;
+            }
+        }
+        assertTrue("Track matching mime '" + prefix + "' not found.", trackIndex >= 0);
+        return trackIndex;
+    }
+
+    public static MediaCodec createCodecFor(MediaFormat format) {
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
+        String codecName = mcl.findDecoderForFormat(format);
+        if (codecName == null) {
+            return null;
+        }
+        // TODO(b/234833109): Implement accurate onFrameRendered callbacks for OMX.
+        if (codecName.contains("OMX")) {
+            return null;
+        }
+        try {
+            return MediaCodec.createByCodecName(codecName);
+        } catch (IOException ex) {
+            return null;
+        }
+    }
+}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/HDRDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/HDRDecoderTest.java
index eec66e6..2ba07a3 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/HDRDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/HDRDecoderTest.java
@@ -203,7 +203,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 {MediaFormat.MIMETYPE_VIDEO_AV1, AV1_HDR_RES, AV1_HDR_STATIC_INFO, null, false},
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
index 9750f30..e953def 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
@@ -125,7 +125,7 @@
         mTestId = testId;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         final List<Object[]> argsList = new ArrayList<>();
         for (MediaAssets assets : ASSETS) {
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderCallback.java b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderCallback.java
new file mode 100644
index 0000000..1be9849
--- /dev/null
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderCallback.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2023 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.media.decoder.cts;
+
+import static org.junit.Assert.fail;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+
+import java.nio.ByteBuffer;
+
+class VideoDecoderCallback extends MediaCodec.Callback {
+    public interface OnInputBufferAvailable {
+        void onInputBufferAvailable(int index, int sampleSize, long presentationTime,
+                                    int flags);
+    }
+
+    public interface OnOutputBufferAvailable {
+        void onOutputBufferAvailable(int index, MediaCodec.BufferInfo info);
+    }
+
+    VideoDecoderCallback(MediaExtractor videoExtractor) {
+        mVideoExtractor = videoExtractor;
+        mOnInputBufferAvailable = null;
+        mOnOutputBufferAvailable = null;
+    }
+
+    public void setOnInputBufferAvailable(OnInputBufferAvailable onInputBufferAvailable) {
+        mOnInputBufferAvailable = onInputBufferAvailable;
+    }
+
+    public void setOnOutputBufferAvailable(OnOutputBufferAvailable onOutputBufferAvailable) {
+        mOnOutputBufferAvailable = onOutputBufferAvailable;
+    }
+
+    @Override
+    public void onInputBufferAvailable(MediaCodec codec, int index) {
+        ByteBuffer inputBuffer = codec.getInputBuffer(index);
+        int sampleSize = mVideoExtractor.readSampleData(inputBuffer, 0);
+        long presentationTime = mVideoExtractor.getSampleTime();
+        int flags = mVideoExtractor.getSampleFlags();
+        if (mOnInputBufferAvailable == null) {
+            codec.queueInputBuffer(index, 0, sampleSize, presentationTime, flags);
+        } else {
+            mOnInputBufferAvailable.onInputBufferAvailable(index, sampleSize, presentationTime,
+                                                           flags);
+        }
+        mVideoExtractor.advance();
+    }
+
+    @Override
+    public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
+        if (mOnOutputBufferAvailable == null) {
+            codec.releaseOutputBuffer(index, false);
+        } else {
+            mOnOutputBufferAvailable.onOutputBufferAvailable(index, info);
+        }
+    }
+
+    @Override
+    public void onError(MediaCodec codec, MediaCodec.CodecException e) {
+        fail("Encountered unexpected error while decoding video: " + e.getMessage());
+    }
+
+    @Override
+    public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
+        // do nothing
+    }
+
+    private final MediaExtractor mVideoExtractor;
+    private OnInputBufferAvailable mOnInputBufferAvailable;
+    private OnOutputBufferAvailable mOnOutputBufferAvailable;
+}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
index e15a02b..a0dc4d5 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo.VideoCapabilities;
@@ -78,6 +79,7 @@
     private static final String MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
     private static final String VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
     private static final String VP9 = MediaFormat.MIMETYPE_VIDEO_VP9;
+    private static final String AV1 = MediaFormat.MIMETYPE_VIDEO_AV1;
 
     private static final boolean GOOG = true;
     private static final boolean OTHER = false;
@@ -121,7 +123,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}:{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{3}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // MediaType, resources, graphics display resolution
@@ -154,6 +156,12 @@
                 {VP9, sVp9Media1280x0720, "hd"},
                 {VP9, sVp9Media1920x1080, "fullhd"},
                 {VP9, sVp9Media3840x2160, "uhd"},
+
+                {AV1, sAv1Media0352x0288, "cif"},
+                {AV1, sAv1Media0640x0360, "vga"},
+                {AV1, sAv1Media0720x0480, "sd"},
+                {AV1, sAv1Media1280x0720, "hd"},
+                {AV1, sAv1Media1920x1080, "fullhd"},
         });
         return prepareParamList(exhaustiveArgsList);
     }
@@ -215,8 +223,12 @@
                            fasterIsOk,  measuredFps);
         // Performance numbers only make sense on real devices, so skip on non-real devices
         if ((MediaUtils.onFrankenDevice() || mSkipRateChecking) && error != null) {
-            // ensure there is data, but don't insist that it is correct
-            assertFalse(error, error.startsWith("Failed to get "));
+            if (TestUtils.isMtsMode() && TestUtils.isMainlineCodec(name)) {
+                assumeFalse(error, error.startsWith("Failed to get "));
+            } else {
+                // ensure there is data, but don't insist that it is correct
+                assertFalse(error, error.startsWith("Failed to get "));
+            }
         } else {
             assertNull(error, error);
         }
@@ -557,6 +569,28 @@
         "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm",
     };
 
+    // AV1 tests
+
+    private static final String[] sAv1Media0352x0288 = {
+        "bbb_s1_352x288_mp4_av1_355kbps_30fps_aac_lc_stereo_128kbps_48000hz.mp4",
+    };
+
+    private static final String[] sAv1Media0640x0360 = {
+        "bbb_s1_640x360_mp4_av1_994kbps_30fps_aac_lc_6ch_342kbps_48000hz.mp4",
+    };
+
+    private static final String[] sAv1Media0720x0480 = {
+        "bbb_s1_720x480_mp4_av1_977kbps_30fps_aac_lc_6ch_341kbps_48000hz.mp4",
+    };
+
+    private static final String[] sAv1Media1280x0720 = {
+        "bbb_s4_1280x720_mp4_av1_2387kbps_30fps_aac_lc_stereo_130kbps_32000hz.mp4",
+    };
+
+    private static final String[] sAv1Media1920x1080 = {
+        "bbb_s2_1920x1080_mp4_av1_5010kbps_60fps_aac_lc_6ch_348kbps_22050hz.mp4",
+    };
+
     @Test
     public void testPerf() throws Exception {
         perf(mDecoderName, mResources);
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/WorkDir.java b/tests/tests/media/decoder/src/android/media/decoder/cts/WorkDir.java
index 3f0a330..e322930 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/WorkDir.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/WorkDir.java
@@ -20,6 +20,6 @@
 
 class WorkDir extends WorkDirBase {
     public static final String getMediaDirString() {
-        return getMediaDirString("CtsMediaDecoderTestCases-1.1");
+        return getMediaDirString("CtsMediaDecoderTestCases-2.0");
     }
 }
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
index e2bd2ae..6f9421d 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
@@ -156,7 +156,7 @@
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{4}_{5})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}_{3}_{4}_{5}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // Audio - CodecMime, arrays of profiles, bit-rates, sample rates, channel counts
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
index f43989e..93f858e 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
@@ -42,7 +42,7 @@
     final private int mBitRate;
     final private boolean mOptional;
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}x{2}_{3}_{4}_{5})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}x{2}_{3}_{4}_{5}")
     public static Collection<Object[]> input() {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // MediaType, width, height, frame-rate, bit-rate, optional
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
index d25b5fa..de642ed 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
@@ -1269,7 +1269,7 @@
         return encoder;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{2}x{3}_{4}_{5})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{2}x{3}_{4}_{5}")
     public static Collection<Object[]> input() {
         final String[] mediaTypesList = new String[] {
                 MediaFormat.MIMETYPE_VIDEO_AVC,
diff --git a/tests/tests/media/extractor/AndroidTest.xml b/tests/tests/media/extractor/AndroidTest.xml
index 402b834..c6e1d9f 100644
--- a/tests/tests/media/extractor/AndroidTest.xml
+++ b/tests/tests/media/extractor/AndroidTest.xml
@@ -40,7 +40,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaExtractorTestCases-2.0" />
+        <option name="media-folder-name" value="CtsMediaExtractorTestCases-2.1" />
         <option name="dynamic-config-module" value="CtsMediaExtractorTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/extractor/DynamicConfig.xml b/tests/tests/media/extractor/DynamicConfig.xml
index 6d2de63..203e6b7 100644
--- a/tests/tests/media/extractor/DynamicConfig.xml
+++ b/tests/tests/media/extractor/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-    <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/extractor/CtsMediaExtractorTestCases-2.0.zip</value>
+    <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/extractor/CtsMediaExtractorTestCases-2.1.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/tests/media/extractor/copy_media.sh b/tests/tests/media/extractor/copy_media.sh
index 3978ee1..8b83bdf 100755
--- a/tests/tests/media/extractor/copy_media.sh
+++ b/tests/tests/media/extractor/copy_media.sh
@@ -17,4 +17,4 @@
 [ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
 source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
 get_adb_options "$@"
-copy_media "extractor" "CtsMediaExtractorTestCases-2.0"
+copy_media "extractor" "CtsMediaExtractorTestCases-2.1"
diff --git a/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java b/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
index 27f76c9..0a425c6 100644
--- a/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
+++ b/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
@@ -16,6 +16,13 @@
 
 package android.media.extractor.cts;
 
+import static android.media.MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.hardware.display.DisplayManager;
@@ -27,15 +34,8 @@
 import android.media.MediaDataSource;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
-import android.media.cts.TestMediaDataSource;
 import android.media.cts.StreamUtils;
-import static android.media.MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
+import android.media.cts.TestMediaDataSource;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
@@ -50,25 +50,20 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.Preconditions;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.BufferedReader;
 import java.io.Closeable;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StreamTokenizer;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -82,7 +77,9 @@
 public class MediaExtractorTest {
     private static final String TAG = "MediaExtractorTest";
     private static final boolean IS_AT_LEAST_S = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
-
+    //TODO(b/248315681) Remove codenameEquals() check once devices return correct version for U
+    public static final boolean IS_AT_LEAST_U = ApiLevelUtil.isAfter(Build.VERSION_CODES.TIRAMISU)
+            || ApiLevelUtil.codenameEquals("UpsideDownCake");
     static final String mInpPrefix = WorkDir.getMediaDirString();
     protected MediaExtractor mExtractor;
 
@@ -500,41 +497,43 @@
         // advances the reference set index, matches set 1 until it encounters set 2 etc.
         // At the end it verifies that all the reference sets were met.
         List<Map<Integer, AudioPresentation>> refPresentations = Arrays.asList(
-                Map.of(  // First set.
-                    10, new AudioPresentation.Builder(10)
+                new HashMap<Integer, AudioPresentation>() {{  // First set.
+                    put(10, new AudioPresentation.Builder(10)
                             .setLocale(ULocale.ENGLISH)
                             .setMasteringIndication(AudioPresentation.MASTERED_FOR_SURROUND)
                             .setHasDialogueEnhancement(true)
-                            .build(),
-                    11, new AudioPresentation.Builder(11)
+                            .build());
+                    put(11, new AudioPresentation.Builder(11)
                             .setLocale(ULocale.ENGLISH)
                             .setMasteringIndication(AudioPresentation.MASTERED_FOR_SURROUND)
                             .setHasAudioDescription(true)
                             .setHasDialogueEnhancement(true)
-                            .build(),
-                    12, new AudioPresentation.Builder(12)
+                            .build());
+                    put(12, new AudioPresentation.Builder(12)
                             .setLocale(ULocale.FRENCH)
                             .setMasteringIndication(AudioPresentation.MASTERED_FOR_SURROUND)
                             .setHasDialogueEnhancement(true)
-                            .build()),
-                Map.of(  // Second set.
-                    10, new AudioPresentation.Builder(10)
+                            .build());
+                }},
+                new HashMap<Integer, AudioPresentation>() {{  // Second set.
+                    put(10, new AudioPresentation.Builder(10)
                             .setLocale(ULocale.GERMAN)
                             .setMasteringIndication(AudioPresentation.MASTERED_FOR_SURROUND)
                             .setHasAudioDescription(true)
                             .setHasDialogueEnhancement(true)
-                            .build(),
-                    11, new AudioPresentation.Builder(11)
+                            .build());
+                    put(11, new AudioPresentation.Builder(11)
                             .setLocale(new ULocale("es"))
                             .setMasteringIndication(AudioPresentation.MASTERED_FOR_SURROUND)
                             .setHasSpokenSubtitles(true)
                             .setHasDialogueEnhancement(true)
-                            .build(),
-                    12, new AudioPresentation.Builder(12)
+                            .build());
+                    put(12, new AudioPresentation.Builder(12)
                             .setLocale(ULocale.ENGLISH)
                             .setMasteringIndication(AudioPresentation.MASTERED_FOR_SURROUND)
                             .setHasDialogueEnhancement(true)
-                            .build()),
+                            .build());
+                }},
                 null,
                 null
         );
@@ -858,6 +857,55 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.media.MediaFormat#MIMETYPE_AUDIO_DTS"})
+    public void testDtsInMpeg2ts() throws Exception {
+        setDataSource("sample_dts.ts");
+        assertEquals(1, mExtractor.getTrackCount());
+
+        // The following values below require API Build.VERSION_CODES.U
+        if (IS_AT_LEAST_U) {
+            MediaFormat trackFormat = mExtractor.getTrackFormat(0);
+            final String mediaType = trackFormat.getString(MediaFormat.KEY_MIME);
+            assertEquals(MediaFormat.MIMETYPE_AUDIO_DTS, mediaType);
+        }
+        readAllData();
+    }
+
+    @Test
+    @ApiTest(apis = {"android.media.MediaFormat#MIMETYPE_AUDIO_DTS_HD"})
+    public void testDtsHdInMpeg2ts() throws Exception {
+        setDataSource("sample_dts_hd.ts");
+        assertEquals(1, mExtractor.getTrackCount());
+
+        // The following values below require API Build.VERSION_CODES.U
+        if (IS_AT_LEAST_U) {
+            MediaFormat trackFormat = mExtractor.getTrackFormat(0);
+            final String mediaType = trackFormat.getString(MediaFormat.KEY_MIME);
+            assertEquals(MediaFormat.MIMETYPE_AUDIO_DTS_HD, mediaType);
+            int mediaProfile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);
+            assertEquals(MediaCodecInfo.CodecProfileLevel.DTS_HDProfileLBR, mediaProfile);
+        }
+        readAllData();
+    }
+
+    @Test
+    @ApiTest(apis = {"android.media.MediaFormat#MIMETYPE_AUDIO_DTS_UHD"})
+    public void testDtsUhdInMpeg2ts() throws Exception {
+        setDataSource("sample_dts_uhd.ts");
+        assertEquals(1, mExtractor.getTrackCount());
+
+        // The following values below require API Build.VERSION_CODES.U
+        if (IS_AT_LEAST_U) {
+            MediaFormat trackFormat = mExtractor.getTrackFormat(0);
+            final String mediaType = trackFormat.getString(MediaFormat.KEY_MIME);
+            assertEquals(MediaFormat.MIMETYPE_AUDIO_DTS_UHD, mediaType);
+            int mediaProfile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);
+            assertEquals(MediaCodecInfo.CodecProfileLevel.DTS_UHDProfileP2, mediaProfile);
+        }
+        readAllData();
+    }
+
+    @Test
     public void testAV1InMP4() throws Exception {
         setDataSource("video_dovi_3840x2160_30fps_dav1_10_2.mp4");
         readAllData();
diff --git a/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java b/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
index 619c63b..8b847e2 100644
--- a/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
+++ b/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
@@ -20,6 +20,6 @@
 
 class WorkDir extends WorkDirBase {
     public static final String getMediaDirString() {
-        return getMediaDirString("CtsMediaExtractorTestCases-2.0");
+        return getMediaDirString("CtsMediaExtractorTestCases-2.1");
     }
 }
diff --git a/tests/tests/media/misc/Android.bp b/tests/tests/media/misc/Android.bp
index feaabe4..87208db 100644
--- a/tests/tests/media/misc/Android.bp
+++ b/tests/tests/media/misc/Android.bp
@@ -66,6 +66,7 @@
         "junit-params",
         "testng",
         "truth-prebuilt",
+        "Harrier",
         "mockito-target-minus-junit4",
         "androidx.heifwriter_heifwriter",
         "CtsCameraUtils",
diff --git a/tests/tests/media/misc/AndroidTest.xml b/tests/tests/media/misc/AndroidTest.xml
index 33d07ef..2add92a 100644
--- a/tests/tests/media/misc/AndroidTest.xml
+++ b/tests/tests/media/misc/AndroidTest.xml
@@ -19,6 +19,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <option name="config-descriptor:metadata" key="parameter" value="multiuser" />
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
         <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
         <option name="set-test-harness" value="false" />
@@ -57,5 +58,6 @@
         <option name="hidden-api-checks" value="false" />
         <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
         <option name="isolated-storage" value="false" />
+        <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
     </test>
 </configuration>
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
index 89d336c..aae07c7 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
@@ -56,12 +56,17 @@
 import android.text.TextUtils;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.UserType;
+import com.android.bedstead.harrier.annotations.UserTest;
 import com.android.compatibility.common.util.PollingCheck;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -75,12 +80,16 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(BedsteadJUnit4.class)
 @AppModeFull(reason = "The system should be able to bind to StubMediaRoute2ProviderService")
 @LargeTest
 @NonMediaMainlineTest
 public class MediaRouter2Test {
     private static final String TAG = "MR2Test";
+
+    // Required by Bedstead.
+    @ClassRule @Rule public static final DeviceState sDeviceState = new DeviceState();
+
     Context mContext;
     private MediaRouter2 mRouter2;
     private Executor mExecutor;
@@ -158,8 +167,11 @@
     }
 
     /**
-     * Tests if we get proper routes for application that has special route type.
+     * Tests if we get proper routes for an application that requests a special route type.
+     *
+     * <p>Runs on both the primary user and a work profile, as per {@link UserTest}.
      */
+    @UserTest({UserType.PRIMARY_USER, UserType.WORK_PROFILE})
     @Test
     public void testGetRoutes() throws Exception {
         Map<String, MediaRoute2Info> routes = waitAndGetRoutes(FEATURES_SPECIAL);
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java
index 1503cd1..109bcbe 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
+
 import junit.framework.Assert;
 
 public class ResourceManagerStubActivity extends Activity {
@@ -66,7 +67,8 @@
         }
     }
 
-    public void testReclaimResource(int type1, int type2) throws InterruptedException {
+    public void testReclaimResource(int type1, int type2, boolean highResolution)
+            throws InterruptedException {
         mType1 = type1;
         mType2 = type2;
         if (type1 != ResourceManagerTestActivityBase.TYPE_MIX && type1 != type2) {
@@ -83,11 +85,13 @@
                     Intent intent1 = new Intent(context, ResourceManagerTestActivity1.class);
                     intent1.putExtra("test-type", mType1);
                     intent1.putExtra("wait-for-reclaim", mWaitForReclaim);
+                    intent1.putExtra("high-resolution", highResolution);
                     startActivityForResult(intent1, mRequestCodes[0]);
                     Thread.sleep(5000);  // wait for process to launch and allocate all codecs.
 
                     Intent intent2 = new Intent(context, ResourceManagerTestActivity2.class);
                     intent2.putExtra("test-type", mType2);
+                    intent2.putExtra("high-resolution", highResolution);
                     startActivityForResult(intent2, mRequestCodes[1]);
 
                     synchronized (mFinishEvent) {
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
index 5a9575f..1776e10 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
@@ -33,41 +33,71 @@
         super("android.media.misc.cts", ResourceManagerStubActivity.class);
     }
 
-    private void doTestReclaimResource(int type1, int type2) throws Exception {
+    private void doTestReclaimResource(int type1, int type2, boolean highResolution)
+            throws Exception {
         Bundle extras = new Bundle();
         ResourceManagerStubActivity activity = launchActivity(
                 "android.media.misc.cts", ResourceManagerStubActivity.class, extras);
-        activity.testReclaimResource(type1, type2);
+        activity.testReclaimResource(type1, type2, highResolution);
         activity.finish();
     }
 
     public void testReclaimResourceNonsecureVsNonsecure() throws Exception {
         doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_NONSECURE,
-                ResourceManagerTestActivityBase.TYPE_NONSECURE);
+                ResourceManagerTestActivityBase.TYPE_NONSECURE, false);
     }
 
     public void testReclaimResourceNonsecureVsSecure() throws Exception {
         doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_NONSECURE,
-                ResourceManagerTestActivityBase.TYPE_SECURE);
+                ResourceManagerTestActivityBase.TYPE_SECURE, false);
     }
 
     public void testReclaimResourceSecureVsNonsecure() throws Exception {
         doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_SECURE,
-                ResourceManagerTestActivityBase.TYPE_NONSECURE);
+                ResourceManagerTestActivityBase.TYPE_NONSECURE, false);
     }
 
     public void testReclaimResourceSecureVsSecure() throws Exception {
         doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_SECURE,
-                ResourceManagerTestActivityBase.TYPE_SECURE);
+                ResourceManagerTestActivityBase.TYPE_SECURE, false);
     }
 
     public void testReclaimResourceMixVsNonsecure() throws Exception {
         doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_MIX,
-                ResourceManagerTestActivityBase.TYPE_NONSECURE);
+                ResourceManagerTestActivityBase.TYPE_NONSECURE, false);
     }
 
     public void testReclaimResourceMixVsSecure() throws Exception {
         doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_MIX,
-                ResourceManagerTestActivityBase.TYPE_SECURE);
+                ResourceManagerTestActivityBase.TYPE_SECURE, false);
+    }
+
+    public void testReclaimResourceNonsecureVsNonsecureHighResolution() throws Exception {
+        doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_NONSECURE,
+                ResourceManagerTestActivityBase.TYPE_NONSECURE, true);
+    }
+
+    public void testReclaimResourceNonsecureVsSecureHighResolution() throws Exception {
+        doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_NONSECURE,
+                ResourceManagerTestActivityBase.TYPE_SECURE, true);
+    }
+
+    public void testReclaimResourceSecureVsNonsecureHighResolution() throws Exception {
+        doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_SECURE,
+                ResourceManagerTestActivityBase.TYPE_NONSECURE, true);
+    }
+
+    public void testReclaimResourceSecureVsSecureHighResolution() throws Exception {
+        doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_SECURE,
+                ResourceManagerTestActivityBase.TYPE_SECURE, true);
+    }
+
+    public void testReclaimResourceMixVsNonsecureHighResolution() throws Exception {
+        doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_MIX,
+                ResourceManagerTestActivityBase.TYPE_NONSECURE, true);
+    }
+    public void testReclaimResourceMixVsSecureHighResolution() throws Exception {
+        doTestReclaimResource(ResourceManagerTestActivityBase.TYPE_MIX,
+                ResourceManagerTestActivityBase.TYPE_SECURE, true);
     }
 }
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
index 664fba4..733ae0f 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
@@ -25,6 +25,7 @@
 import android.media.MediaFormat;
 import android.os.Bundle;
 import android.util.Log;
+
 import java.io.IOException;
 import java.util.Vector;
 
@@ -65,11 +66,22 @@
 
     private MediaCodec.Callback mCallback = new TestCodecCallback();
 
-    private MediaFormat getTestFormat(CodecCapabilities caps, boolean securePlayback) {
+    private MediaFormat getTestFormat(CodecCapabilities caps, boolean securePlayback,
+            boolean highResolution) {
         VideoCapabilities vcaps = caps.getVideoCapabilities();
-        int width = vcaps.getSupportedWidths().getLower();
-        int height = vcaps.getSupportedHeightsFor(width).getLower();
-        int bitrate = vcaps.getBitrateRange().getLower();
+        int width = 0;
+        int height = 0;
+        int bitrate = 0;
+
+        if (highResolution) {
+            width = vcaps.getSupportedWidths().getUpper();
+            height = vcaps.getSupportedHeightsFor(width).getUpper();
+            bitrate = vcaps.getBitrateRange().getUpper();
+        } else {
+            width = vcaps.getSupportedWidths().getLower();
+            height = vcaps.getSupportedHeightsFor(width).getLower();
+            bitrate = vcaps.getBitrateRange().getLower();
+        }
 
         MediaFormat format = MediaFormat.createVideoFormat(MIME, width, height);
         format.setInteger(MediaFormat.KEY_COLOR_FORMAT, caps.colorFormats[0]);
@@ -116,9 +128,11 @@
     protected int allocateCodecs(int max) {
         Bundle extras = getIntent().getExtras();
         int type = TYPE_NONSECURE;
+        boolean highResolution = false;
         if (extras != null) {
             type = extras.getInt("test-type", type);
-            Log.d(TAG, "type is: " + type);
+            highResolution = extras.getBoolean("high-resolution", highResolution);
+            Log.d(TAG, "type is: " + type + " high-resolution: " + highResolution);
         }
 
         boolean shouldSkip = false;
@@ -127,7 +141,7 @@
             securePlayback = false;
             MediaCodecInfo info = getTestCodecInfo(securePlayback);
             if (info != null) {
-                allocateCodecs(max, info, securePlayback);
+                allocateCodecs(max, info, securePlayback, highResolution);
             } else {
                 shouldSkip = true;
             }
@@ -138,7 +152,7 @@
                 securePlayback = true;
                 MediaCodecInfo info = getTestCodecInfo(securePlayback);
                 if (info != null) {
-                    allocateCodecs(max, info, securePlayback);
+                    allocateCodecs(max, info, securePlayback, highResolution);
                 } else {
                     shouldSkip = true;
                 }
@@ -154,10 +168,11 @@
         return mCodecs.size();
     }
 
-    protected void allocateCodecs(int max, MediaCodecInfo info, boolean securePlayback) {
+    protected void allocateCodecs(int max, MediaCodecInfo info, boolean securePlayback,
+            boolean highResolution) {
         String name = info.getName();
         CodecCapabilities caps = info.getCapabilitiesForType(MIME);
-        MediaFormat format = getTestFormat(caps, securePlayback);
+        MediaFormat format = getTestFormat(caps, securePlayback, highResolution);
         MediaCodec codec = null;
         for (int i = mCodecs.size(); i < max; ++i) {
             try {
diff --git a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
index 488f4d3..dae2257 100644
--- a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
+++ b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
@@ -115,6 +115,8 @@
     private static final int  RECORDED_VIDEO_HEIGHT = 144;
     private static final long RECORDED_DURATION_MS  = 3000;
     private static final float FLOAT_TOLERANCE = .0001f;
+    private static final int PLAYBACK_DURATION_MS  = 10000;
+    private static final int ANR_DETECTION_TIME_MS  = 20000;
 
     private final Vector<Integer> mTimedTextTrackIndex = new Vector<>();
     private final Monitor mOnTimedTextCalled = new Monitor();
@@ -713,9 +715,9 @@
             player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
             player.prepare();
             // Test needs the mediaplayer to playback at least about 5 seconds of content.
-            // Clip used here has a duration of 61 seconds, so seek to 50 seconds in the media file.
+            // Clip used here has a duration of 61 seconds, given PLAYBACK_DURATION_MS for play.
             // This leaves enough remaining time, with gapless enabled or disabled,
-            player.seekTo(50000);
+            player.seekTo(player.getDuration() - PLAYBACK_DURATION_MS);
         }
     }
 
@@ -757,6 +759,10 @@
 
     @Test
     public void testSetNextMediaPlayer() throws Exception {
+        final int ITERATIONS = 3;
+        // the +1 is for the trailing test of setNextMediaPlayer(null)
+        final int TOTAL_TIMEOUT_MS = PLAYBACK_DURATION_MS * (ITERATIONS + 1)
+                        + ANR_DETECTION_TIME_MS + 5000 /* listener latency(ms) */;
         initMediaPlayer(mMediaPlayer);
 
         final Monitor mTestCompleted = new Monitor();
@@ -770,9 +776,9 @@
                     return;
                 }
                 long now = SystemClock.elapsedRealtime();
-                if ((now - startTime) > 45000) {
-                    // We've been running for 45 seconds and still aren't done, so we're stuck
-                    // somewhere. Signal ourselves to dump the thread stacks.
+                if ((now - startTime) > TOTAL_TIMEOUT_MS) {
+                    // We've been running beyond TOTAL_TIMEOUT and still aren't done,
+                    // so we're stuck somewhere. Signal ourselves to dump the thread stacks.
                     android.os.Process.sendSignal(android.os.Process.myPid(), 3);
                     SystemClock.sleep(2000);
                     fail("Test is stuck, see ANR stack trace for more info. You may need to" +
@@ -785,7 +791,7 @@
         timer.start();
 
         try {
-            for (int i = 0; i < 3; i++) {
+            for (int i = 0; i < ITERATIONS; i++) {
 
                 initMediaPlayer(mMediaPlayer2);
                 mOnCompletionCalled.reset();
@@ -825,6 +831,7 @@
             }
 
             // Now test that setNextMediaPlayer(null) works. 1 is still playing, 2 is done
+            // this is the final "+1" in our time calculations above
             mOnCompletionCalled.reset();
             mOnInfoCalled.reset();
             initMediaPlayer(mMediaPlayer2);
diff --git a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
index 5485cb6..61b559e 100644
--- a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
+++ b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
@@ -1046,8 +1046,8 @@
             MediaUtils.skipTest("no microphone, camera, or codecs");
             return;
         }
-        long fileSize = 128 * 1024;
-        long tolerance = 50 * 1024;
+        long fileSize = 1028 * 1024;
+        long tolerance = 400 * 1024;
         int width;
         int height;
         List<String> recordFileList = new ArrayList<String>();
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/invalid_chain.pem b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/invalid_chain.pem
index ed33e7f..1a1b2d7 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/invalid_chain.pem
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/invalid_chain.pem
@@ -1,35 +1,36 @@
 -----BEGIN CERTIFICATE-----
-MIICvjCCAaagAwIBAgIDDUD7MA0GCSqGSIb3DQEBCwUAMCMxITAfBgNVBAMTGEFu
-ZHJvaWQgQ1RTIHVudHJ1c3RlZCBDQTAqGBMyMDE1MDEwMTAwMDAwMCswMDAwGBMy
-MDI1MDEwMTAwMDAwMCswMDAwMBQxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH+IdnzoDeGaE1SWn4L8dhfd59AJVYO
-Wxz88ntK55iPCxPGdNdqL5MX0On9K0iBf+e839mRMIdjY1BtEo5Ln9MA6RTLQwt6
-OPaWF/HQQHkmrLOOShNZcerea+rJHPfN7NedSg6Ufb2bcVn7DrKBwUigAJDWVn02
-IB6wHO9slF+NsAcpyecxtvY/p7t0lguAe0j1IiVfX+xGdNFU7WjmGRQzk5KavFi3
-BwDc25rXP7JJ/6M66TnzI54iRI918P0AbhE+3K/5Bbe8qPFtdlEOChP6npUW1Nhm
-z99KolkcW/uCXUBHAsm27QPdW3wYX6hwa5eS8VGTWuhEOddPdBvGGPcCAwEAATAN
-BgkqhkiG9w0BAQsFAAOCAQEAgABDM5HU2+XE6Hx/Ti8LpnJXLdNk6Y1uZro2Vvmz
-MqwdKBC/k5RrdIyalN5lZzCRWKi4f4wgWGGnqbxlAugwa5N0+LWgw2Em4W8HEk6c
-DK9TPVnh7y87ibwGmyeU+bHMyFuVV8Yp+tXUCV2aQhM/yBEyCOEei/twWeZ7uVaw
-ANraJ0UDDeznqJX3rTsvwwBfKLmFm98YhzB3EYVo332oCuvC90RLmEerI5JmpNAw
-jg6Z0DMShcfdN2kIW1NEUTGBbd5sGsPRJVba0giEwXtDKorPLe+kJJMzji8HRk0x
-51tpxEseBrS3DjiIS7CT1RuiBfVJAdfzOHyDeFCX9t7tFQ==
+MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhBbmRy
+b2lkIENUUyB1bnRydXN0ZWQgQ0EwIBcNMTUwMTAxMDAwMDAwWhgPMzAwMDAxMDEw
+MDAwMDBaMBQxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKH+IdnzoDeGaE1SWn4L8dhfd59AJVYOWxz88ntK55iPCxPG
+dNdqL5MX0On9K0iBf+e839mRMIdjY1BtEo5Ln9MA6RTLQwt6OPaWF/HQQHkmrLOO
+ShNZcerea+rJHPfN7NedSg6Ufb2bcVn7DrKBwUigAJDWVn02IB6wHO9slF+NsAcp
+yecxtvY/p7t0lguAe0j1IiVfX+xGdNFU7WjmGRQzk5KavFi3BwDc25rXP7JJ/6M6
+6TnzI54iRI918P0AbhE+3K/5Bbe8qPFtdlEOChP6npUW1Nhmz99KolkcW/uCXUBH
+Asm27QPdW3wYX6hwa5eS8VGTWuhEOddPdBvGGPcCAwEAAaNHMEUwDAYDVR0TAQH/
+BAIwADAfBgNVHSMEGDAWgBShmbz1UJc37NwCMcW49/562dTpczAUBgNVHREEDTAL
+gglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAIusEEDMMg3DStbmm4Xo1w+D
+28SvONHgQI2U7VxzeUM6lzMujsBWJwnX1iXK7bdNqy9Z5JkNoMbtF5B9poygelqY
+6Bk31pWuHzxucHLPENAfnGZZ5PiCjZZGegEcwmIdYFELBMfWbvU9atG9akChv2Fu
+Q/BYtEgPK3mfVBvIQt/b4I3LYjjPADODAmrZFfWuc7HqGMzR8wiHskb0E31+R/Of
+dalL6fbGRQh0j1P1euelZaYfNaegyRP2eNpHhw8my3RctQFZ9ob00KZAsq7bKzwQ
+K5ouEYLke7pQ+6xNs60W1QwF7ezmvusKeZpjZve69fW91Hkanf8odlTCWSXdzWQ=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIC4jCCAcqgAwIBAgIDBxMgMA0GCSqGSIb3DQEBCwUAMCMxITAfBgNVBAMTGEFu
-ZHJvaWQgQ1RTIHVudHJ1c3RlZCBDQTAqGBMyMDE1MDEwMTAwMDAwMCswMDAwGBMy
-MDI1MDEwMTAwMDAwMCswMDAwMCMxITAfBgNVBAMTGEFuZHJvaWQgQ1RTIHVudHJ1
-c3RlZCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMWCkHZZHBs7
-m1njBgF2yh4zEHOO1jN3nl9tNJwXWK6O3qAr4UC/CbokIu4onG26I9kHbaCAcM3L
-7qmuz2cL5gqSrwUD7nVC38+EnP8WpMt/SFljJYlbNqGMep8/ZvybtK8wJm+dAY3w
-Cj4vU9w9XPakG6m0FkSLtS5+XaAIM0rRbWGcPWBv+nHOwXBNpggoe63L2uJ6wra7
-NwW0epXT4FuMzY+f3/ZSdNbhMs4/gJbLHYMt81w7YZ2DY/fgGbZGjLc6PQvV8bZb
-+Wib/Lg0o2rFb9O+pdU0azZQ/kyD/+CBjuEewJCcl6dsQX5k8A71di4uWBHaopVr
-gN2MTL2pqRECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF
-AAOCAQEAORmso2dZmTmaUHQKRnbpDoVcUDeDJWSnkgCbP1ZgpQ+B7t5ZWnLXqpVy
-eyK/ENscNPMpbyyQ8eaeydpSD6jipJfmH3O8NhtWZPA/1oY0Wm4/lsosZGFSadWg
-nSLfqxZtBy+VIZBGZrhPhlJ2U2WKmrTaMYS7TJy1t9RcQIw79pnnLKXAAhZx72U5
-FtPMAGREDaFMt7pVcM63ipytUPtrXH6nzOFHmsGGT0sbA0+/QkN5NkYYbHbFP6oI
-BJ4xZHVLCoyt+5kscsIZXsLb6jd1d/8RoD1w+559uE3T5AyPmfGRnq9+QjKbf0hx
-MC5lBV/nTWSf+GM0Q/hy2CPvvB7WNA==
+MIIC9TCCAd2gAwIBAgIBADANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhBbmRy
+b2lkIENUUyB1bnRydXN0ZWQgQ0EwIBcNMTUwMTAxMDAwMDAwWhgPMzAwMDAxMDEw
+MDAwMDBaMCMxITAfBgNVBAMTGEFuZHJvaWQgQ1RTIHVudHJ1c3RlZCBDQTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJxrWVqyvdBqIS2GFxQ+2oGR8ONN
+QCZAI8gTsev3uA7Wz3K7AHaNPHLV8AQa6XKdeS8pKdAiIRLg6oL74AcAwAZMR6hp
+Ie4av/GxB5ZXTMi8Zv2XiXwMPDbOW6VPre0eP3dZAJjrdw7/PlrXaTZL2NMAuw5J
+68jghKWT+s+xSNheqUVZZWIj8LPjXZEa9E7jROIRb8itefCbEWBRTB44H8JHz6ov
+ROuRJW3kwAbVYU+CZ6dBnccNCfk44CynLWmOxQOl4IiBx3d13mHE1UmwReAKgfWU
+s0tpTgp/JJkY67utCeglRobUZDHBbaGrX3GE8lp9ewruFKh6Bec7kKOLWn0CAwEA
+AaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoZm89VCXN+zcAjHFuPf+
+etnU6XMwDQYJKoZIhvcNAQELBQADggEBAEzGPABpHWXWSRisW3OSd772kg67zIfd
+DRTlLEewhEmyYNpzfVKOuCAA8pR09wezxUwU/9ZzU1dkQ7lnu7YEfVdLXgKrcQlv
+fzvrd/WK1p4VXRlexmBPI6gWzOjYBUmeMFSXyPeS1ItDSpnG2aBxYoTjGxdZvW5V
+eAQeFVJVKwDlXaw403a/Kl+BUWLt5yuJOhFdTbSnsjFKnoK4a/xbbSINXjPFbRA7
+6l40CLLdfkLGDJ3sTIRRO9c8fBfuHXO5/0K/7n+jP/C6emxw5o7ca7H094UDO4oy
+V52LTVFgL003MyLLKSlmSFqw5ykwFgjkCJ7m3A2S/lHox2e1aXlXg08=
 -----END CERTIFICATE-----
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/make_certs.go b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/make_certs.go
new file mode 100644
index 0000000..e160484
--- /dev/null
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/make_certs.go
@@ -0,0 +1,197 @@
+package main

+

+import (

+	"crypto/rand"

+	"crypto/rsa"

+	"crypto/x509"

+	"crypto/x509/pkix"

+	"encoding/pem"

+	"fmt"

+	"math/big"

+	"os"

+	"time"

+)

+

+func mustDecodePEMKey(in string) ([]byte, *rsa.PrivateKey) {

+	block, _ := pem.Decode([]byte(in))

+	if block == nil || block.Type != "PRIVATE KEY" {

+		panic("could not find PEM block of type PRIVATE KEY")

+	}

+	key, err := x509.ParsePKCS8PrivateKey(block.Bytes)

+	if err != nil {

+		panic(fmt.Sprintf("error decoding private key: %s", err))

+	}

+	return block.Bytes, key.(*rsa.PrivateKey)

+}

+

+func mustWriteFile(name string, data []byte) {

+	if err := os.WriteFile(name, data, 0666); err != nil {

+		panic(err)

+	}

+}

+

+func mustWritePEMBlocks(name string, blocks ...*pem.Block) {

+	var data []byte

+	for _, b := range blocks {

+		data = append(data, pem.EncodeToMemory(b)...)

+	}

+	mustWriteFile(name, data)

+}

+

+func mustMakeCertChain(caName string, eeKey, caKey *rsa.PrivateKey) (eeCert, caCert *x509.Certificate) {

+	notBefore, err := time.Parse(time.DateOnly, "2015-01-01")

+	if err != nil {

+		panic(err)

+	}

+	notAfter, err := time.Parse(time.DateOnly, "3000-01-01")

+	if err != nil {

+		panic(err)

+	}

+

+	caTemplate := x509.Certificate{

+		SerialNumber:          new(big.Int).SetUint64(0),

+		Subject:               pkix.Name{CommonName: caName},

+		NotBefore:             notBefore,

+		NotAfter:              notAfter,

+		BasicConstraintsValid: true,

+		IsCA:                  true,

+		SignatureAlgorithm:    x509.SHA256WithRSA,

+	}

+	caBytes, err := x509.CreateCertificate(rand.Reader, &caTemplate, &caTemplate, caKey.Public(), caKey)

+	if err != nil {

+		panic(err)

+	}

+	caCert, err = x509.ParseCertificate(caBytes)

+	if err != nil {

+		panic(err)

+	}

+

+	eeTemplate := x509.Certificate{

+		SerialNumber:          new(big.Int).SetUint64(1),

+		Subject:               pkix.Name{CommonName: "localhost"},

+		NotBefore:             notBefore,

+		NotAfter:              notAfter,

+		DNSNames:              []string{"localhost"},

+		BasicConstraintsValid: true,

+		SignatureAlgorithm:    x509.SHA256WithRSA,

+	}

+	eeBytes, err := x509.CreateCertificate(rand.Reader, &eeTemplate, caCert, eeKey.Public(), caKey)

+	if err != nil {

+		panic(err)

+	}

+	eeCert, err = x509.ParseCertificate(eeBytes)

+	if err != nil {

+		panic(err)

+	}

+

+	return

+}

+

+func main() {

+	trustedCAKeyDER, trustedCAKey := mustDecodePEMKey(trustedCAKeyPEM)

+	_, untrustedCAKey := mustDecodePEMKey(untrustedCAKeyPEM)

+	endEntityKeyDER, endEntityKey := mustDecodePEMKey(endEntityKeyPEM)

+

+	eeTrusted, caTrusted := mustMakeCertChain("Android CTS trusted CA", endEntityKey, trustedCAKey)

+	eeUntrusted, caUntrusted := mustMakeCertChain("Android CTS untrusted CA", endEntityKey, untrustedCAKey)

+

+	mustWriteFile("test_key.pkcs8", endEntityKeyDER)

+	mustWritePEMBlocks("valid_chain.pem", &pem.Block{Type: "CERTIFICATE", Bytes: eeTrusted.Raw}, &pem.Block{Type: "CERTIFICATE", Bytes: caTrusted.Raw})

+	mustWritePEMBlocks("invalid_chain.pem", &pem.Block{Type: "CERTIFICATE", Bytes: eeUntrusted.Raw}, &pem.Block{Type: "CERTIFICATE", Bytes: caUntrusted.Raw})

+	mustWritePEMBlocks("valid_ca.pem", &pem.Block{Type: "CERTIFICATE", Bytes: caTrusted.Raw}, &pem.Block{Type: "PRIVATE KEY", Bytes: trustedCAKeyDER})

+}

+

+const (

+	endEntityKeyPEM = `

+-----BEGIN PRIVATE KEY-----

+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCh/iHZ86A3hmhN

+Ulp+C/HYX3efQCVWDlsc/PJ7SueYjwsTxnTXai+TF9Dp/StIgX/nvN/ZkTCHY2NQ

+bRKOS5/TAOkUy0MLejj2lhfx0EB5JqyzjkoTWXHq3mvqyRz3zezXnUoOlH29m3FZ

++w6ygcFIoACQ1lZ9NiAesBzvbJRfjbAHKcnnMbb2P6e7dJYLgHtI9SIlX1/sRnTR

+VO1o5hkUM5OSmrxYtwcA3Nua1z+ySf+jOuk58yOeIkSPdfD9AG4RPtyv+QW3vKjx

+bXZRDgoT+p6VFtTYZs/fSqJZHFv7gl1ARwLJtu0D3Vt8GF+ocGuXkvFRk1roRDnX

+T3Qbxhj3AgMBAAECggEAUWzaOyG4kPBgkS0qC12ZrPcfu86UddM1fTav88VM8GRG

+XyRMKtNXIorAGj2FeiaN0kAgDM5sJEGS9CQ/RYNBzOASSL967dP7ugbr9kKFheAo

+wwBsv5kgJ7yxZgy9INpDiIWpafa91YbCzUXit1t9ejHi1urGAp4oOwSvJrHfSr+y

+0tBlT1FeNcMd/11me/lmsanzdli0v/xzkzinRmzesI0d4Z+2XTxBFtlos/vrMMAV

+O5Rlg1VVKnpF6wYf+/he5/q8y2TKr61J2FSFX66VoGvHYzegFCO8Shk2ojYXbcJb

+mvcAHqLnllkGQ5TeqMIOldlewlbbwoIsKtrM981LcQKBgQDOnJvfQJdz4SwjQfyR

+rXqrYnjr70OL5CFMQFcWcLg0NUpCsKlWj+HxeOJ5TMm4WdDCpoqJNGb2dpIH0F8c

+Hvmat3lztMuiTSpHQ4mHdo8v5hBr3m79TNmPVOVbSpXJ6ZzTpgzoIO69NZypSjvr

+CyDNIpm7kSfsAfIIrbkeWjc32wKBgQDItxtqDfxeqVNWM2h10Q2r4VHxaweNZsYe

+oyS1JAIGRqir5L5nIRvYsHpVRPyb/xA7wwd/Z21t89ulcitPA8rHOY3q3llnbDA8

+DczS3CSyHlyHrSq3DDK+tzVavOwM102dZK2vX1n1M2n04f7BgYfzMfhhqU+chZHZ

+RwBp6PTMFQKBgQC/eRVe9V4mLtQXrKxjWRDoyW5kwCyp9PYC01Gh4z5ia8xxN4UH

+SnpKrQu8/DOpG9tCuNKESsLsv3+frDSoO/B3uHbeivt4Yui+eFF475/M9Pnc7ZuQ

+NOseUL/pNZrRLyV+Y1FswjBdutR/cuNKdNqmIN21nNURe9AQyOZYwaSQpwKBgAEw

+/QurG5VgQetgEL2qSP99LeRV80yGkKR76Wrd1Nk+sB+dEvg/vQ+TNJau+yTd5bXF

+GZVLAt5FNUeNHu6wIhL+p3X+bd9sR/kDR/T0c49PGNOBVqCRhPeW1M0+E9Sbro1B

+nLpOwZTwAi/+62kwoKLz5/qEa8GNFWmJv1nhlRplAoGAPpMGm9GP8gB+XMOGQFLE

+kBOoYD3xhFKH9HH83vY878dfDJKdHEBJurUiEsv0/1bs1czrWtFuWGoyOjuvPk7s

+E6CB0HYGPjBw+naDFXgQw69OcucysDS6r3YrkTGFfnu1s20nrRcmP6Dk4c6jCp+i

+9gweslZFc4sWLBohJr1/DxQ=

+-----END PRIVATE KEY-----

+`

+

+	trustedCAKeyPEM = `

+-----BEGIN PRIVATE KEY-----

+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDK7USDnAqJ7Kuj

+uotcjH6pqpsTyY+pEvzWLSa1AGOereCxdXd/uiRSyyD/xBHNiJgY/+yGXLvQw6op

+RE/+CXs61SPxJcvBAXNnoH2GdZNcZGcFjgkVyBLLoskzCj5k+DBW1uN/UMBY04tG

+Gpgn1TGvQ9fkpnkBp8VWHRj4lWZoV8Y/En9QGLzcZDtOgoG8dMU3lJCODlC2VbkN

+oQ1xs7uXMH864qciUs/paURXAJL5xOhkDNpNp85VlpRqtYeK3SSr7zHLGX6SjGAt

+wIqWQNilkJ7NjdQDEaF5GeZK5qHosr0FHHZxIw4qR43ewChUHoBGLsXfQxiPtEfZ

+dHMu6ZctAgMBAAECggEAezX1E7P68iOxU4hAdcEYZwwffLQ1dgMBYUmo5t2FnyMT

++qvIEtWCmIKdVq5F4PW+4+8APdSwdOFYwBWqPCSlneMsH49DV7z5xUG89ZcOElsj

+8kt7WK5SOzJr14GwwL2xHAj9uJ/fKg/H0Jj1KbpYoIIg48PwVQD44IBqWQTdWRxd

+QVbxczDIHAjXSD14P4uUAXQrFyYEQXgksu4FNNGFr6JnuNe6eSreKxrw8/7J9OXZ

+7VUfN0Iuw/M4HF1dKQKVK2R0W34wuS2KyI3fKUS7RoSrfXfBuZ1hQ1gWoATiXkbR

+AAMUSWuaj5RQ4lj0wxdRAO+e4QB2yUXHgzCr8pH6QQKBgQDuiXtcdZ2FVN9ezxJt

+XDd6225Rvh8XtWEUwTaJmOtZz2AKlKTQr06u/BqqpKWc5SWQSf88K7WPxF6EMizB

+4D3wVGzCFkeRMMriZmrRe+8IVCq+mAZnRahV4SSH35ZQoNd8/3Mv6o59/UR0x7Nl

+5yTqruROK0Ycz8S0GlvfKiDyywKBgQDZyGaIYqZ63piagmRx3EB1Z+8yfXnn8g2d

+iVYU3UTDWxAFtzq6cfPRUdDxGHgAjmVmLvSGEaxqYNOftxwC3zk1E03w4/KvXg+y

+Vt+1qPZ7Hj1OcGMYA+1/Qy6+GMneYnUkmO9zHoNzSDG5hfNkQ+3SyMx53FfTO8oA

+Lrpl4gFG5wKBgQCtCGXIKDlf4rU13RgM5HwKTuqzuSps1FHb8FxTa+4tc9TDWBhG

+mSSGorHlXxITwdWB2WughkRqSZQWaR82dCf6EgPitq6rj61cldaepzw52nQ3Vagv

+ecQmp+8L8RDk5Afs0JEKDSfYFMR3wfVM0mNhKgTK/3EYrU6PJx/FvpWwCQKBgDrk

+ICXdV1t+ehG+FN9dSej1tA8ZMy/vmpLxIl/9/aw+IbUJ+U2VpvMBhtjLXxf3aaAa

+LnFash8KE+/qmh6EsnmRwM/VNDkL3H7DUzdSe2SLptRhO8qwtTZmumsZVO1X/olo

++cdNhwpTiW67tDd2zwbi2bhSR0WNs3AdMrZ+SQ4dAoGBANkjgWwzVN8KGOe9GdEo

+opcwVzC1l9xkUcB6ykIG+DKw5p1ChGLA+2uufdpNWfPqXixCt5X3qIOy1q/VIdlj

+EHNurGEld93H86V0ieLMRPg5llXWfKND2W8vezZSCGqFcSo+bAVi0YzA6XbLu+TV

+GyyCD8Jk/efmdN0DKjERIKDH

+-----END PRIVATE KEY-----

+`

+

+	untrustedCAKeyPEM = `

+-----BEGIN PRIVATE KEY-----

+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCca1lasr3QaiEt

+hhcUPtqBkfDjTUAmQCPIE7Hr97gO1s9yuwB2jTxy1fAEGulynXkvKSnQIiES4OqC

+++AHAMAGTEeoaSHuGr/xsQeWV0zIvGb9l4l8DDw2zlulT63tHj93WQCY63cO/z5a

+12k2S9jTALsOSevI4ISlk/rPsUjYXqlFWWViI/Cz412RGvRO40TiEW/IrXnwmxFg

+UUweOB/CR8+qL0TrkSVt5MAG1WFPgmenQZ3HDQn5OOAspy1pjsUDpeCIgcd3dd5h

+xNVJsEXgCoH1lLNLaU4KfySZGOu7rQnoJUaG1GQxwW2hq19xhPJafXsK7hSoegXn

+O5Cji1p9AgMBAAECggEAGrReGTS2YNBZsTi5FHkFm4TjvB66cr1VDonEQL22U/w7

+BwKjmdnTheR9+WlxzSJS5+kObS0CegNhrjKbxP5NClY4DqnCQ/EXr4byfWmSn5vA

+to9KRt4c4pt4/IBduIOHQNQ2XKUomqwbhG1N1ln9Hsr7ZH1czpr8MnuQ4KgLAHtm

+Zd3xibhULlE/5S9uYpvBaqwZx3RJk3CMcseio4aFtpx/yi+UPyDWekS0ch2Fz5MF

+G8wnYqXHt2NZhRWdBrQ7n7ZCQT2zNGvKkekAd2jIl5H+mxIRFSlArgdx+TeDJrxZ

+J+mmYooOY7gE8GL+7pSpCb2yNHcA/CkDQspM14QqOQKBgQDQtnanCgAbxW5pDgT4

+fdi4EVWPt9nF18mMXwDZuSqrwPj1kKx9CqhVXbRT4kMaYgMuhn1coC4m+j95kaG+

+dTLtrfnl8mTr/4HBImaacisn1i9gYKfYwoKscBrK9B5n/zaH/HnCKehbTaeinnID

+vvbd7cI2f/YFPVgiq2W6yxDGyQKBgQC/29Frc5rZyNCellT/583AU240PY5b3yhd

+FsYdkCBdI5suq/shvEmwxDqKv8eJt+MRXdPiFub6Wk3wcsiR20saQSsM09sUA5dQ

+CuKZlD2w93DzsbRXinRtwwBYyGFS4C89Bz1AO6rGyi3+GDlJuTAo7XYP9HVwUVos

+rvYB6rysFQKBgQDDj2Qn6a/mVZy5pOA1cb2B4wQXsL3FqgZ4l3/1gZGg8ySS+2cT

+lsvZiP5xZt1XOCUhD/UguBnmfa7CGxnBmpEIsW4o7nFvy63pqHEZIAadwgwMMySy

+brcAGd6Q8iIXccPHsWLo8ll8S4vaTLoqFmG72o6SgF2l1S/i9FRSrPjgOQKBgG+O

+xo9/MewuezerXBNM2vNYz7yqiktbT+II6vunoVnm6UXTFHxCOmsBPrUM3F50wSCI

++Tn+bSHnPmhwpbVB2MKUYA7eZQWXLPWKzsXUT6bFyjS5AI7iX96uw1XcddK1rmID

+ApeF2kAqsWGM/kqi1qEFql+OmnbLpu5ScZMdxcUdAoGBAIkyMaBNiWyImkyl/bxv

+pnhP/eZf435ZQoXRRKR9ONejT9moJoWfNKqwZKgnnHuYA7XmG45N3vSLZgocggDm

+1XWL2XxS0Qs90JOgM3lY3VUfxRwCCWAiYy4a1O8OxaP8dURgy4uqrtH08xRunsIL

+9G6RWORMdSgKMYvi9bJYoHQZ

+-----END PRIVATE KEY-----

+`

+)
\ No newline at end of file
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_ca.pem b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_ca.pem
index d70b4d6..d894941 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_ca.pem
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_ca.pem
@@ -1,20 +1,20 @@
 -----BEGIN CERTIFICATE-----
-MIIC3jCCAcagAwIBAgIDDGqSMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFkFu
-ZHJvaWQgQ1RTIHRydXN0ZWQgQ0EwKhgTMjAxNTAxMDEwMDAwMDArMDAwMBgTMjAy
-NTAxMDEwMDAwMDArMDAwMDAhMR8wHQYDVQQDExZBbmRyb2lkIENUUyB0cnVzdGVk
-IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyu1Eg5wKieyro7qL
-XIx+qaqbE8mPqRL81i0mtQBjnq3gsXV3f7okUssg/8QRzYiYGP/shly70MOqKURP
-/gl7OtUj8SXLwQFzZ6B9hnWTXGRnBY4JFcgSy6LJMwo+ZPgwVtbjf1DAWNOLRhqY
-J9Uxr0PX5KZ5AafFVh0Y+JVmaFfGPxJ/UBi83GQ7ToKBvHTFN5SQjg5QtlW5DaEN
-cbO7lzB/OuKnIlLP6WlEVwCS+cToZAzaTafOVZaUarWHit0kq+8xyxl+koxgLcCK
-lkDYpZCezY3UAxGheRnmSuah6LK9BRx2cSMOKkeN3sAoVB6ARi7F30MYj7RH2XRz
-LumXLQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
-AQBJi4SF/k1KVUZrweqUZ/QJ5HBDxWo4kE4iNw415qw2fAfNsKJknH1bcqgHa7Ea
-nokT8a1KOQlicInptNRbkwBd3Xakt9k9aCWRqyqBzZZersakZ1cB3SNxameelGzl
-a3dvGqVreE3LWhiQR7A3g84hS1kH5oNiY6GVZRk8BsmUUsvKaS6FJSMb9bAGSijQ
-EZwsBk+HoSuLSVxUDtLZgbs1NYVK8jCG6GPv8cWis03pK3VKqjTi3DDs7mHioViG
-G/TUZPq5ok8BemctNPLZAMLVlWPVB389iTOmgJWdR2Lu7LKh4B952+SeHMo3huUR
-Hn/e+Sq5FmJfDVvFG6U3PEDd
+MIIC8TCCAdmgAwIBAgIBADANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBbmRy
+b2lkIENUUyB0cnVzdGVkIENBMCAXDTE1MDEwMTAwMDAwMFoYDzMwMDAwMTAxMDAw
+MDAwWjAhMR8wHQYDVQQDExZBbmRyb2lkIENUUyB0cnVzdGVkIENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyu1Eg5wKieyro7qLXIx+qaqbE8mPqRL8
+1i0mtQBjnq3gsXV3f7okUssg/8QRzYiYGP/shly70MOqKURP/gl7OtUj8SXLwQFz
+Z6B9hnWTXGRnBY4JFcgSy6LJMwo+ZPgwVtbjf1DAWNOLRhqYJ9Uxr0PX5KZ5AafF
+Vh0Y+JVmaFfGPxJ/UBi83GQ7ToKBvHTFN5SQjg5QtlW5DaENcbO7lzB/OuKnIlLP
+6WlEVwCS+cToZAzaTafOVZaUarWHit0kq+8xyxl+koxgLcCKlkDYpZCezY3UAxGh
+eRnmSuah6LK9BRx2cSMOKkeN3sAoVB6ARi7F30MYj7RH2XRzLumXLQIDAQABozIw
+MDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQQPJNSlR06lnK1Omt7gm+rjW1d
+jDANBgkqhkiG9w0BAQsFAAOCAQEAR7FWtOyGzPp8FsDCqNcPKpUO6hhIrPsbbHJV
+jYo7a5tEwKTqebjJ1+ffPWnS3hfQzb9RVSXeJlDW3kCGe/FWHC7m0lvRMsYBshcP
+WTNhY5WHkxyW/U3pxmgkCaV5eglNQrWyQBkhBLrtK3br7GoLAgG9seHmrYOBlYob
+vyWD1byoLyK44bjNB4kZtx4EbjxUNGWSNaUloeZ0LDrgnLXdRJ5mD4kxDMwd1rEC
+ArxEM7aAvQoJ3kjCTN24RqpwcbLL3B/qAsN7H5rW1WQxeaWNBpksOIXSQm4J+F5U
+OTcqCJMPoPbJRbAbERz/8vI2+rEAcYQqSkYEHl2Vt9l7y1S/NA==
 -----END CERTIFICATE-----
 -----BEGIN PRIVATE KEY-----
 MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDK7USDnAqJ7Kuj
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_chain.pem b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_chain.pem
index a55c643..fe9cc25 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_chain.pem
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/res/raw/valid_chain.pem
@@ -1,36 +1,36 @@
 -----BEGIN CERTIFICATE-----
-MIIC2zCCAcOgAwIBAgIJAKee5CFociA2MA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV
-BAMTFkFuZHJvaWQgQ1RTIHRydXN0ZWQgQ0EwHhcNMTgwNTE3MTkyODQ2WhcNMzQx
-MDIwMTkyODQ2WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQCh/iHZ86A3hmhNUlp+C/HYX3efQCVWDlsc/PJ7SueY
-jwsTxnTXai+TF9Dp/StIgX/nvN/ZkTCHY2NQbRKOS5/TAOkUy0MLejj2lhfx0EB5
-JqyzjkoTWXHq3mvqyRz3zezXnUoOlH29m3FZ+w6ygcFIoACQ1lZ9NiAesBzvbJRf
-jbAHKcnnMbb2P6e7dJYLgHtI9SIlX1/sRnTRVO1o5hkUM5OSmrxYtwcA3Nua1z+y
-Sf+jOuk58yOeIkSPdfD9AG4RPtyv+QW3vKjxbXZRDgoT+p6VFtTYZs/fSqJZHFv7
-gl1ARwLJtu0D3Vt8GF+ocGuXkvFRk1roRDnXT3Qbxhj3AgMBAAGjIzAhMAkGA1Ud
-EwQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQCD
-lghY2E4wRutn52RxI9rwd/Ljp13RLLVIKIgyqHTNc4HxC8rlV02rSAcVo1MasDom
-rye3xr/7CVfWF1zu8AFgLZTd83TOf8z62zk4FhiOCmSMKTzCRiab221X4nyHvegI
-EbtukUYmSaPMvSVOFQQLM7+0yCO9GOC3n3YxOaWUsdDPb8oMn86Y0lOHF1MhzFAS
-uh7oF31AEktgDI8J47HQbIQ8dJVCS4gkB42vyX5gY/xD/dTi2oWBMYdcyiDl4Fxi
-mRCuXvj6vkDxLUKoroav5oYUyMB3oZVZe/74YQ+4Yggb+0tOhQhiz26hwcnF0DMI
-m5NKweDumNzCtPfXfNgJ
+MIIC+TCCAeGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBbmRy
+b2lkIENUUyB0cnVzdGVkIENBMCAXDTE1MDEwMTAwMDAwMFoYDzMwMDAwMTAxMDAw
+MDAwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCh/iHZ86A3hmhNUlp+C/HYX3efQCVWDlsc/PJ7SueYjwsTxnTX
+ai+TF9Dp/StIgX/nvN/ZkTCHY2NQbRKOS5/TAOkUy0MLejj2lhfx0EB5JqyzjkoT
+WXHq3mvqyRz3zezXnUoOlH29m3FZ+w6ygcFIoACQ1lZ9NiAesBzvbJRfjbAHKcnn
+Mbb2P6e7dJYLgHtI9SIlX1/sRnTRVO1o5hkUM5OSmrxYtwcA3Nua1z+ySf+jOuk5
+8yOeIkSPdfD9AG4RPtyv+QW3vKjxbXZRDgoT+p6VFtTYZs/fSqJZHFv7gl1ARwLJ
+tu0D3Vt8GF+ocGuXkvFRk1roRDnXT3Qbxhj3AgMBAAGjRzBFMAwGA1UdEwEB/wQC
+MAAwHwYDVR0jBBgwFoAUEDyTUpUdOpZytTpre4Jvq41tXYwwFAYDVR0RBA0wC4IJ
+bG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQB3EE58O/0qE13Gx+Y91/+BOJRs
+ETGpRiaU3xA1uCqRWcvNXpJ+/U6tK3apHv/XEXjUnnfeqWzGIJ9sx4jFZbSoL+kD
+vJhv7q5O+0NAkuNwCtfgXsWfivqn9+1jJbjGpMMha4wO95JKn4U8YBheDiFJ1dtU
+8A/24YWLyOV0CYp+jUhaXm1kYtErE2xKqKUqRFjc1F5IbFhnKkgJTltSSQrhEVNj
+cSrphlXdTvWWHS4+WcXcLXWvtTFjsEIap3OD5NKngThSC3aa9TmxDeBvjy+DfI0y
+uRM4IYDlpusmB17odbHfq+ReCqhZpP+f2QTuomk7bFXUAw5e0crnVaxtAGg0
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIC3jCCAcagAwIBAgIDDGqSMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFkFu
-ZHJvaWQgQ1RTIHRydXN0ZWQgQ0EwKhgTMjAxNTAxMDEwMDAwMDArMDAwMBgTMjAy
-NTAxMDEwMDAwMDArMDAwMDAhMR8wHQYDVQQDExZBbmRyb2lkIENUUyB0cnVzdGVk
-IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyu1Eg5wKieyro7qL
-XIx+qaqbE8mPqRL81i0mtQBjnq3gsXV3f7okUssg/8QRzYiYGP/shly70MOqKURP
-/gl7OtUj8SXLwQFzZ6B9hnWTXGRnBY4JFcgSy6LJMwo+ZPgwVtbjf1DAWNOLRhqY
-J9Uxr0PX5KZ5AafFVh0Y+JVmaFfGPxJ/UBi83GQ7ToKBvHTFN5SQjg5QtlW5DaEN
-cbO7lzB/OuKnIlLP6WlEVwCS+cToZAzaTafOVZaUarWHit0kq+8xyxl+koxgLcCK
-lkDYpZCezY3UAxGheRnmSuah6LK9BRx2cSMOKkeN3sAoVB6ARi7F30MYj7RH2XRz
-LumXLQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
-AQBJi4SF/k1KVUZrweqUZ/QJ5HBDxWo4kE4iNw415qw2fAfNsKJknH1bcqgHa7Ea
-nokT8a1KOQlicInptNRbkwBd3Xakt9k9aCWRqyqBzZZersakZ1cB3SNxameelGzl
-a3dvGqVreE3LWhiQR7A3g84hS1kH5oNiY6GVZRk8BsmUUsvKaS6FJSMb9bAGSijQ
-EZwsBk+HoSuLSVxUDtLZgbs1NYVK8jCG6GPv8cWis03pK3VKqjTi3DDs7mHioViG
-G/TUZPq5ok8BemctNPLZAMLVlWPVB389iTOmgJWdR2Lu7LKh4B952+SeHMo3huUR
-Hn/e+Sq5FmJfDVvFG6U3PEDd
+MIIC8TCCAdmgAwIBAgIBADANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBbmRy
+b2lkIENUUyB0cnVzdGVkIENBMCAXDTE1MDEwMTAwMDAwMFoYDzMwMDAwMTAxMDAw
+MDAwWjAhMR8wHQYDVQQDExZBbmRyb2lkIENUUyB0cnVzdGVkIENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyu1Eg5wKieyro7qLXIx+qaqbE8mPqRL8
+1i0mtQBjnq3gsXV3f7okUssg/8QRzYiYGP/shly70MOqKURP/gl7OtUj8SXLwQFz
+Z6B9hnWTXGRnBY4JFcgSy6LJMwo+ZPgwVtbjf1DAWNOLRhqYJ9Uxr0PX5KZ5AafF
+Vh0Y+JVmaFfGPxJ/UBi83GQ7ToKBvHTFN5SQjg5QtlW5DaENcbO7lzB/OuKnIlLP
+6WlEVwCS+cToZAzaTafOVZaUarWHit0kq+8xyxl+koxgLcCKlkDYpZCezY3UAxGh
+eRnmSuah6LK9BRx2cSMOKkeN3sAoVB6ARi7F30MYj7RH2XRzLumXLQIDAQABozIw
+MDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQQPJNSlR06lnK1Omt7gm+rjW1d
+jDANBgkqhkiG9w0BAQsFAAOCAQEAR7FWtOyGzPp8FsDCqNcPKpUO6hhIrPsbbHJV
+jYo7a5tEwKTqebjJ1+ffPWnS3hfQzb9RVSXeJlDW3kCGe/FWHC7m0lvRMsYBshcP
+WTNhY5WHkxyW/U3pxmgkCaV5eglNQrWyQBkhBLrtK3br7GoLAgG9seHmrYOBlYob
+vyWD1byoLyK44bjNB4kZtx4EbjxUNGWSNaUloeZ0LDrgnLXdRJ5mD4kxDMwd1rEC
+ArxEM7aAvQoJ3kjCTN24RqpwcbLL3B/qAsN7H5rW1WQxeaWNBpksOIXSQm4J+F5U
+OTcqCJMPoPbJRbAbERz/8vI2+rEAcYQqSkYEHl2Vt9l7y1S/NA==
 -----END CERTIFICATE-----
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_multiple.der b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_multiple.der
index 784263f..6d68c18 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_multiple.der
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_multiple.der
Binary files differ
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_single.der b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_single.der
index 64a1359..8694ac0 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_single.der
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/der_single.der
Binary files differ
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_multiple.pem b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_multiple.pem
index f342f3a..3d8216d 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_multiple.pem
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_multiple.pem
@@ -1,34 +1,36 @@
 -----BEGIN CERTIFICATE-----
-MIICvDCCAaSgAwIBAgIDBwztMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNVBAMUBVBF
-TV8xMCoYEzIwMTUwMTAxMDAwMDAwKzAwMDAYEzIwMjAwMTAxMDAwMDAwKzAwMDAw
-EDEOMAwGA1UEAxQFUEVNXzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQCq2QLoIjhJW51CpfQcoiXmtCB6GltsM5HEYqA52AQZXOeO4HXzFwizycpwA1Sh
-EWkKnbvONQ7HO/rxb1gWcU4IWOPMY54BI2hOMiOmknTeobLW38WnCJzeD0mOxx7Z
-9dzRFoAcQdEPvWlB7MD5hK0+sS/CAZcx5Qc/DBE5RrWliKXXsYK5lAdtQiXB4L6H
-126SkH1ZmALer8wAMRhhUSeYoWwR4z7w5kRRntO9lAAA8lfS61K0ojSz170cyH41
-/jvkMFXP1MV8ljxVU5CgNdnRmAgogz834btJ9dbZGckt1Trxp0k7Y9CdRBrykaw/
-n2TQymCdeTGoxV0vWa++InVjAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQELBQADggEBAJWI/rlbtVDsVI2w9Ylf+Agzx7n5xFytrz64d8YcqPlm
-MI/8/PlzA32MqWohe7D/DXbsx8lDctii8sI6L9zjYKxkXIhs6bBnXlbTjHgOhloq
-v3yL1VnJSNfXFjL46jvps8pPbTobjzFNCazS2xZTlIs1MQfpF8nG63+FoTcRGmK8
-q500bS2gQ2lEwh3FusrKAyRGiBJtfnw0pyhOsNpO63yi4HGMMtVpC/6rIkpAor/g
-vIaOWsCYa6yllaeSDGbWyu5GBkZJa9pewCjUQLSwktHuhI9RsUMe9CcBwto3y37I
-151kgX4xNlJYDoomE6ORGgEWqS5fB39GY2f7W9URfXE=
+MIIC0DCCAbigAwIBAgIELVMuzzANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAVQ
+RU1fMTAeFw0xNTAxMDEwMDAwMDBaFw0yMDAxMDEwMDAwMDBaMBAxDjAMBgNVBAMM
+BVBFTV8xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuR70CIgykOVY
+UmpG9f+kjfrPBf1Ald9J3XhFyABVMtfrkH9Vs9HjoG7GL/pSbTR9lBgHKd8MtHUu
+sZDuj3xm8V74AdO+5R8HUK2ZYVraBpDCUkDltetJQDnJR7Bdz406jT5ROSSyqZco
+rsyprEth51KGZGqSVwgdkkGTEygsDtgLWspbt8Rv9cgayx/2nCUSSaWTJmUiWwJE
+L4xwr+cr/SRntVXMtAH6yCNOXhvxhGLISkyGNvVlvlj+yJ09kZHme/+YSDkJQ1Qk
+1cRjOsonyyDACMkjM7Jl3g6/K24EI7+JvZcVs2TgWK/WJcFKpd0A7kV/zHPLRz5u
+aGUxIydXqwIDAQABozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQbatWA
+XVmEk8y+i6E53sf2AWvHFDANBgkqhkiG9w0BAQsFAAOCAQEAKSaPw78p2m8ETFCn
+B7Rd42mI+kUc5bCOEXChIUVUau9ixyYrIfXu1HK6w06lDmyiQ8AKMZSbGzhmlyf5
+mYt8Ri0iQ9ROvRShaT7z0gH7rooGP0SJ7K5EOaLo5qtadxO2JUedMCcIBPWlSk3u
+wpDmmuJIvvq7MOdxohrIzrWdZxvj6zD+ioxvSjyeKqcf/5vw6yu5tM1LUrMGwRJ2
+gZIm0nMWTDWM0qvNo2IHEXH+vE+qr5aLxpnfcpwQsVFKUhGVA06LmhCa3KWtf7qo
+bX2E+bECkZ0l/rfcRNuJNf8pJGlxKhOkPBKlcwmqIqbzbrdcvHTDqk9HdY0x2Yea
+W6GOrw==
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIICvDCCAaSgAwIBAgIDC+NwMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNVBAMUBVBF
-TV8yMCoYEzIwMTUwMTAxMDAwMDAwKzAwMDAYEzIwMjAwMTAxMDAwMDAwKzAwMDAw
-EDEOMAwGA1UEAxQFUEVNXzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQCnMte2oRePmLQB8h4+cBoI2ZAC5KWC0O0nPdEXO383IDoPB/V1dRXy/ZXFw2JU
-acPq+fT+tXw8aiiEH7Jq4wPvI1E1YgvcDnl39xmOvRgoHk2/V9SMJ2L1w2h9aK/4
-490ECRNB1MyydSwG9uE9zoYAHoOjMUfjvjPIjURrJoRx0EiVc+6E6qB92DvOloIW
-PZq60Nql19H8Jl6ISj/br8wKiNN0nkZ3M2/Ditbr/bgucEqHAy9p0J0gPQ4mmlRk
-QTk3gRsHZw2zAn4wyaWKgbB+sY1z77IZ0HeS4FbI2h/qfx4IfIEBOT8IVkJoHqN+
-j6+xI8fWOHRACLevj6Cf+WeZAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQELBQADggEBAIofR+BsrnvRIr+vkABRKJ8shds4mfBCv3Uv0oyLPgoY
-M1X79NuPuT4TmlhX38yk242FTMXwUn1FsTQjA9NNc7BD6aJHZ3/ivdbAViMVs+ND
-1hjlSuzg9N2rDV/+QR2axUBgLNGN4g07IjZpkky4+LB/Havx8e1TQ52NGze1iCjk
-d/+1CjfLCBrIRM2KfQQtqL6Ee6Dy5OIlzk7N1SQ18ON1eVuc/JK7d4bh/vJgUwsq
-wWUOEBkLx1Bu4Na6u+u4pwuKz6XhHN1Sn4TUB7J5p1NS0KEfcuK+qBe0RJbAXhYE
-OF7PYii754/zZBTZYspK2I9WRk9jaXFdKhcA7ptkBfk=
+MIIC0TCCAbmgAwIBAgIFAPYnNg0wDQYJKoZIhvcNAQELBQAwEDEOMAwGA1UEAwwF
+UEVNXzEwHhcNMTUwMTAxMDAwMDAwWhcNMjAwMTAxMDAwMDAwWjAQMQ4wDAYDVQQD
+DAVQRU1fMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALA/CPFWz8VR
+A0Jt+tJKiumipOe3oDqkRwS8AjAHkFoNRA8bsnwQ4WL3hJEYOjx/iMf3LGB5/ky4
+nM+I+SLxTNZGwy3WR2M0EcaYLVIY9y20Kjtx5jqVEPS4SCoDglpPx2fX0UciWX52
+r6uV/WVcVT2BEIHxoEelTODTzxBrG7W8EHiAa8vyldkZ6Jw8gMoOgu41UXdCC+BY
+Jem8jRQXzL+bA5IT28+FtQAqp4llZ4fsddfxa5bVOeVtd7/H9h17MEBH9KWDl1Vp
+vBrpaebP6bVAig6arUM6l2THpkbkD2+RG/y3JMBJCo27PLGfssHn3fLhbXRdkawr
+cQkB2FJXu8MCAwEAAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNY9/
+eg1VHlJ5JMI2oMMXLq9/nX0wDQYJKoZIhvcNAQELBQADggEBAKVrsyYqb7KBUUp6
+h6Fbv3OA8Z9fsViVq2W8ElWbXSrVuO0Ckv8kuPoAXuKRIXzgSn1ESV0Xi95ETaah
+UymyBbmtJLPAhkt28CJD5btJRvQo8qFSYJ2ZtcBtBHLUY3LcfBQhZc7dVDurqpyD
+tBLW/bxETWnhCBCPB0aJ4I1W8OKPHpKRO/8op3m9sy0foVPa/dbzhVSTvg7kb0d/
+m1SkBPrB3U1Y55TVPNcKI3hSXucblZoN4+QaIsN3NoObR78X6Aivce/djtVbE3wD
+nE7ABWfuuPf0ZVNUTu+Pqdq9yM9CQ/6DymXA460YtzYrq8OIUBHwac1+cRwl0wOy
+XvssHrI=
 -----END CERTIFICATE-----
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_single.pem b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_single.pem
index b0ebd7b..f70c4d5 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_single.pem
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/res/raw/pem_single.pem
@@ -1,17 +1,18 @@
 -----BEGIN CERTIFICATE-----
-MIICxjCCAa6gAwIBAgIDD0EmMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNVBAMUClBF
-TV9zaW5nbGUwKhgTMjAxNTAxMDEwMDAwMDArMDAwMBgTMjAyMDAxMDEwMDAwMDAr
-MDAwMDAVMRMwEQYDVQQDFApQRU1fc2luZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEAvvfUKgXYIKc2C3kqwvhtHatNjWU7sTSmAx5Fh3Ok4H41M6XF
-4sTAECkU3UZGIM2kwrb+IJcJBlwg0SG/9s0e5bk1qvvu2iUZjR3y/oOcj/VGNtOT
-DC3TqCkAe4pd6FbydeMIo4H8t1s1Zg0BoGa15o3YvcBS7QOusAMb+h2rj2lVH5+F
-bet+KydK02FUACXYUIL+Em0QcF9ylGLVnfuieGaEtOEwxUhWui1DuDHcJ4V+nG1y
-9jpL+X2EvN7/oXBGV03kEo+i/QnwwI2x8r7yh8ZfkHgUlz5WSWNLQZD+IXOw8DuY
-eAQSvQtqPgYFVi4Zq4dVnWmmmyiKwoLn8eYkZQIDAQABoxMwETAPBgNVHRMBAf8E
-BTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQALfm/CaKleAeAccKEY9wZ796ycfwJn
-H5WdX2LEbosKdr21pbjvna/IPxz6QueX9YAWGWAWNowZDlLRStZR7EAP23cEzWbW
-qQtTuQ+wu1v2M4Zuzw2UAi89ooaXK0VskeMK5AnqY4trAWKMeetOANSdj+J8WIdg
-30jmXuLKX9PLfpq6iNLMcGM3j8Q5cCZmnf6q3KYP/7D5iMeMb/rVGNapfTOyGNFe
-PPhOMFU20BZLpIKpdEAmbWhtX5gzGXADObU6VpBIlG7B2BiUUuQjz3FDKljK7L1r
-bsu+L7mWzAlW4yDt+VwgYmYf1m/RxrCxtLAqQYfJPekQeh3wycLfN9g3
+MIIC2jCCAcKgAwIBAgIEeoeKbzANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApQ
+RU1fc2luZ2xlMB4XDTE1MDEwMTAwMDAwMFoXDTIwMDEwMTAwMDAwMFowFTETMBEG
+A1UEAwwKUEVNX3NpbmdsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AOtHEG/MPdgUjRmCUONB6jqypVQmk/MzpUTtrxtrJo8G+dQ6gJWuNHcFXzmGWvLF
+I4A725IMrKzonLx8PYOZ4jGFCTC+iFkByVMeGCVsCUWz3XCTm9+DMpCSPHT0y0iP
+ssJah5tCs0vcWVxjW9WUOYfXbLLYTX9qnpIhyTigzRwGH88yCjXxnTY6aWvNms+0
++iy6Wf/p/8m04LCqhvko7LKU0pV+OngLgvhL0rhCfHBHEwRdRrWObskTRUUwj5ly
+tTUllbEhEAZvXLVcMMiyTluA2VbPwBhotC9w4MxxZYfjcvcZu8O5Sb2ngg0LnGhr
++YwiHOvlzuTW3VL0Yo7bJOUCAwEAAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUW5+w6QgBPZAjrLN8zk+YnQiDudcwDQYJKoZIhvcNAQELBQADggEBAOek
+b5cObC9TV1yPgeVrT3dYUpDAMh7UGTsRI2ilBHXGcq144ER/vp0epeYcj7V7Y1kF
+Bz2RJo7XKw6U05yhyNfuTwsr0zwV++zpa8tzwV3hrItzgTcIb/a8pgfTVolTQ/e0
+EXfs+nzq76wlPr/L31cdyp4pOKM8OC8VOVr5ENvNWkdZEwOGeViCyDOnJbvEPCC8
+4Pn7H2Y+ipAdm6EPe6LaIXWj7nTcEL/f5wXZv+Y+TLF7mmFhONPvOHqN6By9FjN3
+rBWr211fXHKnI6KUMtpN4oeiFdD4OXKrV9BXKwoJaMtfELoGmu4JgHFQeJ8/qLf9
+mmmhxCkKcwRoERjp0gs=
 -----END CERTIFICATE-----
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/src/android/security/net/config/cts/ResourceSourceTest.java b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/src/android/security/net/config/cts/ResourceSourceTest.java
index 75d3766..82591a8 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/src/android/security/net/config/cts/ResourceSourceTest.java
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/src/android/security/net/config/cts/ResourceSourceTest.java
@@ -17,8 +17,8 @@
 package android.security.net.config.cts;
 
 import android.security.net.config.cts.CtsNetSecConfigResourcesSrcTestCases.R;
-
 import android.test.MoreAsserts;
+
 import java.io.InputStream;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
@@ -26,6 +26,7 @@
 import java.security.cert.X509Certificate;
 import java.util.HashSet;
 import java.util.Set;
+
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
@@ -35,12 +36,14 @@
     public void testSingleDerPresent() throws Exception {
         Set<X509Certificate> trusted = getTrustedCertificates();
         Set<X509Certificate> singleDer = loadCertificates(R.raw.der_single);
+        assertEquals(1, singleDer.size());
         assertContainsAll(trusted, singleDer);
     }
 
     public void testSinglePemPresent() throws Exception {
         Set<X509Certificate> trusted = getTrustedCertificates();
         Set<X509Certificate> singlePem = loadCertificates(R.raw.pem_single);
+        assertEquals(1, singlePem.size());
         assertContainsAll(trusted, singlePem);
     }
 
diff --git a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java
index f5b0140..d83cd94 100644
--- a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java
+++ b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java
@@ -17,6 +17,7 @@
 package android.security.net.config.cts;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.wifi.WifiManager;
 import android.test.AndroidTestCase;
 
@@ -26,12 +27,24 @@
  * Base test case for all tests under {@link android.security.net.config.cts}.
  */
 public class BaseTestCase extends AndroidTestCase {
+
+    private boolean isWifiSupported(Context context) {
+        final PackageManager packageManager = context.getPackageManager();
+        return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
+    }
+
     @Override
     public void setUp() throws Exception {
         // Instant Apps cannot access WifiManager, skip wifi check.
         if (getContext().getPackageManager().isInstantApp()) {
             return;
         }
+
+	// Skip accessing wifi manager if Wifi feature is not supported.
+        if (!isWifiSupported(getContext())) {
+            return;
+        }
+
         WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         if (!wifiManager.isWifiEnabled()) {
             SystemUtil.runShellCommand("svc wifi enable"); // toggle wifi on.
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcFrameworkInitializerTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcFrameworkInitializerTest.java
new file mode 100644
index 0000000..482ea29
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcFrameworkInitializerTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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.nfc.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nfc.NfcFrameworkInitializer;
+import android.nfc.NfcServiceManager;
+import android.test.AndroidTestCase;
+
+public class NfcFrameworkInitializerTest extends AndroidTestCase {
+
+    /**
+     * NfcFrameworkInitializer.registerServiceWrappers() should only be called by
+     * SystemServiceRegistry during boot up when Nfc is first initialized. Calling this API at
+     * any other time should throw an exception.
+     */
+    public void test_RegisterServiceWrappers_failsWhenCalledOutsideOfSystemServiceRegistry() {
+        assertThrows(IllegalStateException.class,
+                () -> NfcFrameworkInitializer.registerServiceWrappers());
+    }
+
+    public void test_SetNfcServiceManager() {
+        assertThrows(IllegalStateException.class,
+                () -> NfcFrameworkInitializer.setNfcServiceManager(
+                    new NfcServiceManager()));
+    }
+
+    // org.junit.Assume.assertThrows is not available until JUnit 4.13
+    private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
+        try {
+            r.run();
+            fail("Expected " + exceptionClass + " to be thrown.");
+        } catch (Exception exception) {
+            assertThat(exception).isInstanceOf(exceptionClass);
+        }
+    }
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcServiceManagerTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcServiceManagerTest.java
new file mode 100644
index 0000000..6920a61
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcServiceManagerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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.nfc.cts;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.pm.PackageManager;
+import android.nfc.NfcServiceManager;
+import android.nfc.NfcServiceManager.ServiceNotFoundException;
+import android.nfc.NfcServiceManager.ServiceRegisterer;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+
+public class NfcServiceManagerTest extends AndroidTestCase {
+
+    private boolean mHasNfc;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mHasNfc = getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_NFC);
+    }
+
+    public void test_ServiceRegisterer() {
+        if (!mHasNfc) {
+            return;
+        }
+        NfcServiceManager serviceManager = new NfcServiceManager();
+        ServiceRegisterer serviceRegisterer =
+                serviceManager.getNfcManagerServiceRegisterer();
+
+        assertThrows(SecurityException.class, () ->
+                serviceRegisterer.register(serviceRegisterer.get()));
+
+        IBinder nfcServiceBinder = serviceRegisterer.get();
+        assertNotNull(nfcServiceBinder);
+
+        nfcServiceBinder = serviceRegisterer.tryGet();
+        assertNotNull(nfcServiceBinder);
+
+        try {
+            nfcServiceBinder = serviceRegisterer.getOrThrow();
+            assertNotNull(nfcServiceBinder);
+        } catch (ServiceNotFoundException exception) {
+            fail("ServiceNotFoundException should not be thrown");
+        }
+    }
+
+    public void test_ServiceNotFoundException() {
+        ServiceManager.ServiceNotFoundException baseException =
+                new ServiceManager.ServiceNotFoundException("");
+        String exceptionDescription = "description test";
+        String baseExceptionDescription = baseException.getMessage();
+        ServiceNotFoundException newException =
+                new ServiceNotFoundException(exceptionDescription);
+        assertEquals(baseExceptionDescription + exceptionDescription, newException.getMessage());
+        try {
+            throw newException;
+        } catch (ServiceNotFoundException exception) {
+            assertEquals(baseExceptionDescription + exceptionDescription, exception.getMessage());
+        }
+    }
+}
diff --git a/tests/tests/openglperf/OWNERS b/tests/tests/openglperf/OWNERS
new file mode 100644
index 0000000..e8d06b51
--- /dev/null
+++ b/tests/tests/openglperf/OWNERS
@@ -0,0 +1,18 @@
+# Bug component: 25421
+# OpenGL Component: https://b.corp.google.com/components/25421/manage#basic
+abdolrashidi@google.com
+cclao@google.com
+chrisforbes@google.com
+chrisfoulds@google.com
+cnorthrop@google.com
+ianelliott@google.com
+lpy@google.com
+memoreno@google.com
+nexa@google.com
+pbaiget@google.com
+romanl@google.com
+sogden@google.com
+solti@google.com
+vantablack@google.com
+yuxinhu@google.com
+
diff --git a/tests/tests/os/TEST_MAPPING b/tests/tests/os/TEST_MAPPING
index 56e9dc6..7e76bc0 100644
--- a/tests/tests/os/TEST_MAPPING
+++ b/tests/tests/os/TEST_MAPPING
@@ -14,5 +14,98 @@
         }
       ]
     }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "CtsOsTestCases",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.RestrictedBuildTest"
+        },
+        {
+          // TODO(b/181318429)
+          "exclude-filter": "android.os.cts.AppHibernationIntegrationTest#testUnusedApp_getsForceStopped"
+        },
+        {
+          // TODO(b/243642791)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testAppWithPermissionsChangedRecently_doesNotGetPermissionRevoked"
+        },
+        {
+          // TODO(b/238904536)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testAutoRevoke_goToUnusedAppsPage_removesSafetyCenterIssue"
+        },
+        {
+          // TODO(b/182562411)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testAutoRevoke_userAllowlisting"
+        },
+        {
+          // TODO(b/182563360)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testPreMinAutoRevokeVersionUnusedApp_doesntGetPermissionRevoked"
+        },
+        {
+          // TODO(b/213570804)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testInstallGrants_notRevokedImmediately"
+        },
+        {
+          // TODO(b/234629012)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testUnusedApp_uninstallApp"
+        },
+        {
+          // TODO(b/201545116)
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testUnusedApp_getsPermissionRevoked"
+        },
+        {
+          "exclude-filter": "android.os.cts.AutoRevokeTest#testPreRUnusedApp_doesntGetPermissionRevoked"
+        },
+        {
+          // TODO(b/203876506)
+          "exclude-filter": "android.os.cts.BuildTest#testSdkInt"
+        },
+        {
+          // TODO(b/221873359)
+          "exclude-filter": "android.os.cts.CompanionDeviceManagerTest#testProfiles"
+        },
+        {
+          // TODO(b/244594813)
+          "exclude-filter": "android.os.cts.DebugTest#testStartMethodTracingDefaultExternalStorage"
+        },
+        {
+          "exclude-filter": "android.os.cts.FileObserverTest#testConstructor"
+        },
+        {
+          "exclude-filter": "android.os.cts.FileObserverTest#testFileObserver"
+        },
+        {
+          "exclude-filter": "android.os.cts.FileObserverTest#testFileObserverExternal"
+        },
+        {
+          "exclude-filter": "android.os.cts.FileObserverTest#testFileObserverExternalStorageDirectory"
+        },
+        {
+          "exclude-filter": "android.os.cts.FileObserverTest#testFileObserver_multipleFilesFull"
+        },
+        {
+          // TODO(b/180726379)
+          "exclude-filter": "android.os.cts.SeccompTest#testKernelPrecedenceTests"
+        },
+        {
+          // TODO(b/214271070)
+          "exclude-filter": "android.os.storage.cts.StorageManagerTest#testAttemptMountNonObb"
+        },
+        {
+          "exclude-filter": "android.os.storage.cts.StorageManagerTest#testAttemptMountObbWrongPackage"
+        },
+        {
+          "exclude-filter": "android.os.storage.cts.StorageManagerTest#testMountAndUnmountObbNormal"
+        },
+        {
+          // TODO(b/203424057)
+          "exclude-filter": "android.os.storage.cts.StorageManagerTest#testMountAndUnmountTwoObbs"
+        }
+      ]
+    }
   ]
 }
diff --git a/tests/tests/os/src/android/os/cts/OperationCanceledExceptionTest.java b/tests/tests/os/src/android/os/cts/OperationCanceledExceptionTest.java
new file mode 100644
index 0000000..f15913f
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/OperationCanceledExceptionTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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.os.cts;
+
+import android.os.OperationCanceledException;
+
+import com.android.compatibility.common.util.ApiTest;
+
+import junit.framework.TestCase;
+
+@ApiTest(apis = {"android.os.OperationCanceledException#OperationCanceledException"})
+public class OperationCanceledExceptionTest extends TestCase {
+    public void testOperationCanceledException() {
+        OperationCanceledException e = null;
+        boolean isThrowed = false;
+
+        try {
+            e = new OperationCanceledException("OperationCanceledException");
+            throw e;
+        } catch (OperationCanceledException ex) {
+            assertSame(e, ex);
+            isThrowed = true;
+        } finally {
+            if (!isThrowed) {
+                fail("should throw out OperationCanceledException");
+            }
+        }
+
+        isThrowed = false;
+
+        try {
+            e = new OperationCanceledException();
+            throw e;
+        } catch (OperationCanceledException ex) {
+            assertSame(e, ex);
+            isThrowed = true;
+        } finally {
+            if (!isThrowed) {
+                fail("should throw out OperationCanceledException");
+            }
+        }
+    }
+
+}
diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp
index eae7276..f90f789 100644
--- a/tests/tests/permission/Android.bp
+++ b/tests/tests/permission/Android.bp
@@ -47,6 +47,7 @@
         // which provides assertThrows
         "testng",
         "bluetooth-test-util-lib",
+        "sts-device-util",
     ],
     jni_libs: [
         "libctspermission_jni",
@@ -111,6 +112,8 @@
         ":CtsStorageEscalationApp29Full",
         ":CtsStorageEscalationApp29Scoped",
         ":CtsVictimPermissionDefinerApp",
+        ":CtsAppThatRequestsSystemAlertWindow22",
+        ":CtsAppThatRequestsSystemAlertWindow23",
     ],
     per_testcase_directory: true,
 }
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index f16ef09..95f79df 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -94,6 +94,8 @@
         <option name="push" value="CtsStorageEscalationApp28.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp28.apk" />
         <option name="push" value="CtsStorageEscalationApp29Full.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp29Full.apk" />
         <option name="push" value="CtsStorageEscalationApp29Scoped.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp29Scoped.apk" />
+        <option name="push" value="CtsAppThatRequestsSystemAlertWindow22.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsSystemAlertWindow22.apk" />
+        <option name="push" value="CtsAppThatRequestsSystemAlertWindow23.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsSystemAlertWindow23.apk" />
     </target_preparer>
 
     <!-- Remove additional apps if installed -->
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow22/Android.bp b/tests/tests/permission/AppThatRequestSystemAlertWindow22/Android.bp
new file mode 100644
index 0000000..43cc9de
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow22/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2022 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"],
+}
+
+android_test_helper_app {
+    name: "CtsAppThatRequestsSystemAlertWindow22",
+    target_sdk_version: "22",
+    certificate: ":cts-testkey2",
+    min_sdk_version: "22",
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts-permission",
+        "sts",
+    ],
+}
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml b/tests/tests/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml
new file mode 100644
index 0000000..8b85b13
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission3.cts.usesystemalertwindowpermission">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+</manifest>
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow23/Android.bp b/tests/tests/permission/AppThatRequestSystemAlertWindow23/Android.bp
new file mode 100644
index 0000000..403257d
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow23/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2022 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"],
+}
+
+android_test_helper_app {
+    name: "CtsAppThatRequestsSystemAlertWindow23",
+    target_sdk_version: "23",
+    certificate: ":cts-testkey2",
+    min_sdk_version: "23",
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts-permission",
+        "sts",
+    ],
+}
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml b/tests/tests/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml
new file mode 100644
index 0000000..8b85b13
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission3.cts.usesystemalertwindowpermission">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+</manifest>
diff --git a/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
index fd7e977..030f341 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
@@ -17,6 +17,8 @@
 
 package android.permission.cts;
 
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
 import android.content.Context;
 import android.media.MediaPlayer;
 import android.net.wifi.WifiManager;
@@ -49,6 +51,10 @@
     @AppModeFull(reason = "Instant apps cannot access the WifiManager")
     @SmallTest
     public void testWifiLockAcquire() {
+        if (!mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI)) {
+            return;
+        }
+
         final WifiManager wifiManager = (WifiManager) mContext.getSystemService(
                 Context.WIFI_SERVICE);
         final WifiLock wifiLock = wifiManager.createWifiLock("WakeLockPermissionTest");
diff --git a/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
index d8acd50..6be8d7d 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
@@ -16,6 +16,8 @@
 
 package android.permission.cts;
 
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
 import android.content.Context;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
@@ -32,10 +34,17 @@
     private static final int TEST_NET_ID = 1;
     private static final WifiConfiguration TEST_WIFI_CONFIGURATION = new WifiConfiguration();
     private WifiManager mWifiManager;
+    private boolean mHasWifi;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mHasWifi = mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI);
+        if (!mHasWifi) {
+            return;
+        }
+
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         assertNotNull(mWifiManager);
     }
@@ -46,6 +55,10 @@
      *   {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
      */
     public void testGetWifiState() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.getWifiState();
             fail("WifiManager.getWifiState didn't throw SecurityException as expected");
@@ -60,6 +73,10 @@
      *   {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
      */
     public void testGetConfiguredNetworks() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.getConfiguredNetworks();
             fail("WifiManager.getConfiguredNetworks didn't throw SecurityException as expected");
@@ -74,6 +91,10 @@
      *   {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
      */
     public void testGetConnectionInfo() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.getConnectionInfo();
             fail("WifiManager.getConnectionInfo didn't throw SecurityException as expected");
@@ -88,6 +109,10 @@
      *   {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
      */
     public void testGetScanResults() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.getScanResults();
             fail("WifiManager.getScanResults didn't throw SecurityException as expected");
@@ -102,6 +127,10 @@
      *   {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
      */
     public void testGetDhcpInfo() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.getDhcpInfo();
             fail("WifiManager.getDhcpInfo didn't throw SecurityException as expected");
@@ -116,6 +145,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testDisconnect() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.disconnect();
             fail("WifiManager.disconnect didn't throw SecurityException as expected");
@@ -130,6 +163,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testReconnect() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.reconnect();
             fail("WifiManager.reconnect didn't throw SecurityException as expected");
@@ -144,6 +181,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testReassociate() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.reassociate();
             fail("WifiManager.reassociate didn't throw SecurityException as expected");
@@ -158,6 +199,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testAddNetwork() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.addNetwork(TEST_WIFI_CONFIGURATION);
             fail("WifiManager.addNetwork didn't throw SecurityException as expected");
@@ -172,6 +217,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testUpdateNetwork() {
+        if (!mHasWifi) {
+            return;
+        }
+
         TEST_WIFI_CONFIGURATION.networkId = 2;
 
         try {
@@ -188,6 +237,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testRemoveNetwork() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.removeNetwork(TEST_NET_ID);
             fail("WifiManager.removeNetwork didn't throw SecurityException as expected");
@@ -202,6 +255,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testEnableNetwork() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.enableNetwork(TEST_NET_ID, false);
             fail("WifiManager.enableNetwork didn't throw SecurityException as expected");
@@ -216,6 +273,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testDisableNetwork() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.disableNetwork(TEST_NET_ID);
             fail("WifiManager.disableNetwork didn't throw SecurityException as expected");
@@ -230,6 +291,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testPingSupplicant() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.pingSupplicant();
             fail("WifiManager.pingSupplicant didn't throw SecurityException as expected");
@@ -244,6 +309,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testStartScan() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.startScan();
             fail("WifiManager.startScan didn't throw SecurityException as expected");
@@ -258,6 +327,10 @@
      *   {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
      */
     public void testSetWifiEnabled() {
+        if (!mHasWifi) {
+            return;
+        }
+
         try {
             mWifiManager.setWifiEnabled(true);
             fail("WifiManager.setWifiEnabled didn't throw SecurityException as expected");
diff --git a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
index e4fa9c2..415a17e 100644
--- a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
@@ -57,13 +57,19 @@
 
 public class OneTimePermissionTest {
     private static final String APP_PKG_NAME = "android.permission.cts.appthatrequestpermission";
+    private static final String CUSTOM_CAMERA_PERM_APP_PKG_NAME =
+            "android.permission.cts.appthatrequestcustomcamerapermission";
     private static final String APK =
             "/data/local/tmp/cts/permissions/CtsAppThatRequestsOneTimePermission.apk";
+    private static final String CUSTOM_CAMERA_PERM_APK =
+            "/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk";
     private static final String EXTRA_FOREGROUND_SERVICE_LIFESPAN =
             "android.permission.cts.OneTimePermissionTest.EXTRA_FOREGROUND_SERVICE_LIFESPAN";
     private static final String EXTRA_FOREGROUND_SERVICE_STICKY =
             "android.permission.cts.OneTimePermissionTest.EXTRA_FOREGROUND_SERVICE_STICKY";
 
+    public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM";
+
     private static final long ONE_TIME_TIMEOUT_MILLIS = 5000;
     private static final long ONE_TIME_KILLED_DELAY_MILLIS = 5000;
     private static final long ONE_TIME_TIMER_LOWER_GRACE_PERIOD = 1000;
@@ -71,6 +77,7 @@
 
     private final Context mContext =
             InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private final PackageManager mPackageManager = mContext.getPackageManager();
     private final UiDevice mUiDevice =
             UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
     private final ActivityManager mActivityManager =
@@ -220,7 +227,7 @@
 
     private void assertGrantedState(String s, int permissionGranted, long timeoutMillis) {
         eventually(() -> Assert.assertEquals(s,
-                permissionGranted, mContext.getPackageManager()
+                permissionGranted, mPackageManager
                         .checkPermission(ACCESS_FINE_LOCATION, APP_PKG_NAME)), timeoutMillis);
     }
 
diff --git a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
index 3dc5f03..75da42f 100644
--- a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
@@ -39,8 +39,10 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
 @AppModeFull(reason = "Instant apps cannot read state of other packages.")
-public class RemovePermissionTest {
+public class RemovePermissionTest extends StsExtraBusinessLogicTestCase {
     private static final String APP_PKG_NAME_BASE =
             "android.permission.cts.revokepermissionwhenremoved";
     private static final String ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME =
diff --git a/tests/tests/permission/src/android/permission/cts/RevokeSawPermissionTest.kt b/tests/tests/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
new file mode 100644
index 0000000..f3f06de
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 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.permission.cts
+
+import android.content.pm.PackageManager
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.After
+import org.junit.Assert
+import org.junit.Test
+
+private val APP_PKG_NAME = "android.permission3.cts.usesystemalertwindowpermission"
+private val APK_22 = "/data/local/tmp/cts/permissions/" +
+        "CtsAppThatRequestsSystemAlertWindow22.apk"
+private val APK_23 = "/data/local/tmp/cts/permissions/" +
+        "CtsAppThatRequestsSystemAlertWindow23.apk"
+
+class RevokeSawPermissionTest {
+
+    fun installApp(apk: String) {
+        SystemUtil.runShellCommand("pm install -r $apk")
+    }
+
+    @After
+    fun uninstallApp() {
+        SystemUtil.runShellCommand("pm uninstall $APP_PKG_NAME")
+    }
+
+    @AsbSecurityTest(cveBugId = [221040577L])
+    @Test
+    fun testPre23AppsWithSystemAlertWindowGetDeniedOnUpgrade() {
+        installApp(APK_22)
+        assertAppHasPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, true)
+        installApp(APK_23)
+        assertAppHasPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, false)
+    }
+
+    private fun assertAppHasPermission(permissionName: String, expectPermission: Boolean) {
+        Assert.assertEquals(
+            if (expectPermission) {
+                PackageManager.PERMISSION_GRANTED
+            } else {
+                PackageManager.PERMISSION_DENIED
+            },
+            InstrumentationRegistry.getInstrumentation().getTargetContext().packageManager
+                .checkPermission(permissionName, APP_PKG_NAME)
+        )
+    }
+}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 19a9ef3..89493fe 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -2990,6 +2990,12 @@
     <permission android:name="android.permission.CREATE_USERS"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi @hide Allows an application to set user association
+         with a certain subscription. Used by Enterprise to associate a
+         subscription with a work or personal profile. -->
+    <permission android:name="android.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION"
+                android:protectionLevel="signature" />
+
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to query users on the
          device. -->
     <permission android:name="android.permission.QUERY_USERS"
@@ -6027,7 +6033,7 @@
     <!-- @SystemApi Allows to access all app shortcuts.
          @hide -->
     <permission android:name="android.permission.ACCESS_SHORTCUTS"
-        android:protectionLevel="signature|role" />
+        android:protectionLevel="signature|role|recents" />
 
     <!-- @SystemApi Allows unlimited calls to shortcut mutation APIs.
          @hide -->
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index a4eb89f..ac9c97a 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -20,8 +20,6 @@
 import static android.content.pm.PermissionInfo.PROTECTION_MASK_BASE;
 import static android.os.Build.VERSION.SECURITY_PATCH;
 
-import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
-
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.Manifest;
@@ -31,7 +29,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
-import android.os.Build;
 import android.os.Process;
 import android.os.SystemProperties;
 import android.platform.test.annotations.AppModeFull;
@@ -77,9 +74,6 @@
     private static final String SET_UNRESTRICTED_GESTURE_EXCLUSION
             = "android.permission.SET_UNRESTRICTED_GESTURE_EXCLUSION";
 
-    private static final String BIND_OEM_CAR_SERVICE =
-            "android.car.permission.BIND_OEM_CAR_SERVICE";
-
     private static final String ACCESS_SHORTCUTS_PERMISSION = "android.permission.ACCESS_SHORTCUTS";
     private static final String BIND_QUICK_SETTINGS_TILE =
             "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -226,11 +220,7 @@
             final int expectedProtectionFlags =
                     expectedPermission.protectionLevel & ~PROTECTION_MASK_BASE;
             final int declaredProtectionFlags = declaredPermission.getProtectionFlags();
-            if (expectedProtectionFlags != declaredProtectionFlags
-                    && !shouldAllowProtectionFlagsChange(
-                            expectedPermissionName,
-                            expectedProtectionFlags,
-                            declaredProtectionFlags)) {
+            if (expectedProtectionFlags != declaredProtectionFlags) {
                 offendingList.add(
                         String.format(
                                 "Permission %s invalid enforced protection %x, expected %x",
@@ -526,28 +516,11 @@
                 return parseDate(SECURITY_PATCH).before(MANAGE_COMPANION_DEVICES_PATCH_DATE);
             case SET_UNRESTRICTED_GESTURE_EXCLUSION:
                 return true;
-            case BIND_OEM_CAR_SERVICE:
-                return shoudldSkipBindOemCarService();
             default:
                 return false;
         }
     }
 
-    /**
-     * check should be skipped only for T and T-QPR1
-     */
-    private boolean shoudldSkipBindOemCarService() {
-        if (Build.VERSION.SDK_INT > 33) {
-            return false;
-        }
-        String output = runShellCommand("dumpsys car_service --version");
-        if (output.contains("Car API minor: 0") || output.contains("Car API minor: 1")) {
-            return true;
-        }
-
-        return false;
-    }
-
     private static boolean shouldAllowProtectionFlagsChange(
             String permissionName, int expectedFlags, int actualFlags) {
         return (ACCESS_SHORTCUTS_PERMISSION.equals(permissionName)
diff --git a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
index 104655f..3c8a35c 100644
--- a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
+++ b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
@@ -22,6 +22,7 @@
 import android.app.NotificationManager
 import android.content.Intent
 import android.content.pm.PackageManager
+import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
 
@@ -43,9 +44,13 @@
     lateinit var notificationManager: NotificationManager
     var launchActivityOnSecondResume = false
     var isFirstResume = true
+    var windowHasFocus = false
+    var pendingCreateChannel = false
     val handler = Handler(Looper.getMainLooper())
 
-    override fun onStart() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
         val launchSecondActivity = intent.getBooleanExtra(EXTRA_START_SECOND_ACTIVITY, false)
         notificationManager = baseContext.getSystemService(NotificationManager::class.java)!!
         if (intent.getBooleanExtra(EXTRA_START_SECOND_APP, false)) {
@@ -73,7 +78,6 @@
             }
         }
 
-
         if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
             requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
         } else if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED, false)) {
@@ -85,8 +89,6 @@
         if (intent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
             requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
         }
-
-        super.onStart()
     }
 
     private fun launchSecondActivity() {
@@ -99,7 +101,21 @@
                             }, LONG_DELAY_MS)
     }
 
+    override fun onWindowFocusChanged(hasFocus: Boolean) {
+        windowHasFocus = hasFocus
+        if (windowHasFocus && pendingCreateChannel) {
+            pendingCreateChannel = false
+            createChannel()
+        }
+    }
+
     private fun createChannel() {
+        // Wait until window has focus so the permission prompt can be displayed
+        if (!windowHasFocus) {
+            pendingCreateChannel = true
+            return
+        }
+
         if (notificationManager.getNotificationChannel(CHANNEL_ID_31) == null) {
             notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID_31,
                 "Foreground Services", NotificationManager.IMPORTANCE_HIGH))
diff --git a/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp b/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp
index 876b68f..293897c 100644
--- a/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp
+++ b/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp
@@ -23,7 +23,7 @@
     defaults: ["mts-target-sdk-version-current"],
     // TODO ntmyren: change to "33" when it is a valid target
     sdk_version: "test_current",
-    min_sdk_version: "test_current",
+    min_sdk_version: "current",
 
     static_libs: [
         "kotlin-stdlib",
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index d55e3a4..dee76c2 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -194,6 +194,7 @@
     fun notificationPromptShownForSubsequentStartsIfTaskStartWasLauncher() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(startSecondActivity = true)
+        waitFindObject(By.res(ALLOW_BUTTON))
         pressBack()
         clickPermissionRequestAllowButton()
     }
diff --git a/tests/tests/permission4/Android.bp b/tests/tests/permission4/Android.bp
index 2ff3bee..72908e2 100644
--- a/tests/tests/permission4/Android.bp
+++ b/tests/tests/permission4/Android.bp
@@ -34,6 +34,7 @@
     ],
     test_suites: [
         "cts",
+        "sts",
         "vts10",
         "general-tests",
         "mts-permission",
diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp b/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp
index a7e0ab6..9dc1b45 100644
--- a/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp
+++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp
@@ -25,6 +25,7 @@
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
+        "sts",
         "vts10",
         "general-tests",
     ],
@@ -36,6 +37,6 @@
     ],
 
     srcs: [
-        "src/**/*.kt"
+        "src/**/*.kt",
     ],
 }
diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt b/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
index 659f228..f7a5c31 100644
--- a/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
+++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
@@ -42,6 +42,7 @@
 private const val USE_CAMERA = "use_camera"
 private const val USE_MICROPHONE = "use_microphone"
 private const val USE_HOTWORD = "use_hotword"
+private const val FINISH_EARLY = "finish_early"
 private const val USE_DURATION_MS = 10000L
 private const val SAMPLE_RATE_HZ = 44100
 
@@ -62,12 +63,14 @@
     private var runMic = false
     private var hotwordFinished = false
     private var runHotword = false
+    private var finishEarly = false
 
     override fun onStart() {
         super.onStart()
         runCamera = intent.getBooleanExtra(USE_CAMERA, false)
         runMic = intent.getBooleanExtra(USE_MICROPHONE, false)
         runHotword = intent.getBooleanExtra(USE_HOTWORD, false)
+        finishEarly = intent.getBooleanExtra(FINISH_EARLY, false)
 
         if (runMic) {
             useMic()
@@ -193,6 +196,11 @@
             AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT)
         recorder = AudioRecord(MIC, SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT, minSize)
         recorder?.startRecording()
+        if (finishEarly) {
+            appOpsManager = getSystemService(AppOpsManager::class.java)
+            appOpsManager?.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO, Process.myUid(), packageName)
+            return
+        }
         GlobalScope.launch {
             delay(USE_DURATION_MS)
             micFinished = true
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 48aef89..2b6ce5f 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -27,6 +27,7 @@
 import android.os.Build
 import android.os.Process
 import android.permission.PermissionManager
+import android.platform.test.annotations.AsbSecurityTest
 import android.provider.DeviceConfig
 import android.provider.Settings
 import android.server.wm.WindowManagerStateHelper
@@ -60,6 +61,7 @@
 private const val USE_CAMERA = "use_camera"
 private const val USE_MICROPHONE = "use_microphone"
 private const val USE_HOTWORD = "use_hotword"
+private const val FINISH_EARLY = "finish_early"
 private const val INTENT_ACTION = "test.action.USE_CAMERA_OR_MIC"
 private const val PRIVACY_CHIP_ID = "com.android.systemui:id/privacy_chip"
 private const val CAR_MIC_PRIVACY_CHIP_ID = "com.android.systemui:id/mic_privacy_chip"
@@ -167,11 +169,17 @@
         Thread.sleep(DELAY_MILLIS)
     }
 
-    private fun openApp(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) {
+    private fun openApp(
+        useMic: Boolean,
+        useCamera: Boolean,
+        useHotword: Boolean,
+        finishEarly: Boolean = false
+    ) {
         context.startActivity(Intent(INTENT_ACTION).apply {
             putExtra(USE_CAMERA, useCamera)
             putExtra(USE_MICROPHONE, useMic)
             putExtra(USE_HOTWORD, useHotword)
+            putExtra(FINISH_EARLY, finishEarly)
             addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
         })
     }
@@ -193,6 +201,13 @@
     }
 
     @Test
+    @AsbSecurityTest(cveBugId = [242537498])
+    fun testMicIndicatorWithManualFinishOpStillShows() {
+        changeSafetyCenterFlag(false.toString())
+        testCameraAndMicIndicator(useMic = true, useCamera = false, finishEarly = true)
+    }
+
+    @Test
     fun testHotwordIndicatorBehavior() {
         changeSafetyCenterFlag(false.toString())
         testCameraAndMicIndicator(useMic = false, useCamera = false, useHotword = true)
@@ -272,12 +287,13 @@
         useCamera: Boolean,
         useHotword: Boolean = false,
         chainUsage: Boolean = false,
-        safetyCenterEnabled: Boolean = false
+        safetyCenterEnabled: Boolean = false,
+        finishEarly: Boolean = false
     ) {
         // If camera is not available skip the test
         assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
         var chainAttribution: AttributionSource? = null
-        openApp(useMic, useCamera, useHotword)
+        openApp(useMic, useCamera, useHotword, finishEarly)
         try {
             eventually {
                 val appView = uiDevice.findObject(By.textContains(APP_LABEL))
@@ -292,20 +308,23 @@
                 }
             }
 
-            if (isTv) {
-                assertTvIndicatorsShown(useMic, useCamera, useHotword)
-            } else if (isCar) {
-                assertCarIndicatorsShown(useMic, useCamera, useHotword, chainUsage)
-            } else {
-                // Hotword gets remapped to RECORD_AUDIO on handheld, so handheld should show a mic
-                // indicator
+            if (!isTv && !isCar) {
                 uiDevice.openQuickSettings()
-                assertPrivacyChipAndIndicatorsPresent(
-                    useMic,
-                    useCamera,
-                    chainUsage,
-                    safetyCenterEnabled
-                )
+            }
+            assertIndicatorsShown(useMic, useCamera, useHotword, chainUsage,
+                safetyCenterEnabled)
+
+            if (finishEarly) {
+                // Assert that the indicator doesn't go away
+                val indicatorGoneException: Exception? = try {
+                    eventually {
+                        assertIndicatorsShown(false, false, false)
+                    }
+                    null
+                } catch (e: Exception) {
+                    e
+                }
+                assertNotNull("Expected the indicator to be present", indicatorGoneException)
             }
         } finally {
             if (chainAttribution != null) {
@@ -315,8 +334,25 @@
         }
     }
 
+    private fun assertIndicatorsShown(
+        useMic: Boolean,
+        useCamera: Boolean,
+        useHotword: Boolean = false,
+        chainUsage: Boolean = false,
+        safetyCenterEnabled: Boolean = false,
+        ) {
+        if (isTv) {
+            assertTvIndicatorsShown(useMic, useCamera, useHotword)
+        } else if (isCar) {
+            assertCarIndicatorsShown(useMic, useCamera, useHotword, chainUsage)
+        } else {
+            assertPrivacyChipAndIndicatorsPresent(useMic, useCamera, chainUsage,
+                safetyCenterEnabled)
+        }
+    }
+
     private fun assertTvIndicatorsShown(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) {
-        if (useMic || useHotword) {
+        if (useMic || useHotword || (!useMic && !useCamera && !useHotword)) {
             val found = WindowManagerStateHelper()
                 .waitFor("Waiting for the mic indicator window to come up") {
                     it.containsWindow(TV_MIC_INDICATOR_WINDOW_TITLE) &&
@@ -351,7 +387,7 @@
                 assertNotNull("Did not find camera chip", cameraPrivacyChip)
                 // Click to chip to show the panel.
                 cameraPrivacyChip.click()
-            } else if (useHotword) {
+            } else {
                 assertNull("Found mic chip, but did not expect to", micPrivacyChip)
                 assertNull("Found camera chip, but did not expect to", cameraPrivacyChip)
             }
@@ -363,18 +399,7 @@
                 assertChainMicAndOtherCameraUsed(false)
                 return@eventually
             }
-            if (useHotword) {
-                // There should be no privacy panel when using hot word
-                val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
-                assertFalse("View with text $micLabel found, but did not expect to",
-                    micLabelView.exists())
-                val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
-                assertFalse("View with text $cameraLabel found, but did not expect to",
-                    cameraLabelView.exists())
-                val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
-                assertFalse("View with text $APP_LABEL found, but did not expect to",
-                    appView.exists())
-            } else if (useMic) {
+            if (useMic) {
                 // There should be a mic privacy panel after mic privacy chip is clicked
                 val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
                 assertTrue("View with text $micLabel not found", micLabelView.exists())
@@ -386,6 +411,17 @@
                 assertTrue("View with text $cameraLabel not found", cameraLabelView.exists())
                 val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
                 assertTrue("View with text $APP_LABEL not found", appView.exists())
+            } else {
+                // There should be no privacy panel when using hot word
+                val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
+                assertFalse("View with text $micLabel found, but did not expect to",
+                    micLabelView.exists())
+                val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
+                assertFalse("View with text $cameraLabel found, but did not expect to",
+                    cameraLabelView.exists())
+                val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+                assertFalse("View with text $APP_LABEL found, but did not expect to",
+                    appView.exists())
             }
         }
     }
@@ -397,7 +433,7 @@
         safetyCenterEnabled: Boolean = false
     ) {
         // Ensure the privacy chip is present (or not)
-        val chipFound = isChipPresent()
+        val chipFound = isChipPresent(useMic || useCamera)
         if (useMic || useCamera) {
             assertTrue("Did not find chip", chipFound)
         } else { // hotword
@@ -425,6 +461,7 @@
                     uiDevice.findObjects(By.res(SAFETY_CENTER_ITEM_ID)).size > 0)
             }
         }
+        uiDevice.pressBack()
     }
 
     private fun createChainAttribution(): AttributionSource? {
@@ -463,13 +500,15 @@
         assertEquals("Expected only one shell view", 1, shellView.size)
     }
 
-    private fun isChipPresent(): Boolean {
+    private fun isChipPresent(clickChip: Boolean): Boolean {
         var chipFound = false
         try {
             eventually {
                 val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
                 assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
-                privacyChip.click()
+                if (clickChip) {
+                    privacyChip.click()
+                }
                 chipFound = true
             }
         } catch (e: Exception) {
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
index 8d833ae..285e3f5 100644
--- a/tests/tests/provider/Android.bp
+++ b/tests/tests/provider/Android.bp
@@ -32,6 +32,7 @@
         "mockito-target-minus-junit4",
         // TODO: remove testng once Android migrates to JUnit 4.12, which provides assertThrows
         "testng",
+        "sts-device-util",
     ],
 
     jni_libs: [
diff --git a/tests/tests/provider/TEST_MAPPING b/tests/tests/provider/TEST_MAPPING
new file mode 100644
index 0000000..d99f6bb
--- /dev/null
+++ b/tests/tests/provider/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsProviderTestCases",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java b/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java
index eaddc09..ce31901 100644
--- a/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java
@@ -31,6 +31,7 @@
 
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index 5ad3cf5..48f55be 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -279,7 +279,8 @@
                     // file creation fails, we ignore and let `dd` command create it instead.
                 }
 
-                executeShellCommand(String.format("dd bs=1 if=%s skip=%d count=%d of=%s",
+                executeShellCommand(String.format(
+                        "dd bs=4K if=%s iflag=skip_bytes,count_bytes skip=%d count=%d of=%s",
                         source.getAbsolutePath(), skip, count, file.getAbsolutePath()));
 
                 // Force sync to try updating other views
diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
index 2f5155a..9c603f8 100644
--- a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
+++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
@@ -40,8 +40,10 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
 @RunWith(AndroidJUnit4.class)
-public class Settings_SystemTest {
+public class Settings_SystemTest extends StsExtraBusinessLogicTestCase {
     private static final String INT_FIELD = System.END_BUTTON_BEHAVIOR;
     private static final String LONG_FIELD = System.SCREEN_OFF_TIMEOUT;
     private static final String FLOAT_FIELD = System.FONT_SCALE;
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 0cf3dd5..56d02d2 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -33,6 +33,7 @@
         "compatibility-common-util-devicesidelib",
         "guava",
         "platform-test-annotations",
+        "permission-test-util-lib",
         "sts-device-util",
         "hamcrest-library",
         "NeneInternal",
@@ -80,6 +81,17 @@
         ":CtsDeviceInfo",
         ":RolePermissionOverrideTestApp",
         ":SplitBluetoothPermissionTestApp",
+        ":CtsPermissionBackupAppCert1",
+        ":CtsPermissionBackupAppCert1Dup",
+        ":CtsPermissionBackupAppCert2",
+        ":CtsPermissionBackupAppCert3",
+        ":CtsPermissionBackupAppCert4",
+        ":CtsPermissionBackupAppCert12",
+        ":CtsPermissionBackupAppCert12Dup",
+        ":CtsPermissionBackupAppCert34",
+        ":CtsPermissionBackupAppCert123",
+        ":CtsPermissionBackupAppCert4History124",
+        ":CtsAppThatRequestCustomCameraPermission",
     ],
 }
 
@@ -89,6 +101,95 @@
     manifest: "testdata/packageinstallertestapp.xml",
 }
 
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert1",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-1",
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert1Dup",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-1",
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert2",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-2",
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert3",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-3",
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert4",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-4",
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert12",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-1",
+    additional_certificates: [
+        ":permission-test-cert-2",
+    ],
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert12Dup",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-1",
+    additional_certificates: [
+        ":permission-test-cert-2",
+    ],
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert34",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-3",
+    additional_certificates: [
+        ":permission-test-cert-4",
+    ],
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert123",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-1",
+    additional_certificates: [
+        ":permission-test-cert-2",
+        ":permission-test-cert-3",
+    ],
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+    name: "CtsPermissionBackupAppCert4History124",
+    min_sdk_version: "30",
+    certificate: ":permission-test-cert-4",
+    additional_certificates: [
+        ":permission-test-cert-1",
+
+    ],
+    rotationMinSdkVersion: "30",
+    lineage: ":permission-test-cert-with-rotation-history",
+    manifest: "testdata/permissionbackuptestapp/AndroidManifest.xml",
+}
+
 android_app_certificate {
     name: "security_cts_test_certificate",
     certificate: "security_cts_test_cert",
@@ -98,3 +199,30 @@
     name: "RolePermissionOverrideTestApp",
     manifest: "testdata/rolepermissionoverridetestapp.xml",
 }
+
+android_app_certificate {
+    name: "permission-test-cert-1",
+    certificate: "test-cert-1",
+}
+
+android_app_certificate {
+    name: "permission-test-cert-2",
+    certificate: "test-cert-2",
+}
+
+android_app_certificate {
+    name: "permission-test-cert-3",
+    certificate: "test-cert-3",
+}
+
+android_app_certificate {
+    name: "permission-test-cert-4",
+    certificate: "test-cert-4",
+}
+
+filegroup {
+    name: "permission-test-cert-with-rotation-history",
+    srcs: [
+        "test-cert-with-1-2-4-in-rotation-history",
+    ],
+}
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index afdddfd..db49773 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -18,6 +18,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="android.security.cts">
 
+    <permission-tree android:name="com.android.cts"/>
+
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
@@ -232,6 +234,26 @@
                 android:resource="@xml/syncadapter" />
         </service>
 
+        <activity android:name="android.security.cts.CVE_2021_0642.PocActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="CVE_2021_0642_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.security.cts.CVE_2021_0642.SecondActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="CVE_2021_0642_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 9bd5eb7..6a6dc92 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -52,6 +52,17 @@
         <option name="cleanup" value="true" />
         <option name="push" value="RolePermissionOverrideTestApp.apk->/data/local/tmp/cts/security/RolePermissionOverrideTestApp.apk" />
         <option name="push" value="SplitBluetoothPermissionTestApp.apk->/data/local/tmp/cts/security/SplitBluetoothPermissionTestApp.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert1.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert1.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert1Dup.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert1Dup.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert2.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert2.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert3.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert3.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert4.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert4.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert12.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert12.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert12Dup.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert12Dup.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert123.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert123.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert34.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert34.apk" />
+        <option name="push" value="CtsPermissionBackupAppCert4History124.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert4History124.apk" />
+        <option name="push" value="CtsAppThatRequestCustomCameraPermission.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
@@ -61,4 +72,9 @@
         <option name="test-timeout" value="900000" />
         <option name="hidden-api-checks" value="false" />
     </test>
+
+    <target_preparer class="android.cts.backup.BackupPreparer">
+        <option name="enable-backup-if-needed" value="true" />
+        <option name="select-local-transport" value="true" />
+    </target_preparer>
 </configuration>
diff --git a/tests/tests/gwp-asan/enabled/Android.bp b/tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp
similarity index 60%
copy from tests/tests/gwp-asan/enabled/Android.bp
copy to tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp
index a78598e..873733d 100644
--- a/tests/tests/gwp-asan/enabled/Android.bp
+++ b/tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp
@@ -1,4 +1,5 @@
-// Copyright (C) 2020 The Android Open Source Project
+//
+// Copyright (C) 2022 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.
@@ -11,32 +12,26 @@
 // 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"],
 }
 
-android_test {
-    name: "CtsGwpAsanTestCases",
-    defaults: ["cts_defaults"],
-    compile_multilib: "both",
-    // When built, explicitly put it in the data partition.
+android_test_helper_app {
+    name: "CtsAppThatRequestCustomCameraPermission",
+    defaults: [
+        "cts_defaults",
+        "mts-target-sdk-version-current",
+    ],
+    min_sdk_version: "30",
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
+        "mts",
+        "sts",
         "general-tests",
     ],
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
-    static_libs: [
-        "ctstestrunner-axt",
-        "androidx.test.rules",
-        "androidx.test.core",
-        "androidx.test.ext.junit",
-    ],
     srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    use_embedded_native_libs: false,
+    resource_dirs: ["res"],
 }
diff --git a/tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml b/tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml
new file mode 100644
index 0000000..a8143a7
--- /dev/null
+++ b/tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission.cts.appthatrequestcustomcamerapermission">
+
+    <permission android:name="appthatrequestcustomcamerapermission.CUSTOM"
+                android:permissionGroup="android.permission-group.CAMERA"
+                android:label="@string/permlab_custom"
+                android:description="@string/permdesc_custom"
+                android:protectionLevel="dangerous" />
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="appthatrequestcustomcamerapermission.CUSTOM" />
+
+    <application>
+        <activity android:name=".RequestCameraPermission" android:exported="true"
+                  android:visibleToInstantApps="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml
similarity index 77%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml
index 1a335c7..8de4638 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml
@@ -1,4 +1,4 @@
-/*
+<!--
  * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,11 +12,9 @@
  * 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_0642;
-
-import android.app.Activity;
-
-public class PocActivity extends Activity {
-}
+<resources>
+    <string name="permlab_custom">Custom</string>
+    <string name="permdesc_custom">allows bypassing one-time permissions</string>
+</resources>
\ No newline at end of file
diff --git a/tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java b/tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
new file mode 100644
index 0000000..4bbeb53
--- /dev/null
+++ b/tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 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.permission.cts.appthatrequestcustomcamerapermission;
+
+import static android.Manifest.permission.CAMERA;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+public class RequestCameraPermission extends Activity {
+
+    private static final String LOG_TAG = RequestCameraPermission.class.getSimpleName();
+
+    public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM";
+    private Handler mHandler;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        boolean cameraGranted =
+                checkSelfPermission(CAMERA) == PERMISSION_GRANTED;
+        boolean customGranted =
+                checkSelfPermission(CUSTOM_PERMISSION) == PERMISSION_GRANTED;
+
+        mHandler = new Handler(getMainLooper());
+
+        if (!cameraGranted && !customGranted) {
+            requestPermissions(new String[] {CAMERA}, 0);
+        } else {
+            Log.e(LOG_TAG, "Test app was opened with cameraGranted=" + cameraGranted
+                    + " and customGranted=" + customGranted);
+        }
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions,
+            int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+        if (requestCode == 0) {
+            if (grantResults[0] != PERMISSION_GRANTED) {
+                Log.e(LOG_TAG, "permission wasn't granted, this test should fail,"
+                        + " leaving test app open.");
+            } else {
+                // Delayed request because the immediate request might show the dialog again
+                mHandler.postDelayed(() ->
+                        requestPermissions(new String[] {CUSTOM_PERMISSION}, 1), 500);
+            }
+        } else if (requestCode == 1) {
+            if (grantResults[0] != PERMISSION_GRANTED) {
+                Log.e(LOG_TAG, "permission wasn't granted, this test should fail,"
+                        + " leaving test app open.");
+            } else {
+                // Here camera was granted and custom was autogranted, exit process and let test
+                // verify both are revoked.
+
+                // Delayed exit because b/254675301
+                mHandler.postDelayed(() -> System.exit(0), 1000);
+            }
+        }
+
+    }
+}
diff --git a/tests/tests/security/native/encryption/Android.bp b/tests/tests/security/native/encryption/Android.bp
index d95cc83..ebbd1f8 100644
--- a/tests/tests/security/native/encryption/Android.bp
+++ b/tests/tests/security/native/encryption/Android.bp
@@ -7,6 +7,7 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-Wno-error=#warnings",
     ],
     srcs: [
         "FileBasedEncryptionPolicyTest.cpp",
diff --git a/tests/tests/security/res/raw/cve_2022_25669.3gp b/tests/tests/security/res/raw/cve_2022_25669.3gp
new file mode 100644
index 0000000..f5ba05a
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_25669.3gp
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_33234.mkv b/tests/tests/security/res/raw/cve_2022_33234.mkv
new file mode 100644
index 0000000..752e3cd
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_33234.mkv
Binary files differ
diff --git a/tests/tests/security/res/values/strings.xml b/tests/tests/security/res/values/strings.xml
new file mode 100644
index 0000000..73dd5b9
--- /dev/null
+++ b/tests/tests/security/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <!-- CVE-2021-0642 -->
+    <string name="cve_2021_0642_action">CVE_2021_0642_ACTION</string>
+    <string name="cve_2021_0642_pkgPhone">com.android.phone</string>
+    <string name="cve_2021_0642_failMsg">Device is vulnerable to b/185126149 !!</string>
+    <string name="cve_2021_0642_msgResolveErrorVoicemail">The intent with action
+    ACTION_CONFIGURE_VOICEMAIL should resolve to either ResolverActivity or
+    VoicemailSettingsActivity</string>
+    <string name="cve_2021_0642_msgResolveErrorPocAction">The intent with action
+    CVE_2021_0642_ACTION should not be resolved to test package</string>
+</resources>
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index 397c012..7bb74ff 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -18,29 +18,25 @@
 
 import static org.junit.Assert.fail;
 
-import android.app.Activity;
+import android.annotation.SuppressLint;
 import android.os.BaseBundle;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.view.AbsSavedState;
 import android.view.View;
-import android.view.View.BaseSavedState;
-import android.annotation.SuppressLint;
+
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
 
-import java.io.InputStream;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.lang.reflect.Field;
 import java.util.Random;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-import android.security.cts.R;
-import android.platform.test.annotations.AsbSecurityTest;
-
 @RunWith(AndroidJUnit4.class)
 public class AmbiguousBundlesTest extends StsExtraBusinessLogicTestCase {
 
@@ -601,6 +597,95 @@
         testAmbiguator(ambiguator);
     }
 
+    /*
+     * b/240138294
+     */
+    @AsbSecurityTest(cveBugId = 240138294)
+    @Test
+    public void test_lazyValueNegativeLength() throws Exception {
+        Ambiguator ambiguator = new Ambiguator() {
+            @Override
+            public Bundle make(Bundle preReSerialize, Bundle postReSerialize) {
+                // Find key that has hash below everything else
+                Random random = new Random(1234);
+                int minHash = 0;
+                for (String s : preReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+                for (String s : postReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+
+                String negativePrefix, positivePrefix;
+                // When read as value, jump back to the start of the header (8 bytes)
+                negativePrefix = getStringEncodingInt(-8);
+                // Size of the malicious bundle before the 'cmd' key
+                positivePrefix = getStringEncodingInt(48);
+
+                String key1, key2, key3;
+                int key1Hash, key2Hash, key3Hash;
+
+                do {
+                    key1 = randomString(random);
+                    // 16 characters total, will be read as type parcelable array when
+                    // read as value
+                    key2 = negativePrefix + randomString(random, 14);
+                    key3 = positivePrefix + randomString(random, 14);
+                    key1Hash = key1.hashCode();
+                    key2Hash = key3.hashCode(); // 2 and 3 are swapped
+                    key3Hash = key2.hashCode();
+                } while (!(key1Hash < key2Hash && key2Hash < key3Hash && key3Hash < minHash));
+
+                // Pad bundles - ensures keys are in right hash order
+                padBundle(postReSerialize, preReSerialize.size() + 2, minHash, random);
+                padBundle(preReSerialize, postReSerialize.size() - 2, minHash, random);
+
+                // Write bundle
+                Parcel parcel = Parcel.obtain();
+
+                int sizePosition = parcel.dataPosition();
+                parcel.writeInt(0);
+                parcel.writeInt(BUNDLE_MAGIC_NATIVE);
+                int startPosition = parcel.dataPosition();
+
+                parcel.writeInt(preReSerialize.size() + 3); // Num key-value pairs
+
+                parcel.writeString(key1); // Key 1
+                parcel.writeString(key2); // Value 1/Key 2
+                parcel.writeInt(VAL_NULL);
+                parcel.writeString(key3);
+                parcel.writeInt(VAL_BUNDLE);
+                parcel.writeBundle(postReSerialize); // Value 3
+
+                // Data from preReSerialize bundle
+                writeBundleSkippingHeaders(parcel, preReSerialize);
+
+                // Fix up bundle size
+                int bundleDataSize = parcel.dataPosition() - startPosition;
+                parcel.setDataPosition(sizePosition);
+                parcel.writeInt(bundleDataSize);
+
+                parcel.setDataPosition(0);
+                Bundle bundle = parcel.readBundle();
+                parcel.recycle();
+                return bundle;
+            }
+
+            private String getStringEncodingInt(int i) {
+                Parcel parcel = Parcel.obtain();
+                parcel.writeInt(2);
+                parcel.writeInt(i);
+                parcel.writeInt(0);
+                parcel.setDataPosition(0);
+                String s = parcel.readString();
+                parcel.recycle();
+                return s;
+            }
+        };
+
+        testAmbiguator(ambiguator);
+    }
+
     private void testAmbiguator(Ambiguator ambiguator) {
         Bundle bundle;
         Bundle verifyMe = new Bundle();
@@ -653,6 +738,7 @@
         protected static final int PROCSTATS_SPARSE_MAPPING_TABLE_ARRAY_SIZE = 4096;
 
         protected static final int BUNDLE_MAGIC = 0x4C444E42;
+        protected static final int BUNDLE_MAGIC_NATIVE = 0x4C444E44; // 'B' 'N' 'D' 'N'
         protected static final int INNER_BUNDLE_PADDING = 1;
 
         protected Field parcelledDataField;
@@ -711,8 +797,12 @@
         }
 
         protected static String randomString(Random random) {
+            return randomString(random, 6);
+        }
+
+        protected static String randomString(Random random, int len) {
             StringBuilder b = new StringBuilder();
-            for (int i = 0; i < 6; i++) {
+            for (int i = 0; i < len; i++) {
                 b.append((char)(' ' + random.nextInt('~' - ' ' + 1)));
             }
             return b.toString();
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java
new file mode 100644
index 0000000..5314ae8
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 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_0642;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.security.cts.R;
+import android.telephony.TelephonyManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0642 extends StsExtraBusinessLogicTestCase {
+
+    // b/185126149
+    // Vulnerable app    : TeleService.apk
+    // Vulnerable module : com.android.phone
+    // Is Play managed   : No
+    @AsbSecurityTest(cveBugId = 185126149)
+    @Test
+    public void testCVE_2021_0642() {
+        try {
+            // This test requires the device to have Telephony feature.
+            Context context = getInstrumentation().getTargetContext();
+            PackageManager pm = context.getPackageManager();
+            assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+
+            // Get ResolverActivity's name and package name
+            Intent customIntent = new Intent(context.getString(R.string.cve_2021_0642_action));
+            ResolveInfo riCustomAction =
+                    pm.resolveActivity(customIntent, PackageManager.MATCH_DEFAULT_ONLY);
+            assumeTrue(context.getString(R.string.cve_2021_0642_msgResolveErrorPocAction),
+                    !riCustomAction.activityInfo.packageName.equals(context.getPackageName()));
+            final String resolverPkgName = riCustomAction.activityInfo.packageName;
+            final String resolverActivityName = riCustomAction.activityInfo.name;
+
+            // Resolving intent with action "ACTION_CONFIGURE_VOICEMAIL"
+            Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
+            ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+            final String resolvedPkgName = ri.activityInfo.packageName;
+            final String resolvedActivityName = ri.activityInfo.name;
+
+            // Check if intent resolves to either VoicemailActivity or ResolverActivity
+            boolean isVoicemailActivity =
+                    resolvedPkgName.equals(context.getString(R.string.cve_2021_0642_pkgPhone));
+            boolean isResolverActivity = resolvedPkgName.equals(resolverPkgName)
+                    && resolvedActivityName.equals(resolverActivityName);
+
+            assumeTrue(context.getString(R.string.cve_2021_0642_msgResolveErrorVoicemail),
+                    isVoicemailActivity || isResolverActivity);
+
+            // If vulnerability is present, the intent with action ACTION_CONFIGURE_VOICEMAIL
+            // would resolve to the IntentResolver i.e. ResolverActivity, the test would fail in
+            // this case.
+            assertFalse(context.getString(R.string.cve_2021_0642_failMsg), isResolverActivity);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
similarity index 93%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
rename to tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
index 1a335c7..ae73b01 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0642;
 
 import android.app.Activity;
 
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
similarity index 87%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
index 1a335c7..4c0caee 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0642;
 
 import android.app.Activity;
 
-public class PocActivity extends Activity {
+public class SecondActivity extends Activity {
 }
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java b/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java
index 1bf6a78..35d576e 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java
@@ -66,7 +66,7 @@
         }
     }
 
-    @AsbSecurityTest(cveBugId = 238477311)
+    @AsbSecurityTest(cveBugId = 238377411)
     @Test
     public void testDeviceAdminAppRestricted() {
         try {
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20456.java b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java
new file mode 100644
index 0000000..2643433
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2022 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 static android.app.NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.AutomaticZenRule;
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+// This CTS test has been created taking reference from the tests present in
+// frameworks/base/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20456 extends StsExtraBusinessLogicTestCase {
+    private static final int INPUT_STRING_LENGTH = 2000; // 2 * 'MAX_STRING_LENGTH'
+    private static final String CLASS_NAME = "className";
+    private static final String PACKAGE_NAME = "packageName";
+    private static final String URI_STRING = "condition://android";
+    private static final String ZEN_RULE_NAME = "ZenRuleName";
+    private ComponentName mComponentNameWithLongFields;
+    private ComponentName mValidComponentName;
+    private String mLongString;
+    private Uri mLongUri;
+    private Uri mValidUri;
+    private List<String> mViolations;
+
+    private void checkFields(AutomaticZenRule rule, boolean ownerFlag, boolean configActivityFlag,
+            String tag) {
+        // Check all fields
+        if (INPUT_STRING_LENGTH <= rule.getName().length()) {
+            mViolations.add(tag + "input string length <= rule name length");
+        }
+        if (mLongUri.toString().length() <= rule.getConditionId().toString().length()) {
+            mViolations.add(tag + "input uri length <= rule conditionId length");
+        }
+        if (ownerFlag) {
+            if (INPUT_STRING_LENGTH <= rule.getOwner().getPackageName().length()) {
+                mViolations.add(tag + "input string length <= rule owner package name length");
+            }
+            if (INPUT_STRING_LENGTH <= rule.getOwner().getClassName().length()) {
+                mViolations.add(tag + "input string length <= rule owner class name length");
+            }
+        }
+        if (configActivityFlag) {
+            if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getPackageName().length()) {
+                mViolations.add(tag
+                        + "input string length <= rule configurationActivity package name length");
+            }
+            if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getClassName().length()) {
+                mViolations.add(tag
+                        + "input string length <= rule configurationActivity class name length");
+            }
+        }
+    }
+
+    private void checkConstructor(boolean ownerFlag, boolean configActivityFlag) {
+        ComponentName owner = ownerFlag ? mComponentNameWithLongFields : null;
+        ComponentName configActivity = configActivityFlag ? mComponentNameWithLongFields : null;
+        AutomaticZenRule rule = new AutomaticZenRule(mLongString, owner, configActivity, mLongUri,
+                null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+        checkFields(rule, ownerFlag, configActivityFlag, "\ncheckConstructor (owner=" + ownerFlag
+                + ", configActivity=" + configActivityFlag + "): ");
+    }
+
+    private void testIsConstructorVulnerable() {
+        // Check all three variants i.e. with owner, with configuration activity and with both
+        // owner and configuration activity. Although third case is mostly redundant, adding it to
+        // complete checks on all possible variants.
+        checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ false);
+        checkConstructor(/* ownerFlag */ false, /* configActivityFlag */ true);
+        checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ true);
+    }
+
+    private void checkFieldSetters(boolean ownerFlag, boolean configActivityFlag) {
+        ComponentName owner = ownerFlag ? mValidComponentName : null;
+        ComponentName configActivity = configActivityFlag ? mValidComponentName : null;
+        AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity,
+                mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+
+        // Check all fields that can be set via setter methods of AutomaticZenRule class
+        rule.setName(mLongString);
+        rule.setConditionId(mLongUri);
+        rule.setConfigurationActivity(mComponentNameWithLongFields);
+        checkFields(rule, /* ownerFlag */ false, /* configActivityFlag */ true,
+                "\ncheckFieldSetters (owner=" + ownerFlag + ", configActivity=" + configActivityFlag
+                        + "): ");
+    }
+
+    private void testIsFieldSetterVulnerable() {
+        checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ false);
+        checkFieldSetters(/* ownerFlag */ false, /* configActivityFlag */ true);
+        checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ true);
+    }
+
+    private void checkParcelInput(boolean ownerFlag, boolean configActivityFlag)
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        ComponentName owner = ownerFlag ? mValidComponentName : null;
+        ComponentName configActivity = configActivityFlag ? mValidComponentName : null;
+        AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity,
+                mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+
+        // Create rules with long fields set directly via reflection so that we can confirm that a
+        // rule with too-long fields that comes in via a parcel has its fields truncated directly.
+        Class automaticZenRuleClass = Class.forName("android.app.AutomaticZenRule");
+        Field fieldName = automaticZenRuleClass.getDeclaredField("name");
+        fieldName.setAccessible(/* flag */ true);
+        fieldName.set(rule, mLongString);
+        Field fieldConditionId = automaticZenRuleClass.getDeclaredField("conditionId");
+        fieldConditionId.setAccessible(/* flag */ true);
+        fieldConditionId.set(rule, mLongUri);
+        if (ownerFlag) {
+            Field fieldOwner = automaticZenRuleClass.getDeclaredField("owner");
+            fieldOwner.setAccessible(/* flag */ true);
+            fieldOwner.set(rule, mComponentNameWithLongFields);
+        }
+        if (configActivityFlag) {
+            Field fieldConfigActivity =
+                    automaticZenRuleClass.getDeclaredField("configurationActivity");
+            fieldConfigActivity.setAccessible(/* flag */ true);
+            fieldConfigActivity.set(rule, mComponentNameWithLongFields);
+        }
+
+        // Write AutomaticZenRule object to parcel
+        Parcel parcel = Parcel.obtain();
+        rule.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        // Instantiate AutomaticZenRule object using parcel
+        AutomaticZenRule ruleFromParcel = new AutomaticZenRule(parcel);
+
+        checkFields(ruleFromParcel, ownerFlag, configActivityFlag, "\ncheckParcelInput (owner="
+                + ownerFlag + ", configActivity=" + configActivityFlag + "): ");
+    }
+
+    private void testIsInputFromParcelVulnerable()
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ false);
+        checkParcelInput(/* ownerFlag */ false, /* configActivityFlag */ true);
+        checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ true);
+    }
+
+    // b/242703460, b/242703505, b/242703780, b/242704043, b/243794204
+    // Vulnerable library : framework.jar
+    // Vulnerable module  : Not applicable
+    // Is Play managed    : No
+    @AsbSecurityTest(cveBugId = {242703460, 242703505, 242703780, 242704043, 243794204})
+    @Test
+    public void testPocCVE_2022_20456() {
+        try {
+            mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A"));
+            mComponentNameWithLongFields = new ComponentName(mLongString, mLongString);
+            mValidComponentName = new ComponentName(PACKAGE_NAME, CLASS_NAME);
+            mLongUri = Uri.parse("condition://" + mLongString);
+            mValidUri = Uri.parse(URI_STRING);
+            mViolations = new ArrayList<String>();
+
+            // Check AutomaticZenRule constructor
+            testIsConstructorVulnerable();
+
+            // Check AutomaticZenRule field setters
+            testIsFieldSetterVulnerable();
+
+            // Check AutomaticZenRule constructor using parcel input
+            testIsInputFromParcelVulnerable();
+
+            assertTrue("Device is vulnerable to at least one of the following vulnerabilities : "
+                    + "b/242703460(CVE-2022-20489), b/242703505(CVE-2022-20490), b/242703780"
+                    + "(CVE-2022-20456), b/242704043(CVE-2022-20492), b/243794204(CVE-2022-20494)"
+                    + " due to these violations where input string length=" + INPUT_STRING_LENGTH
+                    + " and input uri length=" + mLongUri.toString().length() + ":" + mViolations,
+                    mViolations.isEmpty());
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20482.java b/tests/tests/security/src/android/security/cts/CVE_2022_20482.java
new file mode 100644
index 0000000..a0df88c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20482.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 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 static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20482 extends StsExtraBusinessLogicTestCase {
+
+    /**
+     * b/240422263
+     * Vulnerable library   : services.jar
+     * Vulnerable module    : Not applicable
+     * Is Play managed      : No
+     */
+    @AsbSecurityTest(cveBugId = 240422263)
+    @Test
+    public void testPocCVE_2022_20482() {
+        final int notificationChannelLimit = 10000; // 2 * NOTIFICATION_CHANNEL_COUNT_LIMIT
+        final String notificationChannelId = "NotificationChannelId";
+        final String notificationChannelName = "NotificationChannelName";
+        boolean isVulnerable = true;
+        int notificationChannelCount = 0;
+        NotificationManager notificationManager = null;
+        ArrayList<String> notificationChannelIds = new ArrayList<>();
+        try {
+            Context context = getApplicationContext();
+            notificationManager = context.getSystemService(NotificationManager.class);
+
+            // Store total number of notification channels present before test run
+            notificationChannelCount = notificationManager.getNotificationChannels().size();
+
+            // Create 'notificationChannelLimit' notification channels
+            for (int i = 0; i < notificationChannelLimit; ++i) {
+                String uniqueNotificationChannelId = notificationChannelId + i;
+                NotificationChannel notificationChannel =
+                        new NotificationChannel(uniqueNotificationChannelId,
+                                notificationChannelName, NotificationManager.IMPORTANCE_DEFAULT);
+
+                // Create notification channel
+                notificationManager.createNotificationChannel(notificationChannel);
+
+                // Add notification channel id in list(for deleting notification channel later)
+                notificationChannelIds.add(uniqueNotificationChannelId);
+            }
+        } catch (Exception e) {
+            isVulnerable = false;
+            if (!(e instanceof IllegalStateException)
+                    || !e.getMessage().contains("Limit exceed; cannot create more channels")) {
+                assumeNoException("Unexpected exception occurred!", e);
+            }
+        } finally {
+            try {
+                // Retrieve total number of notification channels added by test so that the
+                // test fails only if all notification channels from test were added successfully
+                notificationChannelCount = notificationManager.getNotificationChannels().size()
+                        - notificationChannelCount;
+                boolean flagAllNotificationChannelsAdded =
+                        notificationChannelCount == notificationChannelLimit;
+
+                // Delete notification channels created earlier
+                for (String id : notificationChannelIds) {
+                    notificationManager.deleteNotificationChannel(id);
+                }
+
+                // Fail if all notification channels from test were added successfully without
+                // any occurrence of IllegalStateException
+                assertFalse(
+                        "Device is vulnerable to b/240422263! Permanent denial of service"
+                                + " possible via NotificationManager#createNotificationChannel",
+                        isVulnerable && flagAllNotificationChannelsAdded);
+            } catch (Exception ignoredException) {
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20493.java b/tests/tests/security/src/android/security/cts/CVE_2022_20493.java
new file mode 100644
index 0000000..4933dc6
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20493.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.service.notification.Condition;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/*
+ * This CTS test has been created taking reference from the tests present in
+ * frameworks/base/core/tests/coretests/src/android/service/notification/ConditionTest.java
+ */
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20493 extends StsExtraBusinessLogicTestCase {
+    private static final int INPUT_STRING_LENGTH = 2000;
+    private String mLongString;
+    private String mValidString;
+    private Uri mLongUri;
+    private Uri mValidUri;
+
+    private boolean checkFields(Condition condition, boolean checkLine) {
+        // Check all fields
+        boolean status = (mLongUri.toString().length() <= condition.id.toString().length())
+                || (INPUT_STRING_LENGTH <= condition.summary.length());
+        if (checkLine) {
+            status = status || (INPUT_STRING_LENGTH <= condition.line1.length())
+                    || (INPUT_STRING_LENGTH <= condition.line2.length());
+        }
+        return status;
+    }
+
+    private boolean testLongFieldsInConstructors() {
+        // Confirm strings are truncated via short constructor
+        Condition firstCondition = new Condition(mLongUri, mLongString, Condition.STATE_TRUE);
+
+        // Confirm strings are truncated via long constructor
+        Condition secondCondition = new Condition(mLongUri, mLongString, mLongString, mLongString,
+                -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS);
+        return checkFields(firstCondition, false) || checkFields(secondCondition, true);
+    }
+
+    private boolean setFieldsUsingReflection(boolean setLine)
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        // Set fields via reflection to force them to be long, then parcel and unparcel to make sure
+        // it gets truncated upon unparcelling.
+        Condition condition;
+        if (setLine) {
+            condition = new Condition(mValidUri, mValidString, mValidString, mValidString, -1,
+                    Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS);
+        } else {
+            condition = new Condition(mValidUri, mValidString, Condition.STATE_TRUE);
+        }
+
+        Class conditionClass = Class.forName("android.service.notification.Condition");
+        Field id = conditionClass.getDeclaredField("id");
+        id.setAccessible(true);
+        id.set(condition, mLongUri);
+        Field summary = conditionClass.getDeclaredField("summary");
+        summary.setAccessible(true);
+        summary.set(condition, mLongString);
+        if (setLine) {
+            Field line1 = conditionClass.getDeclaredField("line1");
+            line1.setAccessible(true);
+            line1.set(condition, mLongString);
+            Field line2 = conditionClass.getDeclaredField("line2");
+            line2.setAccessible(true);
+            line2.set(condition, mLongString);
+        }
+
+        Parcel parcel = Parcel.obtain();
+        condition.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        Condition conditionFromParcel = new Condition(parcel);
+        return checkFields(conditionFromParcel, setLine);
+    }
+
+    private boolean testLongFieldsFromParcel()
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        return setFieldsUsingReflection(true) || setFieldsUsingReflection(false);
+    }
+
+    /**
+     * b/242846316
+     * Vulnerable library : framework.jar
+     * Vulnerable module  : Not applicable
+     * Is Play managed    : No
+     */
+    @AsbSecurityTest(cveBugId = 242846316)
+    @Test
+    public void testPocCVE_2022_20493() {
+        try {
+            mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A"));
+            mLongUri = Uri.parse("condition://" + mLongString);
+            mValidUri = Uri.parse("condition://android");
+            mValidString = "placeholder";
+            boolean firstResult = testLongFieldsInConstructors();
+            boolean secondResult = testLongFieldsFromParcel();
+            assertFalse("Device is vulnerable to b/242846316!", firstResult || secondResult);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/CertificateTest.java b/tests/tests/security/src/android/security/cts/CertificateTest.java
index 7b1ed9d..7569338 100644
--- a/tests/tests/security/src/android/security/cts/CertificateTest.java
+++ b/tests/tests/security/src/android/security/cts/CertificateTest.java
@@ -16,11 +16,25 @@
 
 package android.security.cts;
 
+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.content.Context;
+import android.content.pm.PackageManager;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import android.content.pm.PackageManager;
-import android.test.AndroidTestCase;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.MessageDigest;
@@ -36,12 +50,23 @@
 import java.util.List;
 import java.util.Set;
 
-public class CertificateTest extends AndroidTestCase {
+@RunWith(Parameterized.class)
+public class CertificateTest {
+    @Parameter
+    public String mApexCertsEnabled;
+
+    @Parameters(name = "{0}")
+    public static Object[] data() {
+        return new Object[] {"true", "false"};
+    }
+
     // The directory for CA root certificates trusted by WFA (WiFi Alliance)
     private static final String DIR_OF_CACERTS_FOR_WFA =
             "/apex/com.android.wifi/etc/security/cacerts_wfa";
 
+    @Test
     public void testNoRemovedCertificates() throws Exception {
+        System.setProperty("system.certs.enabled", mApexCertsEnabled);
         Set<String> expectedCertificates = new HashSet<String>(
                 Arrays.asList(CertificateData.CERTIFICATE_DATA));
         Set<String> deviceCertificates = getDeviceCertificates();
@@ -67,7 +92,9 @@
      *
      * <p>For questions, comments, and code reviews please contact security@android.com.
      */
+    @Test
     public void testNoAddedCertificates() throws Exception {
+        System.setProperty("system.certs.enabled", mApexCertsEnabled);
         Set<String> expectedCertificates = new HashSet<String>(
                 Arrays.asList(CertificateData.CERTIFICATE_DATA));
         Set<String> deviceCertificates = getDeviceCertificates();
@@ -75,7 +102,9 @@
         assertEquals("Unknown CA certificates", Collections.EMPTY_SET, deviceCertificates);
     }
 
+    @Test
     public void testBlockCertificates() throws Exception {
+        System.setProperty("system.certs.enabled", mApexCertsEnabled);
         Set<String> blockCertificates = new HashSet<String>();
         blockCertificates.add("C0:60:ED:44:CB:D8:81:BD:0E:F8:6C:0B:A2:87:DD:CF:81:67:47:8C");
 
@@ -90,6 +119,7 @@
      *
      * For questions, comments, and code reviews please contact security@android.com.
      */
+    @Test
     public void testNoRemovedWfaCertificates() throws Exception {
         if (!isWifiSupported()) {
             return;
@@ -101,6 +131,7 @@
         assertEquals("Missing WFA CA certificates", Collections.EMPTY_SET, expectedCertificates);
     }
 
+    @Test
     public void testNoAddedWfaCertificates() throws Exception {
         if (!isWifiSupported()) {
             return;
@@ -113,7 +144,9 @@
     }
 
     private boolean isWifiSupported() {
-        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
+        Context context;
+        context = InstrumentationRegistry.getInstrumentation().getContext();
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
     }
 
     private KeyStore createWfaKeyStore() throws CertificateException, IOException,
diff --git a/tests/tests/security/src/android/security/cts/MediaSessionTest.java b/tests/tests/security/src/android/security/cts/MediaSessionTest.java
new file mode 100644
index 0000000..d74179e
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaSessionTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertThrows;
+
+import android.content.ComponentName;
+import android.content.ContextWrapper;
+import android.media.session.MediaSession;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@AppModeFull
+@RunWith(AndroidJUnit4.class)
+public class MediaSessionTest extends StsExtraBusinessLogicTestCase {
+    private static final String TAG = "MediaSessionTest";
+
+    private static final String TEST_SESSION_TAG_FOREIGN_PACKAGE =
+            "test-session-tag-foreign-package";
+    private static final String TEST_FOREIGN_PACKAGE_NAME = "fakepackage";
+    private static final String TEST_FOREIGN_PACKAGE_CLASS = "com.fakepackage.media.FakeReceiver";
+
+    @Test
+    @AsbSecurityTest(cveBugId = 238177121)
+    public void setMediaButtonBroadcastReceiver_withForeignPackageName_fails() throws Exception {
+        // Create Media Session
+        MediaSession mediaSession = new MediaSession(new ContextWrapper(getContext()) {
+                    @Override
+                    public String getPackageName() {
+                        return TEST_FOREIGN_PACKAGE_NAME;
+                    }
+                }, TEST_SESSION_TAG_FOREIGN_PACKAGE);
+
+        assertThrows("Component name with different package name was registered.",
+                IllegalArgumentException.class,
+                () -> mediaSession.setMediaButtonBroadcastReceiver(
+                        new ComponentName(TEST_FOREIGN_PACKAGE_NAME, TEST_FOREIGN_PACKAGE_CLASS)));
+
+        mediaSession.release();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java b/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java
new file mode 100644
index 0000000..eafef73
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2022 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 static android.Manifest.permission.CAMERA;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.DeviceConfig;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject2;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.UiAutomatorUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class OneTimePermissionTest {
+
+    private static final String CUSTOM_CAMERA_PERM_APP_PKG_NAME =
+            "android.permission.cts.appthatrequestcustomcamerapermission";
+    private static final String CUSTOM_CAMERA_PERM_APK =
+            "/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk";
+
+    public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM";
+
+    private static final long ONE_TIME_TIMEOUT_MILLIS = 5000;
+    private static final long ONE_TIME_KILLED_DELAY_MILLIS = 5000;
+
+    private final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+    private String mOldOneTimePermissionTimeoutValue;
+    private String mOldOneTimePermissionKilledDelayValue;
+
+    @Before
+    public void wakeUpScreen() {
+        SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
+
+        SystemUtil.runShellCommand("input keyevent 82");
+    }
+
+    @Before
+    public void installApp() {
+        runShellCommand("pm install -r " + CUSTOM_CAMERA_PERM_APK);
+    }
+
+    @Before
+    public void prepareDeviceForOneTime() {
+        runWithShellPermissionIdentity(() -> {
+            mOldOneTimePermissionTimeoutValue = DeviceConfig.getProperty("permissions",
+                    "one_time_permissions_timeout_millis");
+            mOldOneTimePermissionKilledDelayValue = DeviceConfig.getProperty("permissions",
+                    "one_time_permissions_killed_delay_millis");
+            DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+                    Long.toString(ONE_TIME_TIMEOUT_MILLIS), false);
+            DeviceConfig.setProperty("permissions",
+                    "one_time_permissions_killed_delay_millis",
+                    Long.toString(ONE_TIME_KILLED_DELAY_MILLIS), false);
+        });
+    }
+
+    @After
+    public void uninstallApp() {
+        runShellCommand("pm uninstall " + CUSTOM_CAMERA_PERM_APP_PKG_NAME);
+    }
+
+    @After
+    public void restoreDeviceForOneTime() {
+        runWithShellPermissionIdentity(
+                () -> {
+                    DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+                            mOldOneTimePermissionTimeoutValue, false);
+                    DeviceConfig.setProperty("permissions",
+                            "one_time_permissions_killed_delay_millis",
+                            mOldOneTimePermissionKilledDelayValue, false);
+                });
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 237405974L)
+    public void testCustomPermissionIsGrantedOneTime() throws Throwable {
+        Intent startApp = new Intent()
+                .setComponent(new ComponentName(CUSTOM_CAMERA_PERM_APP_PKG_NAME,
+                        CUSTOM_CAMERA_PERM_APP_PKG_NAME + ".RequestCameraPermission"))
+                .addFlags(FLAG_ACTIVITY_NEW_TASK);
+
+        mContext.startActivity(startApp);
+
+        // We're only manually granting CAMERA, but the app will later request CUSTOM and get it
+        // granted silently. This is intentional since it's in the same group but both should
+        // eventually be revoked
+        clickOneTimeButton();
+
+        // Just waiting for the revocation
+        eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+                mContext.getPackageManager()
+                        .checkPermission(CAMERA, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
+
+        // This checks the vulnerability
+        eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+                mContext.getPackageManager()
+                        .checkPermission(CUSTOM_PERMISSION, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
+
+    }
+
+    private void clickOneTimeButton() throws Throwable {
+        final UiObject2 uiObject = UiAutomatorUtils.waitFindObject(By.res(
+                "com.android.permissioncontroller:id/permission_allow_one_time_button"), 10000);
+        Thread.sleep(500);
+        uiObject.click();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 4bfe8fe..b6ee6ed 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -102,7 +102,7 @@
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_runtime_debug));
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_runtime_release));
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata3));
-        // The following keys are not not used by modules on the latest Android release, but it
+        // The following keys are not used by modules on the latest Android release, but it
         // won't negatively affect tests to include their signatures here too.
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata));
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata2));
diff --git a/tests/tests/security/src/android/security/cts/PermissionBackupCertificateCheckTest.kt b/tests/tests/security/src/android/security/cts/PermissionBackupCertificateCheckTest.kt
new file mode 100644
index 0000000..1170939
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/PermissionBackupCertificateCheckTest.kt
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2018 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.Manifest.permission.*
+import android.app.AppOpsManager
+import android.content.pm.PackageManager.*
+import android.os.ParcelFileDescriptor
+import android.permission.cts.PermissionUtils.grantPermission
+import android.platform.test.annotations.AppModeFull
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compatibility.common.util.BackupUtils
+import com.android.compatibility.common.util.BackupUtils.LOCAL_TRANSPORT_TOKEN
+import com.android.compatibility.common.util.BusinessLogicTestCase
+import com.android.compatibility.common.util.ShellUtils.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
+import java.io.InputStream
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests that permissions for backed up apps are restored only after checking that their signing
+ * certificates are compared.
+ *
+ * @see [com.android.permissioncontroller.permission.service.BackupHelper]
+ */
+@AppModeFull
+@RunWith(AndroidJUnit4::class)
+class PermissionBackupCertificateCheckTest : StsExtraBusinessLogicTestCase() {
+    private val backupUtils: BackupUtils =
+        object : BackupUtils() {
+            override fun executeShellCommand(command: String): InputStream {
+                val pfd =
+                    BusinessLogicTestCase.getInstrumentation()
+                        .uiAutomation
+                        .executeShellCommand(command)
+                return ParcelFileDescriptor.AutoCloseInputStream(pfd)
+            }
+        }
+
+    private var isBackupSupported = false
+
+    private val targetContext = InstrumentationRegistry.getTargetContext()
+
+    @Before
+    fun setUp() {
+        val packageManager = BusinessLogicTestCase.getInstrumentation().context.packageManager
+        isBackupSupported =
+            (packageManager != null && packageManager.hasSystemFeature(FEATURE_BACKUP))
+
+        if (isBackupSupported) {
+            assertTrue("Backup not enabled", backupUtils.isBackupEnabled)
+            assertTrue("LocalTransport not selected", backupUtils.isLocalTransportSelected)
+            backupUtils.executeShellCommandSync("setprop log.tag.$APP_LOG_TAG VERBOSE")
+        }
+    }
+
+    @After
+    fun tearDown() {
+        uninstallIfInstalled(APP)
+        clearFlag(APP, ACCESS_FINE_LOCATION, FLAG_PERMISSION_USER_SET)
+        clearFlag(APP, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_USER_SET)
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has the
+     * same certificate as the backed up app.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_sameCert_restoresRuntimePermissions() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_1_DUP)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has a
+     * different certificate as the backed up app.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_diffCert_doesNotGrantRuntimePermissions() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_3)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has the
+     * backed up app's certificate in its signing history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_midHistoryToRotated_restoresRuntimePermissions() {
+        install(APP_APK_CERT_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has the
+     * backed up app's certificate as the original certificate in its signing history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_origToRotated_restoresRuntimePermissions() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the backed up app has the
+     * restored app's certificate in its signing history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_rotatedToMidHistory_restoresRuntimePermissions() {
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_2)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the backed up app has the
+     * restored app's certificate in its signing history as its original certificate.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_rotatedToOrig_restoresRuntimePermissions() {
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_1)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the backed up app has the same
+     * certificate as the restored app, but the restored app additionally has signing certificate
+     * history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_sameWithHistory_restoresRuntimePermissions() {
+        install(APP_APK_CERT_4)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the backed up app has the same
+     * certificate as the restored app, but the backed up app additionally has signing certificate
+     * history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_sameWithoutHistory_restoresRuntimePermissions() {
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has
+     * signing history, but the backed up app's certificate is not in this signing history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_notInBackedUpHistory_doesNotRestoreRuntimePerms() {
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_3)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has
+     * signing history, but the backed up app's certificate is not in this signing history.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_notInRestoredHistory_doesNotRestoreRuntimePerms() {
+        install(APP_APK_CERT_3)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has
+     * multiple certificates, and the backed up app also has identical multiple certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_sameMultCerts_restoresRuntimePermissions() {
+        install(APP_APK_CERT_1_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_1_2_DUP)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has
+     * multiple certificates, and the backed up app do not have identical multiple certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_diffMultCerts_doesNotRestoreRuntimePermissions() {
+        install(APP_APK_CERT_1_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_3_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the app being restored has
+     * multiple certificates, and the backed up app's certificate is present in th restored app's
+     * certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_singleToMultiCert_restoresRuntimePerms() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_1_2_3)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the backed up app and the app
+     * being restored have multiple certificates, and the backed up app's certificates are a subset
+     * of the restored app's certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_multCertsToSuperset_doesNotRestoreRuntimePerms() {
+        install(APP_APK_CERT_1_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_1_2_3)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of regular runtime permissions, when the backed up app and the app
+     * being restored have multiple certificates, and the backed up app's certificates are a
+     * superset of the restored app's certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_multCertsToSubset_doesNotRestoreRuntimePermissions() {
+        install(APP_APK_CERT_1_2_3)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_1_2)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, READ_CONTACTS))
+        }
+    }
+
+    /**
+     * Test backup and restore of tri-state permissions, when both foreground and background runtime
+     * permissions are not granted and the backed up and restored app have compatible certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_fgBgDenied_matchingCerts_restoresFgBgPermissions() {
+        install(APP_APK_CERT_2)
+        if (!isBackupSupported) {
+            return
+        }
+        // Make a token change to permission state, to enable to us to determine when restore is
+        // complete.
+        grantPermission(APP, WRITE_CONTACTS)
+        // PERMISSION_DENIED is the default state, so we mark the permissions as user set in order
+        // to ensure that permissions are backed up.
+        setFlag(APP, ACCESS_FINE_LOCATION, FLAG_PERMISSION_USER_SET)
+        setFlag(APP, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_USER_SET)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+
+            // Wait until restore is complete.
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, WRITE_CONTACTS))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_BACKGROUND_LOCATION))
+            assertEquals(AppOpsManager.MODE_IGNORED, getAppOp(APP, ACCESS_FINE_LOCATION))
+        }
+    }
+
+    /**
+     * Test backup and restore of tri-state permissions, when both foreground and background runtime
+     * permissions are not granted and the backed up and restored app don't have compatible
+     * certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_fgBgDenied_notMatchingCerts_doesNotRestorePerms() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        // Make a token change to permission state, to enable to us to determine when restore is
+        // complete.
+        grantPermission(APP, WRITE_CONTACTS)
+        // PERMISSION_DENIED is the default state, so we mark the permissions as user set in order
+        // to ensure that permissions are backed up.
+        setFlag(APP, ACCESS_FINE_LOCATION, FLAG_PERMISSION_USER_SET)
+        setFlag(APP, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_USER_SET)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_2)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+
+            // Wait until restore is complete.
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, WRITE_CONTACTS))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_BACKGROUND_LOCATION))
+            assertEquals(AppOpsManager.MODE_IGNORED, getAppOp(APP, ACCESS_FINE_LOCATION))
+        }
+    }
+
+    /**
+     * Test backup and restore of tri-state permissions, when foreground runtime permission is
+     * granted and the backed up and restored app have compatible certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_fgGranted_matchingCerts_restoresFgBgPermissions() {
+        install(APP_APK_CERT_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+        // PERMISSION_DENIED is the default state, so we mark the permissions as user set in order
+        // to ensure that permissions are backed up.
+        setFlag(APP, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_USER_SET)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_BACKGROUND_LOCATION))
+            assertEquals(AppOpsManager.MODE_FOREGROUND, getAppOp(APP, ACCESS_FINE_LOCATION))
+        }
+    }
+
+    /**
+     * Test backup and restore of tri-state permissions, when foreground runtime permission is
+     * granted and the backed up and restored app don't have compatible certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_fgGranted_notMatchingCerts_doesNotRestoreFgBgPerms() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+        // PERMISSION_DENIED is the default state, so we mark the permissions as user set in order
+        // to ensure that permissions are backed up.
+        setFlag(APP, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_USER_SET)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_2)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_BACKGROUND_LOCATION))
+            assertEquals(AppOpsManager.MODE_IGNORED, getAppOp(APP, ACCESS_FINE_LOCATION))
+        }
+    }
+
+    /**
+     * Test backup and restore of tri-state permissions, when foreground and background runtime
+     * permissions are granted and the backed up and restored app have compatible certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_fgBgGranted_matchingCerts_restoresFgBgPermissions() {
+        install(APP_APK_CERT_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+        grantPermission(APP, ACCESS_BACKGROUND_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_BACKGROUND_LOCATION))
+            assertEquals(AppOpsManager.MODE_ALLOWED, getAppOp(APP, ACCESS_FINE_LOCATION))
+        }
+    }
+
+    /**
+     * Test backup and restore of tri-state permissions, when foreground and background runtime
+     * permissions are granted and the backed up and restored app don't have compatible
+     * certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_fgBgGranted_notMatchingCerts_restoresFgBgPerms() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+        grantPermission(APP, ACCESS_BACKGROUND_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_2)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually {
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION))
+            assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_BACKGROUND_LOCATION))
+            assertEquals(AppOpsManager.MODE_IGNORED, getAppOp(APP, ACCESS_FINE_LOCATION))
+        }
+    }
+
+    /**
+     * Test backup and restore of flags when the backed up app and restored app have compatible
+     * certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_matchingCerts_restoresFlags() {
+        install(APP_APK_CERT_2)
+        if (!isBackupSupported) {
+            return
+        }
+        setFlag(APP, WRITE_CONTACTS, FLAG_PERMISSION_USER_SET)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually { assertTrue(isFlagSet(APP, WRITE_CONTACTS, FLAG_PERMISSION_USER_SET)) }
+    }
+
+    /**
+     * Test backup and restore of flags when the backed up app and restored app don't have
+     * compatible certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_notMatchingCerts_doesNotRestoreFlag() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        setFlag(APP, WRITE_CONTACTS, FLAG_PERMISSION_USER_SET)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        install(APP_APK_CERT_2)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+
+        eventually { assertFalse(isFlagSet(APP, WRITE_CONTACTS, FLAG_PERMISSION_USER_SET)) }
+    }
+
+    /**
+     * Test backup and delayed restore of regular runtime permission, i.e. when an app is installed
+     * after restore has run, and the backed up app and restored app have compatible certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_appInstalledLater_matchingCerts_restoresCorrectly() {
+        install(APP_APK_CERT_2)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+
+        eventually { assertEquals(PERMISSION_GRANTED, checkPermission(APP, ACCESS_FINE_LOCATION)) }
+    }
+
+    /**
+     * Test backup and delayed restore of regular runtime permission, i.e. when an app is installed
+     * after restore has run, and the backed up app and restored app don't have compatible
+     * certificates.
+     */
+    @Test
+    @AsbSecurityTest(cveBugId = [184847040])
+    fun testRestore_appInstalledLater_notMatchingCerts_doesNotRestore() {
+        install(APP_APK_CERT_1)
+        if (!isBackupSupported) {
+            return
+        }
+        grantPermission(APP, ACCESS_FINE_LOCATION)
+
+        backupUtils.backupNowAndAssertSuccess(ANDROID_PACKAGE)
+        uninstallIfInstalled(APP)
+        backupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, ANDROID_PACKAGE)
+        install(APP_APK_CERT_4_HISTORY_1_2_4)
+
+        eventually { assertEquals(PERMISSION_DENIED, checkPermission(APP, ACCESS_FINE_LOCATION)) }
+    }
+
+    private fun install(apk: String) {
+        val output = runShellCommand("pm install -r $apk")
+        assertEquals("Success", output)
+    }
+
+    private fun uninstallIfInstalled(packageName: String) {
+        runShellCommand("pm uninstall $packageName")
+    }
+
+    private fun setFlag(app: String, permission: String, flag: Int) {
+        runWithShellPermissionIdentity {
+            targetContext.packageManager.updatePermissionFlags(
+                permission, app, flag, flag, targetContext.user)
+        }
+    }
+
+    private fun clearFlag(app: String, permission: String, flag: Int) {
+        runWithShellPermissionIdentity {
+            targetContext.packageManager.updatePermissionFlags(
+                permission, app, flag, 0, targetContext.user)
+        }
+    }
+
+    private fun isFlagSet(app: String, permission: String, flag: Int): Boolean {
+        return try {
+            callWithShellPermissionIdentity<Int> {
+                targetContext.packageManager.getPermissionFlags(permission, app, targetContext.user)
+            } and flag == flag
+        } catch (e: Exception) {
+            throw RuntimeException(e)
+        }
+    }
+
+    private fun checkPermission(app: String, permission: String): Int {
+        return targetContext.packageManager.checkPermission(permission, app)
+    }
+
+    private fun getAppOp(app: String, permission: String): Int {
+        return try {
+            callWithShellPermissionIdentity {
+                targetContext
+                    .getSystemService<AppOpsManager>(AppOpsManager::class.java)!!
+                    .unsafeCheckOpRaw(
+                        AppOpsManager.permissionToOp(permission)!!,
+                        targetContext.packageManager.getPackageUid(app, 0),
+                        app)
+            }
+        } catch (e: Exception) {
+            throw RuntimeException(e)
+        }
+    }
+
+    companion object {
+        /** The name of the package of the apps under test */
+        private const val APP = "android.security.permissionbackup"
+        /** The apk of the packages */
+        private const val APK_PATH = "/data/local/tmp/cts/security/"
+        private const val APP_APK_CERT_1 = "${APK_PATH}CtsPermissionBackupAppCert1.apk"
+        private const val APP_APK_CERT_1_DUP = "${APK_PATH}CtsPermissionBackupAppCert1Dup.apk"
+        private const val APP_APK_CERT_2 = "${APK_PATH}CtsPermissionBackupAppCert2.apk"
+        private const val APP_APK_CERT_3 = "${APK_PATH}CtsPermissionBackupAppCert3.apk"
+        private const val APP_APK_CERT_4 = "${APK_PATH}CtsPermissionBackupAppCert4.apk"
+        private const val APP_APK_CERT_1_2 = "${APK_PATH}CtsPermissionBackupAppCert12.apk"
+        private const val APP_APK_CERT_1_2_DUP = "${APK_PATH}CtsPermissionBackupAppCert12Dup.apk"
+        private const val APP_APK_CERT_1_2_3 = "${APK_PATH}CtsPermissionBackupAppCert123.apk"
+        private const val APP_APK_CERT_3_4 = "${APK_PATH}CtsPermissionBackupAppCert34.apk"
+        private const val APP_APK_CERT_4_HISTORY_1_2_4 =
+            "${APK_PATH}CtsPermissionBackupAppCert4History124.apk"
+        private const val APP_LOG_TAG = "PermissionBackupApp"
+        /** The name of the package for backup */
+        private const val ANDROID_PACKAGE = "android"
+        private const val TIMEOUT_MILLIS: Long = 10000
+
+        /**
+         * Make sure that a [Runnable] eventually finishes without throwing an [Exception].
+         *
+         * @param r The [Runnable] to run.
+         */
+        fun eventually(r: Runnable) {
+            val start = System.currentTimeMillis()
+            while (true) {
+                try {
+                    r.run()
+                    return
+                } catch (e: Throwable) {
+                    if (System.currentTimeMillis() - start < TIMEOUT_MILLIS) {
+                        try {
+                            Thread.sleep(100)
+                        } catch (ignored: InterruptedException) {
+                            throw RuntimeException(e)
+                        }
+                    } else {
+                        throw e
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/PermissionMemoryFootprintTest.kt b/tests/tests/security/src/android/security/cts/PermissionMemoryFootprintTest.kt
new file mode 100644
index 0000000..c774760
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/PermissionMemoryFootprintTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 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.content.pm.PackageManager
+import android.content.pm.PermissionInfo
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class PermissionMemoryFootprintTest : StsExtraBusinessLogicTestCase() {
+    companion object {
+        const val MAX_NUM_PERMISSIONS = 32000
+        const val PKG_TREE_NAME = "com.android.cts"
+        val LONG_DESCRIPTION = " ".repeat(MAX_NUM_PERMISSIONS / 10)
+        val SHORT_DESCRIPTION = " ".repeat(MAX_NUM_PERMISSIONS / 100)
+
+        val permInfo = PermissionInfo().apply {
+            labelRes = 1
+            protectionLevel = PermissionInfo.PROTECTION_NORMAL
+        }
+    }
+
+    val packageManager: PackageManager = InstrumentationRegistry.getInstrumentation()
+                    .getTargetContext().packageManager!!
+
+    @Throws(SecurityException::class)
+    private fun createOrRemovePermissions(
+        largePerm: Boolean = true,
+        add: Boolean = true,
+        numPerms: Int = MAX_NUM_PERMISSIONS,
+    ): Int {
+        var numPermsCreated = 0
+        for (i in 1..numPerms) {
+            try {
+                permInfo.name = "$PKG_TREE_NAME.$i"
+                permInfo.nonLocalizedDescription = if (largePerm) {
+                    LONG_DESCRIPTION
+                } else {
+                    SHORT_DESCRIPTION
+                }
+
+                if (add) {
+                    packageManager.addPermission(permInfo)
+                } else {
+                    packageManager.removePermission(permInfo.name)
+                }
+            } catch (e: SecurityException) {
+                break
+            }
+            numPermsCreated = i
+        }
+        return numPermsCreated
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = [242537498])
+    fun checkAppsCreatingPermissionsAreCapped() {
+        var numCreated = 0
+        try {
+            numCreated = createOrRemovePermissions()
+            Assert.assertNotEquals("Expected at least one permission", numCreated, 0)
+            Assert.assertNotEquals(numCreated, MAX_NUM_PERMISSIONS)
+        } finally {
+            createOrRemovePermissions(add = false, numPerms = numCreated)
+        }
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = [242537498])
+    fun checkAppsCantIncreasePermissionSizeAfterCreating() {
+        var numCreatedShort = 0
+        try {
+            numCreatedShort = createOrRemovePermissions(largePerm = false)
+            Assert.assertNotEquals("Expected at least one permission", numCreatedShort, 0)
+            val numCreatedLong = createOrRemovePermissions(numPerms = 1)
+            Assert.assertEquals("Expected to not be able to create a large permission",
+                0, numCreatedLong)
+        } finally {
+            createOrRemovePermissions(add = false, numPerms = numCreatedShort)
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt b/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt
index 28d004f..3b20d45 100644
--- a/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt
+++ b/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt
@@ -18,7 +18,10 @@
 
 import android.platform.test.annotations.AsbSecurityTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compatibility.common.util.mainline.MainlineModule
+import com.android.compatibility.common.util.mainline.ModuleDetector
 import org.junit.After
+import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -35,6 +38,8 @@
     @Test
     @AsbSecurityTest(cveBugId = [223907044])
     fun testAutoGrant() {
+        assumeFalse(ModuleDetector.moduleIsPlayManaged(
+                mContext.getPackageManager(), MainlineModule.PERMISSION_CONTROLLER))
         installPackage(SPLIT_PERMISSION_APK_PATH)
         assertAppHasPermission(android.Manifest.permission.BLUETOOTH, true)
         assertAppHasPermission(android.Manifest.permission.BLUETOOTH_CONNECT, true)
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 307a3e7..4facc06 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1377,8 +1377,10 @@
         };
         server.start();
         String uri = "rtsp://127.0.0.1:8080/cve_2016_3880";
-        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(new CrashUtils.Config()
-                .setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT));
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(
+                new CrashUtils.Config()
+                        .setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT)
+                        .appendAbortMessageExcludes("CHECK\\(IsRTSPVersion"));
         LooperThread t = new LooperThread(new Runnable() {
             @Override
             public void run() {
@@ -1809,6 +1811,18 @@
      before any existing test methods
      ***********************************************************/
     @Test
+    @AsbSecurityTest(cveBugId = 240971780)
+    public void testStagefright_cve_2022_33234() throws Exception {
+         doStagefrightTest(R.raw.cve_2022_33234);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 235102508)
+    public void testStagefright_cve_2022_25669() throws Exception {
+         doStagefrightTest(R.raw.cve_2022_25669);
+    }
+
+    @Test
     @AsbSecurityTest(cveBugId = 223209306)
     public void testStagefright_cve_2022_22085() throws Exception {
          doStagefrightTest(R.raw.cve_2022_22085);
diff --git a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
index 73474a1..eeed518 100644
--- a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
@@ -76,7 +76,9 @@
 
     @After
     public void tearDown() throws Exception {
-        mWallpaperManager.clear(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+        if (mWallpaperManager != null) {
+            mWallpaperManager.clear(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+        }
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .dropShellPermissionIdentity();
     }
diff --git a/tests/tests/security/src/android/security/cts/WorkSourceTest.java b/tests/tests/security/src/android/security/cts/WorkSourceTest.java
new file mode 100644
index 0000000..1438b29
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/WorkSourceTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.os.WorkSource;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class WorkSourceTest extends StsExtraBusinessLogicTestCase {
+    private static final int TEST_PID = 6512;
+    private static final String TEST_PACKAGE_NAME = "android.security.cts";
+
+    @Test
+    @AsbSecurityTest(cveBugId = 220302519)
+    public void testWorkChainParceling() {
+        WorkSource ws = new WorkSource(TEST_PID, TEST_PACKAGE_NAME);
+        // Create a WorkChain so the mChains becomes non-null
+        ws.createWorkChain();
+        assertNotNull("WorkChains must be non-null in order to properly test parceling",
+                ws.getWorkChains());
+        // Then clear it so it's an empty list.
+        ws.getWorkChains().clear();
+        assertTrue("WorkChains must be empty in order to properly test parceling",
+                ws.getWorkChains().isEmpty());
+
+        Parcel p = Parcel.obtain();
+        ws.writeToParcel(p, 0);
+        p.setDataPosition(0);
+
+        // Read the Parcel back out and validate the two Parcels are identical
+        WorkSource readWs = WorkSource.CREATOR.createFromParcel(p);
+        assertNotNull(readWs.getWorkChains());
+        assertTrue(readWs.getWorkChains().isEmpty());
+        assertEquals(ws, readWs);
+
+        // Assert that we've read every byte out of the Parcel.
+        assertEquals(p.dataSize(), p.dataPosition());
+
+        p.recycle();
+    }
+}
diff --git a/tests/tests/security/test-cert-1.pk8 b/tests/tests/security/test-cert-1.pk8
new file mode 100644
index 0000000..f781c30
--- /dev/null
+++ b/tests/tests/security/test-cert-1.pk8
Binary files differ
diff --git a/tests/tests/security/test-cert-1.x509.pem b/tests/tests/security/test-cert-1.x509.pem
new file mode 100644
index 0000000..06adcfe
--- /dev/null
+++ b/tests/tests/security/test-cert-1.x509.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBbDCCARGgAwIBAgIJAMoPtk37ZudyMAoGCCqGSM49BAMCMBIxEDAOBgNVBAMM
+B2VjLXAyNTYwHhcNMTYwMzMxMTQ1ODA2WhcNNDMwODE3MTQ1ODA2WjASMRAwDgYD
+VQQDDAdlYy1wMjU2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpl8RPSLLSROQ
+gwesMe4roOkTi3hfrGU20U6izpDStL/hlLUM3I4Wn1SnOpke8Pp2MpglvgeMx4J0
+BwPaRLTX66NQME4wHQYDVR0OBBYEFNQTNWi5WzAVizIgceqMQ/9bBczIMB8GA1Ud
+IwQYMBaAFNQTNWi5WzAVizIgceqMQ/9bBczIMAwGA1UdEwQFMAMBAf8wCgYIKoZI
+zj0EAwIDSQAwRgIhAPUEoIZsrvAp9BcULFy3E1THn/zR1kBhjfyk8Z4W23jWAiEA
++O6kgpeZwGytCMbT0tLsBeBXQVTnR+oP27gELLZVqt0=
+-----END CERTIFICATE-----
diff --git a/tests/tests/security/test-cert-2.pk8 b/tests/tests/security/test-cert-2.pk8
new file mode 100644
index 0000000..5e73f27
--- /dev/null
+++ b/tests/tests/security/test-cert-2.pk8
Binary files differ
diff --git a/tests/tests/security/test-cert-2.x509.pem b/tests/tests/security/test-cert-2.x509.pem
new file mode 100644
index 0000000..f8e5e65
--- /dev/null
+++ b/tests/tests/security/test-cert-2.x509.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBbTCCAROgAwIBAgIJAIhVvR3SsrIlMAoGCCqGSM49BAMCMBIxEDAOBgNVBAMM
+B2VjLXAyNTYwHhcNMTgwNzEzMTc0MTUxWhcNMjgwNzEwMTc0MTUxWjAUMRIwEAYD
+VQQDDAllYy1wMjU2XzIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQdTMoEcq2X
+7jzs7w2pPWK0UMZ4gzOzbnVTzen3SrXfALu6a6lQ5oRh1wu8JxtiFR2tLeK/YgPN
+IHaAHHqdRCLho1AwTjAdBgNVHQ4EFgQUeZHZKwII/ESL9QbU78n/9CjLXl8wHwYD
+VR0jBBgwFoAU1BM1aLlbMBWLMiBx6oxD/1sFzMgwDAYDVR0TBAUwAwEB/zAKBggq
+hkjOPQQDAgNIADBFAiAnaauxtJ/C9TR5xK6SpmMdq/1SLJrLC7orQ+vrmcYwEQIh
+ANJg+x0fF2z5t/pgCYv9JDGfSQWj5f2hAKb+Giqxn/Ce
+-----END CERTIFICATE-----
diff --git a/tests/tests/security/test-cert-3.pk8 b/tests/tests/security/test-cert-3.pk8
new file mode 100644
index 0000000..d7309dd
--- /dev/null
+++ b/tests/tests/security/test-cert-3.pk8
Binary files differ
diff --git a/tests/tests/security/test-cert-3.x509.pem b/tests/tests/security/test-cert-3.x509.pem
new file mode 100644
index 0000000..c028ff7
--- /dev/null
+++ b/tests/tests/security/test-cert-3.x509.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBbjCCARWgAwIBAgIJAIOU9crRaomnMAoGCCqGSM49BAMCMBQxEjAQBgNVBAMM
+CWVjLXAyNTZfMjAeFw0xODA3MTQwMDA1MjZaFw0yODA3MTEwMDA1MjZaMBQxEjAQ
+BgNVBAMMCWVjLXAyNTZfMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMeYkMO
+nbb8WSjZdfxOR0GbrPyy4HyJKZ5s1+NE3SGt/TCNWMtJoaKj/srM7qSGIGnzC+Fk
+O8wlUEDYCJ37N0OjUDBOMB0GA1UdDgQWBBRvjQgosT769Xf8hrDpn6PlS8vP8DAf
+BgNVHSMEGDAWgBR5kdkrAgj8RIv1BtTvyf/0KMteXzAMBgNVHRMEBTADAQH/MAoG
+CCqGSM49BAMCA0cAMEQCICVr2qJ4TCc+TMKRpZWkZ3ne6d6QRNyferggMJVn35/p
+AiAaStjGmJG1qMR0NP6VQO0fSXm1+tNIPz+gTVZ3NVpXng==
+-----END CERTIFICATE-----
diff --git a/tests/tests/security/test-cert-4.pk8 b/tests/tests/security/test-cert-4.pk8
new file mode 100644
index 0000000..3675d50
--- /dev/null
+++ b/tests/tests/security/test-cert-4.pk8
Binary files differ
diff --git a/tests/tests/security/test-cert-4.x509.pem b/tests/tests/security/test-cert-4.x509.pem
new file mode 100644
index 0000000..4060400
--- /dev/null
+++ b/tests/tests/security/test-cert-4.x509.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBezCCASCgAwIBAgIUbIy4qBhDPB5kMfsW+zrg+1rWCqcwCgYIKoZIzj0EAwIw
+FDESMBAGA1UEAwwJZWMtcDI1Nl8zMB4XDTIwMDUxMzE5MTUyOFoXDTMwMDUxMTE5
+MTUyOFowFDESMBAGA1UEAwwJZWMtcDI1Nl80MFkwEwYHKoZIzj0CAQYIKoZIzj0D
+AQcDQgAE20pgAx55rUnLdZAH1oVdRGm5HIurBlQ08vupca3n5NGVmaD2e15wjP2n
+VD5WMMN2nTfgk2QNfHaKFRRM0OXc9KNQME4wHQYDVR0OBBYEFG54lwMyVUM2tu6J
+JOqnAjDjk/Z4MB8GA1UdIwQYMBaAFG+NCCixPvr1d/yGsOmfo+VLy8/wMAwGA1Ud
+EwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAM54bnnsdUdEYILpyvkQYU/4B1j5
+gZ+w8UhpUGer4PzUAiEApIgeMy3ewhFq0rWc+JHQ8zH/fifne3xiBseYjZtTkzA=
+-----END CERTIFICATE-----
diff --git a/tests/tests/security/test-cert-with-1-2-4-in-rotation-history b/tests/tests/security/test-cert-with-1-2-4-in-rotation-history
new file mode 100644
index 0000000..7326e46
--- /dev/null
+++ b/tests/tests/security/test-cert-with-1-2-4-in-rotation-history
Binary files differ
diff --git a/tests/tests/security/testdata/permissionbackuptestapp/AndroidManifest.xml b/tests/tests/security/testdata/permissionbackuptestapp/AndroidManifest.xml
new file mode 100644
index 0000000..2b75d8c
--- /dev/null
+++ b/tests/tests/security/testdata/permissionbackuptestapp/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.permissionbackup" >
+
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
+    <uses-permission android:name="android.permission.READ_CONTACTS"/>
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
+    <application
+        android:label="Android Permission Backup CTS App">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
diff --git a/tests/tests/settings/Android.bp b/tests/tests/settings/Android.bp
index 46edf80..1798e55 100644
--- a/tests/tests/settings/Android.bp
+++ b/tests/tests/settings/Android.bp
@@ -1,3 +1,4 @@
+
 package {
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java
index edc1cd2..812b1ef 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java
@@ -421,7 +421,8 @@
             mLauncherContext1, mPackageContext1.getPackageName(), "s2", false));
     }
 
-    public void testSetDynamicShortcuts_PersistsShortcutsToDisk() throws Exception {
+    // TODO: b/259468694
+    public void setDynamicShortcuts_PersistsShortcutsToDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -474,7 +475,8 @@
         });
     }
 
-    public void testRemoveAllDynamicShortcuts_RemovesShortcutsFromDisk() throws Exception {
+    // TODO: b/259468694
+    public void removeAllDynamicShortcuts_RemovesShortcutsFromDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -533,7 +535,8 @@
         });
     }
 
-    public void testAddDynamicShortcuts_PersistsShortcutsToDisk() throws Exception {
+    // TODO: b/259468694
+    public void addDynamicShortcuts_PersistsShortcutsToDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -588,7 +591,8 @@
         });
     }
 
-    public void testPushDynamicShortcuts_PersistsShortcutsToDisk() throws Exception {
+    // TODO: b/259468694
+    public void pushDynamicShortcuts_PersistsShortcutsToDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -657,7 +661,8 @@
         SystemUtil.runShellCommand("cmd shortcut reset-config");
     }
 
-    public void testRemoveDynamicShortcuts_RemovesShortcutsFromDisk() throws Exception {
+    // TODO: b/259468694
+    public void removeDynamicShortcuts_RemovesShortcutsFromDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -687,7 +692,8 @@
         });
     }
 
-    public void testRemoveLongLivedShortcuts_RemovesShortcutsFromDisk() throws Exception {
+    // TODO: b/259468694
+    public void removeLongLivedShortcuts_RemovesShortcutsFromDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -716,7 +722,8 @@
         });
     }
 
-    public void testDisableShortcuts_RemovesShortcutsFromDisk() throws Exception {
+    // TODO: b/259468694
+    public void disableShortcuts_RemovesShortcutsFromDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
@@ -746,7 +753,8 @@
         });
     }
 
-    public void testUpdateShortcuts_UpdateShortcutsOnDisk() throws Exception {
+    // TODO: b/259468694
+    public void updateShortcuts_UpdateShortcutsOnDisk() throws Exception {
         if (!isAppSearchEnabled()) {
             return;
         }
diff --git a/tests/tests/systemui/AndroidManifest.xml b/tests/tests/systemui/AndroidManifest.xml
index 15933b6..3bcb78e 100644
--- a/tests/tests/systemui/AndroidManifest.xml
+++ b/tests/tests/systemui/AndroidManifest.xml
@@ -29,13 +29,11 @@
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
 
     <application android:requestLegacyExternalStorage="true">
-        <!-- Have LightBarActivity always take up the full screen, regardless of orientation,
-             so it's never letterboxed. If the activity is letterboxed, then the status icons will
-             be outside of the activity and the tests will fail. See b/246515090. -->
+        <!-- Have LightBarActivity always be in portrait orientation, since the test's screenshots
+             rely on portrait orientation. See b/260069585. -->
         <activity android:name=".LightBarActivity"
              android:theme="@android:style/Theme.Material.NoActionBar"
-             android:screenOrientation="unspecified"
-             android:resizeableActivity="true"/>
+             android:screenOrientation="portrait"/>
         <activity android:name=".LightBarThemeActivity"
              android:theme="@style/LightBarTheme"
              android:screenOrientation="portrait"/>
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index 5079217..c09cb53 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -41,6 +41,7 @@
 import android.permission.PermissionManager;
 import android.permission.cts.PermissionUtils;
 import android.platform.test.annotations.AppModeFull;
+import android.server.wm.IgnoreOrientationRequestSession;
 import android.view.Gravity;
 import android.view.InputDevice;
 import android.view.MotionEvent;
@@ -54,6 +55,8 @@
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.compatibility.common.util.ThrowingRunnable;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestName;
@@ -86,6 +89,7 @@
     private final String NOTIFICATION_CHANNEL_ID = "test_channel";
     private final String NOTIFICATION_GROUP_KEY = "test_group";
     private NotificationManager mNm;
+    private IgnoreOrientationRequestSession mOrientationRequestSession;
 
     @Rule
     public ActivityTestRule<LightBarActivity> mActivityRule = new ActivityTestRule<>(
@@ -93,6 +97,28 @@
     @Rule
     public TestName mTestName = new TestName();
 
+
+
+    @Before
+    public void setUp() {
+        // We need to prevent letterboxing because when an activity is letterboxed, then the status
+        // bar icons are outside the activity space so our verification will fail. See b/246515090.
+        //
+        // When ignore_orientation_request is set to true and the device is in landscape but the
+        // activity is in portrait, then the device remains in landscape but letterboxes the
+        // activity (so the activity is *not* full screen). Setting ignore_orientation_request to
+        // false will cause the device to instead rotate to portrait to match the activity, thus
+        // preventing letterboxing.
+        mOrientationRequestSession = new IgnoreOrientationRequestSession(false /* enable */);
+    }
+
+    @After
+    public void tearDown() {
+        if (mOrientationRequestSession != null) {
+            mOrientationRequestSession.close();
+        }
+    }
+
     @Test
     @AppModeFull // Instant apps cannot create notifications
     public void testLightStatusBarIcons() throws Throwable {
diff --git a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
index c890889..60b03b7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
@@ -16,8 +16,18 @@
 
 package android.telecom.cts;
 
+import static android.media.AudioManager.MODE_IN_CALL;
+import static android.media.AudioManager.MODE_IN_COMMUNICATION;
+import static android.telecom.cts.TestUtils.SELF_MANAGED_ACCOUNT_LABEL;
+import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1;
+import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
+import static android.telecom.cts.TestUtils.waitOnAllHandlers;
+
+import static org.junit.Assert.assertNotEquals;
+
 import android.content.Context;
 import android.database.Cursor;
+import android.graphics.Color;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.provider.CallLog;
@@ -35,14 +45,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.function.Predicate;
 
-import static android.media.AudioManager.MODE_IN_COMMUNICATION;
-import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1;
-import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_4;
-import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
-import static android.telecom.cts.TestUtils.waitOnAllHandlers;
-
-import static org.junit.Assert.assertNotEquals;
-
 /**
  * CTS tests for the self-managed {@link android.telecom.ConnectionService} APIs.
  * For more information about these APIs, see {@link android.telecom}, and
@@ -123,6 +125,33 @@
                 TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_3);
     }
 
+    public void testSelfManagedConnectionServiceRegistrationUnmodifiable() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
+        verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_1,
+                TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
+        PhoneAccount newPhoneAccount = PhoneAccount.builder(
+                        TEST_SELF_MANAGED_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL)
+                .setAddress(Uri.parse("sip:test@test.com"))
+                .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
+                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
+                        | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING
+                        | PhoneAccount.CAPABILITY_VIDEO_CALLING)
+                .setHighlightColor(Color.BLUE)
+                .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
+                .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+                .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
+                .build();
+        try {
+            mTelecomManager.registerPhoneAccount(newPhoneAccount);
+            fail("Self-managed phone account can be replaced to a call provider phone account!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
     private void verifyAccountRegistration(PhoneAccountHandle handle, PhoneAccount phoneAccount) {
         // The phone account is registered in the setup method.
         assertPhoneAccountRegistered(handle);
diff --git a/tests/tests/telephony/OWNERS b/tests/tests/telephony/OWNERS
index 89e4f4d..e0f294d 100644
--- a/tests/tests/telephony/OWNERS
+++ b/tests/tests/telephony/OWNERS
@@ -15,3 +15,5 @@
 tgunn@google.com
 tjstuart@google.com
 xiaotonj@google.com
+grantmenke@google.com
+pmadapurmath@google.com
diff --git a/tests/tests/telephony/current/Android.bp b/tests/tests/telephony/current/Android.bp
index dfe4bbb..30dce59 100644
--- a/tests/tests/telephony/current/Android.bp
+++ b/tests/tests/telephony/current/Android.bp
@@ -96,10 +96,3 @@
     ],
     per_testcase_directory: true,
 }
-
-filegroup {
-    name: "cts-telephony-utils",
-    srcs: [
-        "src/android/telephony/cts/TelephonyUtils.java",
-    ],
-}
diff --git a/tests/tests/telephony/current/mockmodem/Android.bp b/tests/tests/telephony/current/mockmodem/Android.bp
index 0e2a29a..091dc81 100644
--- a/tests/tests/telephony/current/mockmodem/Android.bp
+++ b/tests/tests/telephony/current/mockmodem/Android.bp
@@ -20,7 +20,6 @@
     name: "android.telephony.mockmodem",
     srcs: [
         "src/**/*.java",
-        ":cts-telephony-utils",
     ],
     libs: [
         "android-support-annotations",
@@ -34,6 +33,7 @@
         "android.hardware.radio.data-V1-java",
         "android.hardware.radio.messaging-V1-java",
         "android.hardware.radio.voice-V1-java",
+        "telephony-cts-utils",
     ],
 
     min_sdk_version: "30",
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java
index 8031994..5db9bf5 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemServiceConnector.java
@@ -22,7 +22,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.text.TextUtils;
 import android.util.Log;
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CallComposerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CallComposerTest.java
index c4a1e0c..6220f8f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CallComposerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CallComposerTest.java
@@ -30,6 +30,7 @@
 import android.os.UserHandle;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.cts.util.TelephonyUtils;
 import android.util.Pair;
 
 import androidx.annotation.NonNull;
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
index e4b06ae..07a6f39 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
@@ -30,6 +30,8 @@
 
 import static com.android.compatibility.common.util.AppOpsUtils.setOpMode;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -50,6 +52,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
 
 import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.TestThread;
@@ -59,13 +62,30 @@
 import org.junit.Test;
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 
+// TODO(b/221323753): replace remain junit asserts with Truth assert
 public class CarrierConfigManagerTest {
 
+    private static final long TIMEOUT_MILLIS = 5000;
+
+    private static final int TEST_SLOT_INDEX = 0;
+    private static final int TEST_SUB_ID = 1;
+    private static final int TEST_CARRIER_ID = 99;
+    private static final int TEST_PRECISE_CARRIER_ID = 100;
+
     private static final String CARRIER_NAME_OVERRIDE = "carrier_a";
     private CarrierConfigManager mConfigManager;
     private TelephonyManager mTelephonyManager;
@@ -203,6 +223,94 @@
                                 CarrierConfigManager.Gps.KEY_PREFIX));
     }
 
+    private void checkConfigSubset(PersistableBundle configSubset, PersistableBundle allConfigs,
+            String key) {
+        assertThat(configSubset).isNotNull();
+        assertThat(allConfigs).isNotNull();
+
+        // KEY_CARRIER_CONFIG_VERSION_STRING and KEY_CARRIER_CONFIG_APPLIED_BOOL should always
+        // be included
+        assertThat(configSubset.containsKey(
+                CarrierConfigManager.KEY_CARRIER_CONFIG_VERSION_STRING)).isTrue();
+        assertThat(configSubset.containsKey(
+                CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL)).isTrue();
+
+        Object value = allConfigs.get(key);
+        if (value instanceof PersistableBundle) {
+            assertThat(isEqual((PersistableBundle) configSubset.get(key),
+                    (PersistableBundle) value)).isTrue();
+        } else {
+            // value may be array types, compare with value equality instead of object equality
+            assertThat(configSubset.get(key)).isEqualTo(value);
+        }
+    }
+
+    // Checks for PersistableBundle equality
+    // Copied from com.android.server.vcn.util.PersistableBundleUtils
+    // TODO: move to a CTS common lib if other CTS cases also need PersistableBundle equality check
+    private static boolean isEqual(PersistableBundle left, PersistableBundle right) {
+        // Check for pointer equality & null equality
+        if (Objects.equals(left, right)) {
+            return true;
+        }
+
+        // If only one of the two is null, but not the other, not equal by definition.
+        if (Objects.isNull(left) != Objects.isNull(right)) {
+            return false;
+        }
+
+        if (!left.keySet().equals(right.keySet())) {
+            return false;
+        }
+
+        for (String key : left.keySet()) {
+            Object leftVal = left.get(key);
+            Object rightVal = right.get(key);
+
+            // Check for equality
+            if (Objects.equals(leftVal, rightVal)) {
+                continue;
+            } else if (Objects.isNull(leftVal) != Objects.isNull(rightVal)) {
+                // If only one of the two is null, but not the other, not equal by definition.
+                return false;
+            } else if (!Objects.equals(leftVal.getClass(), rightVal.getClass())) {
+                // If classes are different, not equal by definition.
+                return false;
+            }
+            if (leftVal instanceof PersistableBundle) {
+                if (!isEqual((PersistableBundle) leftVal, (PersistableBundle) rightVal)) {
+                    return false;
+                }
+            } else if (leftVal.getClass().isArray()) {
+                if (leftVal instanceof boolean[]) {
+                    if (!Arrays.equals((boolean[]) leftVal, (boolean[]) rightVal)) {
+                        return false;
+                    }
+                } else if (leftVal instanceof double[]) {
+                    if (!Arrays.equals((double[]) leftVal, (double[]) rightVal)) {
+                        return false;
+                    }
+                } else if (leftVal instanceof int[]) {
+                    if (!Arrays.equals((int[]) leftVal, (int[]) rightVal)) {
+                        return false;
+                    }
+                } else if (leftVal instanceof long[]) {
+                    if (!Arrays.equals((long[]) leftVal, (long[]) rightVal)) {
+                        return false;
+                    }
+                } else if (!Arrays.equals((Object[]) leftVal, (Object[]) rightVal)) {
+                    return false;
+                }
+            } else {
+                if (!Objects.equals(leftVal, rightVal)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
     @Test
     public void testGetConfig() {
         PersistableBundle config = mConfigManager.getConfig();
@@ -210,6 +318,48 @@
     }
 
     @Test
+    public void testGetConfig_withNullKeys() {
+        try {
+            mConfigManager.getConfig(null);
+            fail("getConfig with null keys should throw NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            mConfigManager.getConfig(CarrierConfigManager.KEY_CARRIER_CONFIG_VERSION_STRING, null);
+            fail("getConfig with null keys should throw NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    @Test
+    public void testGetConfig_withValidKeys() {
+        PersistableBundle allConfigs = mConfigManager.getConfig();
+        Set<String> allKeys = allConfigs.keySet();
+        assertThat(allKeys).isNotNull();
+
+        for (String key : allKeys) {
+            PersistableBundle configSubset = mConfigManager.getConfig(key);
+            checkConfigSubset(configSubset, allConfigs, key);
+        }
+    }
+
+    @Test
+    public void testGetConfig_keyWithoutDefaultValue() {
+        String keyWithDefaultValue = CarrierConfigManager.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
+        String keyWithoutDefaultValue = "random_key_for_testing";
+
+        PersistableBundle configSubset = mConfigManager.getConfig(keyWithoutDefaultValue);
+        assertThat(configSubset.isEmpty()).isFalse();
+        assertThat(configSubset.keySet()).doesNotContain(keyWithoutDefaultValue);
+
+        configSubset = mConfigManager.getConfig(keyWithDefaultValue, keyWithoutDefaultValue);
+        assertThat(configSubset.isEmpty()).isFalse();
+        assertThat(configSubset.keySet()).contains(keyWithDefaultValue);
+        assertThat(configSubset.keySet()).doesNotContain(keyWithoutDefaultValue);
+    }
+
+    @Test
     @AsbSecurityTest(cveBugId = 73136824)
     public void testRevokePermission() {
         PersistableBundle config;
@@ -240,6 +390,64 @@
         checkConfig(config);
     }
 
+    @Test
+    public void testGetConfigForSubId_withNullKeys() {
+        try {
+            mConfigManager.getConfigForSubId(SubscriptionManager.getDefaultSubscriptionId(), null);
+            fail("getConfigForSubId with null keys should throw NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            mConfigManager.getConfigForSubId(SubscriptionManager.getDefaultSubscriptionId(),
+                    CarrierConfigManager.KEY_CARRIER_CONFIG_VERSION_STRING, null);
+            fail("getConfigForSubId with null keys should throw NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    @Test
+    public void testGetConfigForSubId_withValidSingleKey() {
+        final int defaultSubId = SubscriptionManager.getDefaultSubscriptionId();
+        PersistableBundle allConfigs = mConfigManager.getConfigForSubId(defaultSubId);
+        Set<String> allKeys = allConfigs.keySet();
+        assertThat(allKeys).isNotNull();
+
+        for (String key : allKeys) {
+            PersistableBundle configSubset = mConfigManager.getConfigForSubId(defaultSubId, key);
+            checkConfigSubset(configSubset, allConfigs, key);
+        }
+    }
+
+    @Test
+    public void testGetConfigForSubId_withValidMultipleKeys() {
+        final int defaultSubId = SubscriptionManager.getDefaultSubscriptionId();
+        PersistableBundle allConfigs = mConfigManager.getConfigForSubId(defaultSubId);
+        Set<String> allKeys = allConfigs.keySet();
+        assertThat(allKeys).isNotNull();
+
+        // Just cover size in 2..10 to cover majority of cases while keeping this case quick
+        for (int size = 2; size <= 10; size++) {
+            Collection<List<String>> subsets = partitionSetWithSize(allKeys, size);
+            for (List<String> subset : subsets) {
+                String[] keyArray = new String[subset.size()];
+                keyArray = subset.toArray(keyArray);
+
+                PersistableBundle configSubset = mConfigManager.getConfigForSubId(defaultSubId,
+                        keyArray);
+                for (String key : keyArray) {
+                    checkConfigSubset(configSubset, allConfigs, key);
+                }
+            }
+        }
+    }
+
+    private Collection<List<String>> partitionSetWithSize(Set<String> keySet, int size) {
+        final AtomicInteger counter = new AtomicInteger(0);
+        return keySet.stream().collect(Collectors.groupingBy(s -> counter.getAndIncrement()))
+                .values();
+    }
+
     /**
      * Tests the CarrierConfigManager.notifyConfigChangedForSubId() API. This makes a call to
      * notifyConfigChangedForSubId() API and expects a SecurityException since the test apk is not signed
@@ -384,4 +592,79 @@
                     CarrierConfigManager.ImsVoice.KEY_AMRWB_PAYLOAD_DESCRIPTION_BUNDLE));
         }
     }
+
+    @Test
+    public void testRegisterCarrierConfigChangeListener_withNullExecutor() throws Exception {
+        // non-null listener
+        CarrierConfigManager.CarrierConfigChangeListener listener = (a, b, c, d) -> {
+        };
+        try {
+            mConfigManager.registerCarrierConfigChangeListener(null, listener);
+            fail("NullPointerException expected when register with null executor");
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    @Test
+    public void testRegisterCarrierConfigChangeListener_withNullListener() throws Exception {
+        // non-null executor
+        Executor executor = Runnable::run;
+        try {
+            mConfigManager.registerCarrierConfigChangeListener(executor, null);
+            fail("NullPointerException expected when register with null listener");
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    @Test
+    public void testUnregisterCarrierConfigChangeListener_withNullListener() throws Exception {
+        try {
+            mConfigManager.unregisterCarrierConfigChangeListener(null);
+            fail("NullPointerException expected when unregister with null listener");
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    @Test
+    public void testCarrierConfigChangeListener() throws Exception {
+        LinkedBlockingQueue<CarrierConfigChangeParams> queue = new LinkedBlockingQueue<>(1);
+
+        CarrierConfigManager.CarrierConfigChangeListener listener =
+                (slotIndex, subId, carrierId, preciseCarrierId) -> queue.offer(
+                        new CarrierConfigChangeParams(slotIndex, subId, carrierId,
+                                preciseCarrierId));
+
+        try {
+            mConfigManager.registerCarrierConfigChangeListener(Runnable::run, listener);
+
+            TelephonyRegistryManager telephonyRegistryManager = getContext().getSystemService(
+                    TelephonyRegistryManager.class);
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(telephonyRegistryManager,
+                    (trm) -> trm.notifyCarrierConfigChanged(TEST_SLOT_INDEX, TEST_SUB_ID,
+                            TEST_CARRIER_ID, TEST_PRECISE_CARRIER_ID));
+            CarrierConfigChangeParams result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+
+            assertEquals(TEST_SLOT_INDEX, result.mSlotIndex);
+            assertEquals(TEST_SUB_ID, result.mSubId);
+            assertEquals(TEST_CARRIER_ID, result.mCarrierId);
+            assertEquals(TEST_PRECISE_CARRIER_ID, result.mPreciseCarrierId);
+        } finally {
+            mConfigManager.unregisterCarrierConfigChangeListener(listener);
+        }
+    }
+
+    // A data value class to wrap the parameters of carrier config change
+    private class CarrierConfigChangeParams {
+        final int mSlotIndex;
+        final int mSubId;
+        final int mCarrierId;
+        final int mPreciseCarrierId;
+
+        CarrierConfigChangeParams(int slotIndex, int subId, int carrierId, int preciseCarrierId) {
+            mSlotIndex = slotIndex;
+            mSubId = subId;
+            mCarrierId = carrierId;
+            mPreciseCarrierId = preciseCarrierId;
+        }
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CarrierMessagingServiceWrapperTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CarrierMessagingServiceWrapperTest.java
index b8f4354..25468c3 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CarrierMessagingServiceWrapperTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CarrierMessagingServiceWrapperTest.java
@@ -30,6 +30,7 @@
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.cts.util.TelephonyUtils;
 
 import androidx.test.InstrumentationRegistry;
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
index fac2067..d529409 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -47,6 +47,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.util.Log;
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
index 59771fe..6f6d5c4 100755
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
@@ -60,6 +60,7 @@
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.cts.util.TelephonyUtils;
 import android.text.TextUtils;
 import android.util.Log;
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsMessageTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsMessageTest.java
index bd060b9..b8c89d8 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsMessageTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsMessageTest.java
@@ -16,7 +16,7 @@
 
 package android.telephony.cts;
 
-import static android.telephony.cts.TelephonyUtils.hexStringToByteArray;
+import static android.telephony.cts.util.TelephonyUtils.hexStringToByteArray;
 
 import static androidx.test.InstrumentationRegistry.getContext;
 
@@ -35,6 +35,7 @@
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.cts.util.TelephonyUtils;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
old mode 100755
new mode 100644
index 4029c50..b1688ff
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -23,15 +23,19 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
+import android.Manifest;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.UiAutomation;
@@ -51,11 +55,13 @@
 import android.os.ParcelUuid;
 import android.os.PersistableBundle;
 import android.os.Process;
+import android.os.UserHandle;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
 import android.telephony.TelephonyManager;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsMmTelManager;
@@ -266,6 +272,15 @@
     }
 
     @Test
+    public void testGetAllSubscriptionInfoList() throws Exception {
+        List<SubscriptionInfo> allSubInfoList = ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mSm, SubscriptionManager::getAllSubscriptionInfoList);
+        SubscriptionInfo subInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
+                (sm) -> sm.getActiveSubscriptionInfo(mSubId));
+        assertThat(allSubInfoList).contains(subInfo);
+    }
+
+    @Test
     public void testIsActiveSubscriptionId() throws Exception {
         assertTrue(mSm.isActiveSubscriptionId(mSubId));
     }
@@ -279,6 +294,12 @@
     }
 
     @Test
+    public void testGetSubscriptionId() throws Exception {
+        int slotId = SubscriptionManager.getSlotIndex(mSubId);
+        assertThat(SubscriptionManager.getSubscriptionId(slotId)).isEqualTo(mSubId);
+    }
+
+    @Test
     public void testGetResourcesForSubId() {
         Resources r = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
                 (sm) -> sm.getResourcesForSubId(InstrumentationRegistry.getContext(), mSubId));
@@ -1323,6 +1344,44 @@
         }
     }
 
+    @Test
+    public void testSetAndGetSubscriptionUserHandle() throws Exception {
+        // Throws IllegalArgumentException as SubscriptionId is invalid.
+        assertThrows(IllegalArgumentException.class,
+                () -> mSm.setSubscriptionUserHandle(-1, UserHandle.SYSTEM));
+
+        // Throws IllegalArgumentException as SubscriptionId is invalid.
+        assertThrows(IllegalArgumentException.class, () -> mSm.getSubscriptionUserHandle(-1));
+
+        // Throws SecurityException as we do not have MANAGE_SUBSCRIPTION_USER_ASSOCIATION
+        // permission.
+        assertThrows(SecurityException.class,
+                () -> mSm.setSubscriptionUserHandle(mSubId, UserHandle.SYSTEM));
+
+        // Throws SecurityException as we do not have MANAGE_SUBSCRIPTION_USER_ASSOCIATION
+        // permission.
+        assertThrows(SecurityException.class, () -> mSm.getSubscriptionUserHandle(mSubId));
+
+        // Set and get user handle with MANAGE_SUBSCRIPTION_USER_ASSOCIATION permission.
+        try {
+            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                    .adoptShellPermissionIdentity(
+                            Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+            UserHandle originalUserHandle = mSm.getSubscriptionUserHandle(mSubId);
+
+            mSm.setSubscriptionUserHandle(mSubId, null);
+            assertThat(mSm.getSubscriptionUserHandle(mSubId)).isEqualTo(null);
+
+            mSm.setSubscriptionUserHandle(mSubId, UserHandle.SYSTEM);
+            assertThat(mSm.getSubscriptionUserHandle(mSubId)).isEqualTo(UserHandle.SYSTEM);
+
+            mSm.setSubscriptionUserHandle(mSubId, originalUserHandle);
+        } finally {
+            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                    .dropShellPermissionIdentity();
+        }
+    }
+
     @Nullable
     private PersistableBundle getBundleFromBackupData(byte[] data) {
         try (ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
index 5971976..8c716b5 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
@@ -52,6 +52,7 @@
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyManager.DataEnabledReason;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.text.TextUtils;
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 555b5e9..c5b3762 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -99,6 +99,7 @@
 import android.telephony.UiccPortInfo;
 import android.telephony.UiccSlotInfo;
 import android.telephony.UiccSlotMapping;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.NetworkSlicingConfig;
 import android.telephony.emergency.EmergencyNumber;
@@ -3622,6 +3623,7 @@
 
             ModemActivityInfo diff = activityInfo1.getDelta(activityInfo2);
             assertNotNull(diff);
+            assertTrue("two activityInfo are identical", !activityInfo1.equals(activityInfo2));
             assertTrue("diff is" + diff, diff.isValid() || diff.isEmpty());
         } finally {
             InstrumentationRegistry.getInstrumentation().getUiAutomation()
@@ -4021,6 +4023,38 @@
     }
 
     @Test
+    public void testAutoDataSwitchPolicy() {
+        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));
+
+        ShellIdentityUtils.ShellPermissionMethodHelper<Boolean, TelephonyManager> getPolicyHelper =
+                (tm) -> tm.isMobileDataPolicyEnabled(
+                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
+
+        boolean autoDatSwitchAllowed = ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mTelephonyManager, getPolicyHelper);
+
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
+                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+                        !autoDatSwitchAllowed));
+
+        waitForMs(500);
+        assertNotEquals(autoDatSwitchAllowed,
+                ShellIdentityUtils.invokeMethodWithShellPermissions(
+                        mTelephonyManager, getPolicyHelper));
+
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
+                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+                        autoDatSwitchAllowed));
+
+        waitForMs(500);
+        assertEquals(autoDatSwitchAllowed,
+                ShellIdentityUtils.invokeMethodWithShellPermissions(
+                        mTelephonyManager, getPolicyHelper));
+    }
+
+    @Test
     public void testGetCdmaEnhancedRoamingIndicatorDisplayNumber() {
         assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CDMA));
 
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/DefaultSmsAppHelper.java b/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
similarity index 86%
rename from tests/tests/telephonyprovider/src/android/telephonyprovider/cts/DefaultSmsAppHelper.java
rename to tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
index 0a433b0..a2fe9d2 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/DefaultSmsAppHelper.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.telephonyprovider.cts;
+package android.telephony.cts.util;
 
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
@@ -34,8 +34,8 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 
-class DefaultSmsAppHelper {
-    static void ensureDefaultSmsApp() {
+public class DefaultSmsAppHelper {
+    public static void ensureDefaultSmsApp() {
         if (!hasTelephony() || !hasSms()) {
             return;
         }
@@ -71,7 +71,7 @@
         }
     }
 
-    static void stopBeingDefaultSmsApp() {
+    public static void stopBeingDefaultSmsApp() {
         if (!hasSms()) {
             return;
         }
@@ -106,17 +106,19 @@
         }
     }
 
-    static void assumeTelephony() {
+    public static void assumeTelephony() {
         Assume.assumeTrue(hasTelephony());
     }
 
-    static boolean hasTelephony() {
+    public static boolean hasTelephony() {
         Context context = ApplicationProvider.getApplicationContext();
         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
     }
 
-    static boolean hasSms() {
-        TelephonyManager telephonyManager = (TelephonyManager) ApplicationProvider.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
+    public static boolean hasSms() {
+        TelephonyManager telephonyManager = (TelephonyManager)
+                ApplicationProvider.getApplicationContext().getSystemService(
+                        Context.TELEPHONY_SERVICE);
         return telephonyManager.isSmsCapable();
     }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java b/tests/tests/telephony/current/src/android/telephony/cts/util/TelephonyUtils.java
similarity index 99%
rename from tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java
rename to tests/tests/telephony/current/src/android/telephony/cts/util/TelephonyUtils.java
index 90ed0b6..dccfc21 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/util/TelephonyUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.telephony.cts;
+package android.telephony.cts.util;
 
 import android.app.Instrumentation;
 import android.os.ParcelFileDescriptor;
diff --git a/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java b/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java
index f8e9508..4a9158c 100644
--- a/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java
@@ -30,7 +30,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.UiccCardInfo;
 import android.telephony.UiccPortInfo;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccInfo;
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
index 985aca9..cc6da06 100644
--- a/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
@@ -29,7 +29,7 @@
 import android.os.AsyncTask;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.gba.UaSecurityProtocolIdentifier;
 import android.util.Log;
 
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/EabBulkCapabilityUpdaterTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/EabBulkCapabilityUpdaterTest.java
index 284f515..0e0ac48 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/EabBulkCapabilityUpdaterTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/EabBulkCapabilityUpdaterTest.java
@@ -34,15 +34,13 @@
 import android.content.IntentFilter;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.HandlerThread;
-import android.os.Looper;
 import android.os.PersistableBundle;
 import android.provider.ContactsContract;
 import android.telecom.PhoneAccount;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsRcsManager;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java
index ba74fc9..be384de 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/EabControllerTest.java
@@ -37,7 +37,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ProvisioningManager;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
index 4f902a2..80c7a75 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
@@ -39,7 +39,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.cts.InCallServiceStateValidator;
 import android.telephony.cts.InCallServiceStateValidator.InCallServiceCallbacks;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.MmTelFeature;
 import android.telephony.ims.stub.ImsFeatureConfiguration;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
index a994d98..4519c0a 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
@@ -23,9 +23,9 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
-import android.telephony.cts.TelephonyUtils;
 import android.telephony.cts.externalimsservice.ITestExternalImsService;
 import android.telephony.cts.externalimsservice.TestExternalImsService;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.stub.ImsFeatureConfiguration;
 import android.text.TextUtils;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index e799fa0..94699f1 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -43,7 +43,7 @@
 import android.telephony.cts.AsyncSmsMessageListener;
 import android.telephony.cts.CarrierCapability;
 import android.telephony.cts.SmsReceiverHelper;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsMmTelManager;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
index 178fa18..8e6d95b 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
@@ -37,7 +37,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.ims.DelegateRegistrationState;
 import android.telephony.ims.DelegateRequest;
 import android.telephony.ims.FeatureTagState;
diff --git a/tests/tests/telephony2/Android.bp b/tests/tests/telephony2/Android.bp
index 450803f..bba2263 100644
--- a/tests/tests/telephony2/Android.bp
+++ b/tests/tests/telephony2/Android.bp
@@ -22,10 +22,10 @@
     static_libs: [
         "ctstestrunner-axt",
         "compatibility-device-util-axt",
+        "telephony-cts-utils",
     ],
     srcs: [
-      "src/**/*.java",
-      ":cts-telephony-utils"
+        "src/**/*.java",
     ],
     sdk_version: "test_current",
     // Tag this module as a cts test artifact
@@ -37,4 +37,4 @@
         "android.test.runner",
         "android.test.base",
     ],
-}
\ No newline at end of file
+}
diff --git a/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java b/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java
index 25cd10c..b038d4c 100644
--- a/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java
+++ b/tests/tests/telephony2/src/android/telephony2/cts/CallStateListenerPermissionTest.java
@@ -30,7 +30,7 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
diff --git a/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java b/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java
index e645537..6c99e53 100644
--- a/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java
+++ b/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerNoPermissionTest.java
@@ -21,7 +21,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 
 import androidx.test.InstrumentationRegistry;
 
diff --git a/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerReadPhoneStatePermissionTest.java b/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerReadPhoneStatePermissionTest.java
index 214a3f7..d8a9c3c 100644
--- a/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerReadPhoneStatePermissionTest.java
+++ b/tests/tests/telephony2/src/android/telephony2/cts/TelephonyManagerReadPhoneStatePermissionTest.java
@@ -26,7 +26,7 @@
 import android.telecom.TelecomManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 import android.telephony.emergency.EmergencyNumber;
 
 import androidx.test.InstrumentationRegistry;
diff --git a/tests/tests/telephony5/Android.bp b/tests/tests/telephony5/Android.bp
index c1833ee..944093a 100644
--- a/tests/tests/telephony5/Android.bp
+++ b/tests/tests/telephony5/Android.bp
@@ -23,16 +23,15 @@
         "ctstestrunner-axt",
         "compatibility-device-util-axt",
         "androidx.test.ext.junit",
-
-                "androidx.heifwriter_heifwriter",
-                "androidx.test.core",
-                "compatibility-device-util-axt",
-                "junit",
-                "platform-test-annotations",
+        "androidx.heifwriter_heifwriter",
+        "androidx.test.core",
+        "compatibility-device-util-axt",
+        "junit",
+        "platform-test-annotations",
+        "telephony-cts-utils",
     ],
     srcs: [
-      "src/**/*.java",
-      ":cts-telephony-utils"
+        "src/**/*.java",
     ],
     sdk_version: "test_current",
     // Tag this module as a cts test artifact
@@ -44,4 +43,4 @@
         "android.test.runner",
         "android.test.base",
     ],
-}
\ No newline at end of file
+}
diff --git a/tests/tests/telephony5/src/android/telephony5/cts/TelephonyManagerReadNonDangerousPermissionTest.java b/tests/tests/telephony5/src/android/telephony5/cts/TelephonyManagerReadNonDangerousPermissionTest.java
index 1ddba2c..778e0ed 100644
--- a/tests/tests/telephony5/src/android/telephony5/cts/TelephonyManagerReadNonDangerousPermissionTest.java
+++ b/tests/tests/telephony5/src/android/telephony5/cts/TelephonyManagerReadNonDangerousPermissionTest.java
@@ -22,7 +22,7 @@
 import android.content.pm.PackageManager;
 import android.platform.test.annotations.AppModeFull;
 import android.telephony.TelephonyManager;
-import android.telephony.cts.TelephonyUtils;
+import android.telephony.cts.util.TelephonyUtils;
 
 import androidx.test.InstrumentationRegistry;
 
diff --git a/tests/tests/telephonyprovider/Android.bp b/tests/tests/telephonyprovider/Android.bp
index 90b02ae..ca58247 100644
--- a/tests/tests/telephonyprovider/Android.bp
+++ b/tests/tests/telephonyprovider/Android.bp
@@ -30,6 +30,7 @@
         "androidx.test.rules",
         "androidx.test.core",
         "truth-prebuilt",
+        "telephony-cts-utils",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/CellBroadcastProviderTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/CellBroadcastProviderTest.java
index 8218ce4..6773c11 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/CellBroadcastProviderTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/CellBroadcastProviderTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.hasTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.hasTelephony;
 
 import android.content.ContentResolver;
 import android.provider.Telephony;
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
index d2e6fd0..2d2c140 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -27,6 +27,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.Telephony;
+import android.telephony.cts.util.DefaultSmsAppHelper;
 
 import androidx.test.filters.SmallTest;
 
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
index fc5bbbd..ca1f01a 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -28,6 +28,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.Telephony;
+import android.telephony.cts.util.DefaultSmsAppHelper;
 
 import com.android.compatibility.common.util.ApiTest;
 
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
index 7748400..89b27ef 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -36,6 +36,7 @@
 import android.provider.Telephony.Mms.Outbox;
 import android.provider.Telephony.Mms.Sent;
 import android.provider.Telephony.Sms;
+import android.telephony.cts.util.DefaultSmsAppHelper;
 
 import androidx.test.filters.SmallTest;
 
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
index ebecd8a..05e52ea 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Conversations;
+import android.telephony.cts.util.DefaultSmsAppHelper;
 
 import androidx.test.filters.SmallTest;
 
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
index 87b08b9c..f40f4d7 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -31,6 +31,8 @@
 import android.net.Uri;
 
 import android.provider.Telephony;
+import android.telephony.SubscriptionManager;
+import android.telephony.cts.util.DefaultSmsAppHelper;
 
 import androidx.test.filters.SmallTest;
 
@@ -239,7 +241,8 @@
             cursor.getInt(cursor.getColumnIndex(Telephony.Sms.LOCKED))).isEqualTo(0);
 
         assertThat(
-            cursor.getInt(cursor.getColumnIndex(Telephony.Sms.SUBSCRIPTION_ID))).isEqualTo(-1);
+            cursor.getInt(cursor.getColumnIndex(Telephony.Sms.SUBSCRIPTION_ID))).isEqualTo(
+                SubscriptionManager.getDefaultSmsSubscriptionId());
 
         assertThat(
             cursor.getInt(cursor.getColumnIndex(Telephony.Sms.ERROR_CODE))).isEqualTo(-1);
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
index 66365e2..cbab7ef 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
@@ -16,7 +16,7 @@
 
 package android.telephonyprovider.cts;
 
-import static android.telephonyprovider.cts.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -28,6 +28,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.Telephony;
+import android.telephony.cts.util.DefaultSmsAppHelper;
 
 import androidx.test.filters.SmallTest;
 
diff --git a/tests/tests/text/src/android/text/cts/EmojiConsistencyTest.java b/tests/tests/text/src/android/text/cts/EmojiConsistencyTest.java
new file mode 100644
index 0000000..3e159d0
--- /dev/null
+++ b/tests/tests/text/src/android/text/cts/EmojiConsistencyTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.text.cts;
+
+import static org.junit.Assert.assertNotNull;
+
+
+import android.text.EmojiConsistency;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Set;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EmojiConsistencyTest {
+
+    @Test
+    public void whenCallingCodepointExclusions_returnsNonNull() {
+        Set<int[]> result = EmojiConsistency.getEmojiConsistencySet();
+        assertNotNull("CodepointExclusions.getExcludedCodepoints() != null", result);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
index 7a91ab9..08666e2 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
@@ -81,7 +81,9 @@
         }
 
         window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
-                View.SYSTEM_UI_FLAG_FULLSCREEN
+                View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
+                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
         window.decorView.keepScreenOn = true
         mHandler = RenderSpecHandler()
 
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 028c6b7..8de86d3 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -18,10 +18,12 @@
 
 import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
 import static android.ipsec.ike.cts.IkeTunUtils.PortPair;
+import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -56,6 +58,7 @@
 import android.net.vcn.cts.TestNetworkWrapper.VcnTestNetworkCallback;
 import android.net.vcn.cts.TestNetworkWrapper.VcnTestNetworkCallback.CapabilitiesChangedEvent;
 import android.os.ParcelUuid;
+import android.os.PersistableBundle;
 import android.os.SystemClock;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -137,6 +140,8 @@
                         VcnGatewayConnectionConfigTest.buildVcnGatewayConnectionConfigBase()
                                 .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
                                 .setVcnUnderlyingNetworkPriorities(nwTemplate)
+                                .addGatewayOption(
+                                        VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY)
                                 .build());
     }
 
@@ -487,6 +492,155 @@
         }
     }
 
+    @Test
+    public void testSetVcnConfigOnTestNetworkAndHandleDataStall() throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        try (TestNetworkWrapper testNetworkWrapper =
+                createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp, cellNetwork, cellNetworkCb, testNetworkWrapper);
+
+                        mConnectivityManager.simulateDataStall(
+                                DETECTION_METHOD_DNS_EVENTS,
+                                System.currentTimeMillis(),
+                                vcnSetupResult.vcnNetwork,
+                                new PersistableBundle() /* extra data stall info; unused */);
+
+                        injectAndVerifyIkeMobikePackets(testNetworkWrapper.ikeTunUtils);
+
+                        clearVcnConfigsAndVerifyNetworkTeardown(
+                                subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                    });
+        }
+    }
+
+    private class NetworkSelectionTestNetworkParams {
+        public final boolean isMetered;
+
+        NetworkSelectionTestNetworkParams(boolean isMetered) {
+            this.isMetered = isMetered;
+        }
+    }
+
+    private TestNetworkWrapper createTestNetworkForNetworkSelection(
+            int subId, NetworkSelectionTestNetworkParams params) throws Exception {
+        return createTestNetworkWrapper(params.isMetered, subId, LOCAL_ADDRESS);
+    }
+
+    private void verifyVcnMigratesToPreferredUnderlyingNetwork(
+            VcnConfig vcnConfig,
+            NetworkSelectionTestNetworkParams lessPreferred,
+            NetworkSelectionTestNetworkParams preferred)
+            throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        // Start on a less preferred network.
+        try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+                createTestNetworkForNetworkSelection(subId, lessPreferred)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp,
+                                        cellNetwork,
+                                        cellNetworkCb,
+                                        vcnConfig,
+                                        testNetworkWrapperLessPreferred);
+
+                        // Then bring up a more preferred network, and expect to switch to it.
+                        try (TestNetworkWrapper testNetworkWrapperPreferred =
+                                createTestNetworkForNetworkSelection(subId, preferred)) {
+                            injectAndVerifyIkeMobikePackets(
+                                    testNetworkWrapperPreferred.ikeTunUtils);
+
+                            clearVcnConfigsAndVerifyNetworkTeardown(
+                                    subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                        }
+                    });
+        }
+    }
+
+    private void verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+            VcnConfig vcnConfig,
+            NetworkSelectionTestNetworkParams lessPreferred,
+            NetworkSelectionTestNetworkParams preferred)
+            throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        // Start on a more preferred network.
+        try (TestNetworkWrapper testNetworkWrapperPreferred =
+                createTestNetworkForNetworkSelection(subId, preferred)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp,
+                                        cellNetwork,
+                                        cellNetworkCb,
+                                        vcnConfig,
+                                        testNetworkWrapperPreferred);
+
+                        // Then bring up a less preferred network, and expect the VCN underlying
+                        // network does not change.
+                        try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+                                createTestNetworkForNetworkSelection(subId, lessPreferred)) {
+                            injectAndVerifyIkeDpdPackets(
+                                    testNetworkWrapperPreferred.ikeTunUtils,
+                                    vcnSetupResult.ikeExchangePortPair);
+
+                            clearVcnConfigsAndVerifyNetworkTeardown(
+                                    subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                        }
+                    });
+        }
+    }
+
+    private void verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+            VcnConfig vcnConfig,
+            NetworkSelectionTestNetworkParams lessPreferred,
+            NetworkSelectionTestNetworkParams preferred)
+            throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        // Start on a more preferred network
+        try (TestNetworkWrapper testNetworkWrapperPreferred =
+                createTestNetworkForNetworkSelection(subId, preferred)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp,
+                                        cellNetwork,
+                                        cellNetworkCb,
+                                        vcnConfig,
+                                        testNetworkWrapperPreferred);
+
+                        // Bring up a less preferred network
+                        try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+                                createTestNetworkForNetworkSelection(subId, lessPreferred)) {
+                            // Teardown the preferred network
+                            testNetworkWrapperPreferred.close();
+                            testNetworkWrapperPreferred.vcnNetworkCallback.waitForLost();
+
+                            // Verify the VCN switches to the remaining less preferred network
+                            injectAndVerifyIkeMobikePackets(
+                                    testNetworkWrapperLessPreferred.ikeTunUtils);
+
+                            clearVcnConfigsAndVerifyNetworkTeardown(
+                                    subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                        }
+                    });
+        }
+    }
+
     private VcnConfig createVcnConfigPrefersMetered() throws Exception {
         final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
         nwTemplates.add(
@@ -497,98 +651,29 @@
     }
 
     @Test
-    public void testVcnMigratesToPreferredUnderlyingNetwork() throws Exception {
-        final int subId = verifyAndGetValidDataSubId();
-        final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
-        // Start on NOT_METERED, less preferred network.
-        try (TestNetworkWrapper testNetworkWrapperNotMetered =
-                createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
-            verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
-                final VcnSetupResult vcnSetupResult =
-                    setupAndGetVcnNetwork(
-                        subGrp,
-                        cellNetwork,
-                        cellNetworkCb,
-                        vcnConfig,
-                        testNetworkWrapperNotMetered);
-
-                // Then bring up a more preferred network, and expect to switch to it.
-                try (TestNetworkWrapper testNetworkWrapperMetered =
-                        createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
-                    injectAndVerifyIkeMobikePackets(testNetworkWrapperMetered.ikeTunUtils);
-
-                    clearVcnConfigsAndVerifyNetworkTeardown(
-                            subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
-                }
-            });
-        }
+    public void testVcnMigratesToPreferredUnderlyingNetwork_preferMetered() throws Exception {
+        verifyVcnMigratesToPreferredUnderlyingNetwork(
+                createVcnConfigPrefersMetered(),
+                new NetworkSelectionTestNetworkParams(false /* isMetered */),
+                new NetworkSelectionTestNetworkParams(true /* isMetered */));
     }
 
     @Test
-    public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork() throws Exception {
-        final int subId = verifyAndGetValidDataSubId();
-        final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
-        // Start on METERED, more preferred network
-        try (TestNetworkWrapper testNetworkWrapperMetered =
-                createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
-            verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
-                final VcnSetupResult vcnSetupResult =
-                        setupAndGetVcnNetwork(
-                                subGrp,
-                                cellNetwork,
-                                cellNetworkCb,
-                                vcnConfig,
-                                testNetworkWrapperMetered);
-
-                // Then bring up a less preferred network, and expect the VCN underlying
-                // network does not change.
-                try (TestNetworkWrapper testNetworkWrapperNotMetered =
-                        createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
-                    injectAndVerifyIkeDpdPackets(
-                            testNetworkWrapperMetered.ikeTunUtils,
-                            vcnSetupResult.ikeExchangePortPair);
-
-                    clearVcnConfigsAndVerifyNetworkTeardown(
-                            subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
-                }
-            });
-        }
+    public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferMetered()
+            throws Exception {
+        verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+                createVcnConfigPrefersMetered(),
+                new NetworkSelectionTestNetworkParams(false /* isMetered */),
+                new NetworkSelectionTestNetworkParams(true /* isMetered */));
     }
 
     @Test
-    public void testVcnMigratesAfterPreferredUnderlyingNetworkDies() throws Exception {
-        final int subId = verifyAndGetValidDataSubId();
-        final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
-        // Start on METERED, more preferred network
-        try (TestNetworkWrapper testNetworkWrapperMetered =
-                createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
-            verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
-                final VcnSetupResult vcnSetupResult =
-                        setupAndGetVcnNetwork(
-                                subGrp,
-                                cellNetwork,
-                                cellNetworkCb,
-                                vcnConfig,
-                                testNetworkWrapperMetered);
-
-                // Bring up a NOT_METERED, less preferred network
-                try (TestNetworkWrapper testNetworkWrapperNotMetered =
-                        createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
-                    // Teardown the preferred network
-                    testNetworkWrapperMetered.close();
-                    testNetworkWrapperMetered.vcnNetworkCallback.waitForLost();
-
-                    // Verify the VCN switches to the remaining NOT_METERED network
-                    injectAndVerifyIkeMobikePackets(testNetworkWrapperNotMetered.ikeTunUtils);
-
-                    clearVcnConfigsAndVerifyNetworkTeardown(
-                            subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
-                }
-            });
-        }
+    public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferMetered()
+            throws Exception {
+        verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+                createVcnConfigPrefersMetered(),
+                new NetworkSelectionTestNetworkParams(false /* isMetered */),
+                new NetworkSelectionTestNetworkParams(true /* isMetered */));
     }
 
     @Test
diff --git a/tests/tests/view/src/android/view/cts/OWNERS b/tests/tests/view/src/android/view/cts/OWNERS
index fae65c5..c352c1f 100644
--- a/tests/tests/view/src/android/view/cts/OWNERS
+++ b/tests/tests/view/src/android/view/cts/OWNERS
@@ -2,6 +2,7 @@
 per-file ASurfaceControlTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
 per-file AttachedSurfaceControlSyncTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
 per-file AttachedSurfaceControlTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
+per-file SetTouchableRegionTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
 per-file SurfaceControlTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
 per-file SurfaceViewSyncTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
 
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
index c89cdb8..9cff62b 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
@@ -72,6 +72,9 @@
         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
         mContent.getViewTreeObserver().addOnDrawListener(this);
         mContent.setOnApplyWindowInsetsListener(this);
+
+        //setDecorFitsSystemWindows to false will ignore the cutout
+        getWindow().setDecorFitsSystemWindows(false);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java b/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java
index ad73c21..2cf7b5c 100644
--- a/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java
+++ b/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java
@@ -16,14 +16,17 @@
 
 package android.view.cts;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
 
 import android.app.Activity;
+import android.app.ActivityOptions;
 import android.app.Instrumentation;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Region;
-import android.view.AttachedSurfaceControl;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
@@ -33,22 +36,18 @@
 import com.android.compatibility.common.util.CtsTouchUtils;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
+import androidx.test.core.app.ActivityScenario;
 import androidx.test.runner.AndroidJUnit4;
 
 @RunWith(AndroidJUnit4.class)
 public class SetTouchableRegionTest {
     private Instrumentation mInstrumentation;
     private Activity mActivity;
-    @Rule
-    public ActivityTestRule<CtsActivity> mActivityRule =
-        new ActivityTestRule<>(CtsActivity.class);
+    private ActivityScenario<CtsActivity> mScenario;
 
     class MotionRecordingView extends View {
         public MotionRecordingView(Context context) {
@@ -80,20 +79,28 @@
     @Before
     public void setup() {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
-        mActivity = mActivityRule.getActivity();
+        // Launch activity in fullscreen windowing mode
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(mInstrumentation.getTargetContext(), CtsActivity.class);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        mScenario = ActivityScenario.launch(intent, options.toBundle());
+        mScenario.onActivity(activity -> {
+            mActivity = activity;
+        });
     }
 
     void tapSync() {
         mInstrumentation.waitForIdleSync();
         assertFalse(mMotionRecordingView.gotEvent());
 
-        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mMotionRecordingView);
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mMotionRecordingView);
         mInstrumentation.waitForIdleSync();
     }
 
     @Test
     public void testClickthroughRegion() throws Throwable {
-        mActivityRule.runOnUiThread(() -> {
+        mScenario.onActivity(activity -> {
             mMotionRecordingView = new MotionRecordingView(mActivity);
             mActivity.setContentView(mMotionRecordingView);
         });
@@ -101,7 +108,7 @@
         // We have a view filling our entire hierarchy and so a tap should reach it
         assertTrue(mMotionRecordingView.gotEvent());
 
-        mActivityRule.runOnUiThread(() -> {
+        mScenario.onActivity(activity -> {
             mPopupView = new View(mActivity);
             PopupWindow popup = new PopupWindow(mPopupView,
                 ViewGroup.LayoutParams.FILL_PARENT,
@@ -114,7 +121,7 @@
         // and so the tap should not reach us
         assertFalse(mMotionRecordingView.gotEvent());
 
-        mActivityRule.runOnUiThread(() -> {
+        mScenario.onActivity(activity -> {
             mPopupView.getRootSurfaceControl().setTouchableRegion(new Region());
         });
         tapSync();
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
index c4f36b7..d1e388b 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
@@ -156,6 +156,12 @@
     }
 
     public void verifyScreenshot(PixelChecker pixelChecker, TestName name) {
+        int retries = 0;
+        int maxRetries = 2;
+        int numMatchingPixels = 0;
+        Rect bounds = null;
+        boolean success = false;
+
         // Wait for the stable insets update. The position of the surface view is in correct before
         // the update. Sometimes this callback isn't called, so we don't want to fail the test
         // because it times out.
@@ -163,33 +169,44 @@
             Log.w(TAG, "Insets animation wait timed out.");
         }
 
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        UiAutomation uiAutomation = mInstrumentation.getUiAutomation();
+        while (retries < maxRetries) {
+            final CountDownLatch countDownLatch = new CountDownLatch(1);
+            UiAutomation uiAutomation = mInstrumentation.getUiAutomation();
+            mHandler.post(() -> {
+                mScreenshot = uiAutomation.takeScreenshot(getWindow());
+                countDownLatch.countDown();
+            });
+
+            try {
+                countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS);
+            } catch (Exception e) {
+            }
+
+            assertNotNull(mScreenshot);
+
+            Bitmap swBitmap = mScreenshot.copy(Bitmap.Config.ARGB_8888, false);
+            mScreenshot.recycle();
+
+            numMatchingPixels = pixelChecker.getNumMatchingPixels(swBitmap);
+            bounds = pixelChecker.getBoundsToCheck(swBitmap);
+            success = pixelChecker.checkPixels(numMatchingPixels, swBitmap.getWidth(),
+                    swBitmap.getHeight());
+            if (!success) {
+                saveFailureCapture(swBitmap, name);
+                swBitmap.recycle();
+                retries++;
+                try {
+                    Thread.sleep(300);
+                } catch (InterruptedException e) {
+                }
+            } else {
+                swBitmap.recycle();
+                break;
+            }
+        }
         mHandler.post(() -> {
-            mScreenshot = uiAutomation.takeScreenshot(getWindow());
             mParent.removeAllViews();
-            countDownLatch.countDown();
         });
-
-        try {
-            countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS);
-        } catch (Exception e) {
-        }
-
-        assertNotNull(mScreenshot);
-
-        Bitmap swBitmap = mScreenshot.copy(Bitmap.Config.ARGB_8888, false);
-        mScreenshot.recycle();
-
-        int numMatchingPixels = pixelChecker.getNumMatchingPixels(swBitmap);
-        Rect bounds = pixelChecker.getBoundsToCheck(swBitmap);
-        boolean success = pixelChecker.checkPixels(numMatchingPixels, swBitmap.getWidth(),
-                swBitmap.getHeight());
-        if (!success) {
-            saveFailureCapture(swBitmap, name);
-        }
-        swBitmap.recycle();
-
         assertTrue("Actual matched pixels:" + numMatchingPixels
                 + " Bitmap size:" + bounds.width() + "x" + bounds.height(), success);
     }
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java
index 8ecdbd0..4f7cc13 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java
@@ -66,10 +66,10 @@
             }
             Trace.endSection();
 
-            boolean success = mPixelChecker.validatePlane(plane, mFrameNumber++, mBoundsToCheck,
-                    mWidth, mHeight);
 
             synchronized (mResultLock) {
+                boolean success = mPixelChecker.validatePlane(plane, mFrameNumber++, mBoundsToCheck,
+                        mWidth, mHeight);
                 mResultLock.notifyAll();
                 if (success) {
                     mResultSuccessFrames++;
@@ -152,8 +152,8 @@
             for (int i = 0; i < mFirstFailures.size(); i++) {
                 testResult.failures.put(mFirstFailures.keyAt(i), mFirstFailures.valueAt(i));
             }
+            mImageReader.close();
+            mWorkerThread.quitSafely();
         }
-        mImageReader.close();
-        mWorkerThread.quitSafely();
     }
 }
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceProximityTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceProximityTest.java
index 699a8f4..a47fb2b 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceProximityTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceProximityTest.java
@@ -28,7 +28,6 @@
 import android.os.Parcelable;
 import android.platform.test.annotations.AppModeFull;
 import android.provider.DeviceConfig;
-import android.service.attention.AttentionService;
 import android.service.voice.HotwordDetectedResult;
 import android.voiceinteraction.common.Utils;
 import android.voiceinteraction.service.EventPayloadParcelable;
@@ -39,9 +38,11 @@
 
 import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
+import com.android.compatibility.common.util.RequiredServiceRule;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -55,8 +56,11 @@
 @AppModeFull(reason = "No real use case for instant mode hotword detection service")
 public final class HotwordDetectionServiceProximityTest
         extends AbstractVoiceInteractionBasicTestCase {
-    /** TODO(b/247920386): Replace with the system constant. */
-    private static final boolean ENABLE_PROXIMITY_RESULT = false;
+    private static final String ATTENTION_SERVICE = "attention";
+
+    @ClassRule
+    public static final RequiredServiceRule ATTENTION_SERVICE_RULE =
+            new RequiredServiceRule(ATTENTION_SERVICE);
 
     @Rule
     public final DeviceConfigStateChangerRule mEnableAttentionManagerServiceRule =
@@ -65,15 +69,20 @@
                     SERVICE_ENABLED,
                     "true");
 
-    private static final String EXTRA_PROXIMITY_METERS =
-            "android.service.voice.extra.PROXIMITY_METERS";
+    private static final String EXTRA_PROXIMITY =
+            "android.service.voice.extra.PROXIMITY";
 
     private static Instrumentation sInstrumentation = InstrumentationRegistry.getInstrumentation();
 
     private static final String SERVICE_ENABLED = "service_enabled";
     private static final String FAKE_SERVICE_PACKAGE =
             HotwordDetectionServiceProximityTest.class.getPackage().getName();
-    private static final double SUCCESSFUL_PROXIMITY_DISTANCE = 1.0;
+    private static final double PROXIMITY_NEAR_METERS = 2.0;
+    private static final double PROXIMITY_FAR_METERS = 6.0;
+    private static final int PROXIMITY_UNKNOWN = -1;
+    private static final int PROXIMITY_NEAR = 1;
+    private static final int PROXIMITY_FAR = 2;
+    private static final boolean ENABLE_PROXIMITY_RESULT = true;
 
     @BeforeClass
     public static void enableAttentionService() throws InterruptedException {
@@ -106,7 +115,7 @@
                 null);
 
         // when proximity is unknown, proximity should not be returned.
-        CtsTestAttentionService.respondProximity(AttentionService.PROXIMITY_UNKNOWN);
+        CtsTestAttentionService.respondProximity(PROXIMITY_UNKNOWN);
 
         verifyProximityBundle(
                 performAndGetDetectionResult(mActivityTestRule, mContext,
@@ -114,14 +123,21 @@
                         Utils.HOTWORD_DETECTION_SERVICE_BASIC),
                 null);
 
-        // when proximity is known, proximity should be returned.
-        CtsTestAttentionService.respondProximity(SUCCESSFUL_PROXIMITY_DISTANCE);
+        CtsTestAttentionService.respondProximity(PROXIMITY_NEAR_METERS);
 
         verifyProximityBundle(
                 performAndGetDetectionResult(mActivityTestRule, mContext,
                         Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST,
                         Utils.HOTWORD_DETECTION_SERVICE_BASIC),
-                SUCCESSFUL_PROXIMITY_DISTANCE);
+                PROXIMITY_NEAR);
+
+        CtsTestAttentionService.respondProximity(PROXIMITY_FAR_METERS);
+
+        verifyProximityBundle(
+                performAndGetDetectionResult(mActivityTestRule, mContext,
+                        Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST,
+                        Utils.HOTWORD_DETECTION_SERVICE_BASIC),
+                PROXIMITY_FAR);
 
         testHotwordDetection(mActivityTestRule, mContext,
                 Utils.HOTWORD_DETECTION_SERVICE_DSP_DESTROY_DETECTOR,
@@ -164,7 +180,7 @@
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS,
                 Utils.HOTWORD_DETECTION_SERVICE_BASIC);
 
-        CtsTestAttentionService.respondProximity(AttentionService.PROXIMITY_UNKNOWN);
+        CtsTestAttentionService.respondProximity(PROXIMITY_UNKNOWN);
 
         verifyProximityBundle(
                 performAndGetDetectionResult(mActivityTestRule, mContext,
@@ -189,13 +205,13 @@
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS,
                 Utils.HOTWORD_DETECTION_SERVICE_BASIC);
 
-        CtsTestAttentionService.respondProximity(SUCCESSFUL_PROXIMITY_DISTANCE);
+        CtsTestAttentionService.respondProximity(PROXIMITY_NEAR_METERS);
 
         verifyProximityBundle(
                 performAndGetDetectionResult(mActivityTestRule, mContext,
                         Utils.HOTWORD_DETECTION_SERVICE_MIC_ONDETECT_TEST,
                         Utils.HOTWORD_DETECTION_SERVICE_BASIC),
-                SUCCESSFUL_PROXIMITY_DISTANCE);
+                PROXIMITY_NEAR);
 
         testHotwordDetection(mActivityTestRule, mContext,
                 Utils.HOTWORD_DETECTION_SERVICE_SOFTWARE_DESTROY_DETECTOR,
@@ -214,7 +230,7 @@
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS,
                 Utils.HOTWORD_DETECTION_SERVICE_BASIC);
 
-        CtsTestAttentionService.respondProximity(SUCCESSFUL_PROXIMITY_DISTANCE);
+        CtsTestAttentionService.respondProximity(PROXIMITY_FAR);
 
         verifyProximityBundle(
                 performAndGetDetectionResult(mActivityTestRule, mContext,
@@ -230,21 +246,16 @@
     }
 
     // simply check that the proximity values are equal.
-    private void verifyProximityBundle(Parcelable result, Double expected) {
+    private void verifyProximityBundle(Parcelable result, Integer expected) {
         assertThat(result).isInstanceOf(EventPayloadParcelable.class);
         HotwordDetectedResult hotwordDetectedResult =
                 ((EventPayloadParcelable) result).mHotwordDetectedResult;
         assertThat(hotwordDetectedResult).isNotNull();
         if (expected == null || !ENABLE_PROXIMITY_RESULT) {
-            assertThat(
-                    hotwordDetectedResult.getExtras().containsKey(EXTRA_PROXIMITY_METERS))
-                    .isFalse();
+            assertThat(hotwordDetectedResult.getExtras().containsKey(EXTRA_PROXIMITY)).isFalse();
         } else {
-            assertThat(
-                    hotwordDetectedResult.getExtras().containsKey(EXTRA_PROXIMITY_METERS))
-                    .isTrue();
-            assertThat(
-                    hotwordDetectedResult.getExtras().getDouble(EXTRA_PROXIMITY_METERS))
+            assertThat(hotwordDetectedResult.getExtras().containsKey(EXTRA_PROXIMITY)).isTrue();
+            assertThat(hotwordDetectedResult.getExtras().getInt(EXTRA_PROXIMITY))
                     .isEqualTo(expected);
         }
     }
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 01d866a..928dcf8 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -24,6 +24,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.KeyEvent;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.webkit.HttpAuthHandler;
 import android.webkit.RenderProcessGoneDetail;
 import android.webkit.SafeBrowsingResponse;
@@ -38,8 +39,6 @@
 import android.webkit.cts.WebViewSyncLoader.WaitForLoadedClient;
 import android.util.Pair;
 
-import androidx.test.filters.FlakyTest;
-
 import com.android.compatibility.common.util.NullWebViewUtils;
 import com.android.compatibility.common.util.PollingCheck;
 import com.google.common.util.concurrent.SettableFuture;
@@ -143,7 +142,6 @@
 
     // Verify shouldoverrideurlloading called on webview called via onCreateWindow
     // TODO(sgurun) upstream this test to Aw.
-    @FlakyTest(bugId = 253448914)
     public void testShouldOverrideUrlLoadingOnCreateWindow() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -160,56 +158,70 @@
 
         final WebView childWebView = mOnUiThread.createWebView();
 
-        WebViewOnUiThread childWebViewOnUiThread = new WebViewOnUiThread(childWebView);
-        mOnUiThread.setWebChromeClient(new WebChromeClient() {
-            @Override
-            public boolean onCreateWindow(
-                WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
-                WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
-                childWebView.setWebViewClient(childWebViewClient);
-                childWebView.getSettings().setJavaScriptEnabled(true);
-                transport.setWebView(childWebView);
-                getActivity().addContentView(childWebView, new ViewGroup.LayoutParams(
-                            ViewGroup.LayoutParams.FILL_PARENT,
-                            ViewGroup.LayoutParams.WRAP_CONTENT));
-                resultMsg.sendToTarget();
-                return true;
-            }
-        });
-        {
-          final int childCallCount = childWebViewClient.getShouldOverrideUrlLoadingCallCount();
-          mOnUiThread.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_TAG_URL));
+        try {
+            WebViewOnUiThread childWebViewOnUiThread = new WebViewOnUiThread(childWebView);
+            mOnUiThread.setWebChromeClient(new WebChromeClient() {
+                @Override
+                public boolean onCreateWindow(
+                        WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
+                    WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
+                    childWebView.setWebViewClient(childWebViewClient);
+                    childWebView.getSettings().setJavaScriptEnabled(true);
+                    transport.setWebView(childWebView);
+                    getActivity().addContentView(childWebView, new ViewGroup.LayoutParams(
+                                ViewGroup.LayoutParams.FILL_PARENT,
+                                ViewGroup.LayoutParams.WRAP_CONTENT));
+                    resultMsg.sendToTarget();
+                    return true;
+                }
+            });
+            {
+                final int childCallCount =
+                        childWebViewClient.getShouldOverrideUrlLoadingCallCount();
+                mOnUiThread.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_TAG_URL));
 
-          new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
-              @Override
-              protected boolean check() {
-                  return childWebViewClient.hasOnPageFinishedCalled();
-              }
-          }.run();
-          new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
-              @Override
-              protected boolean check() {
-                  return childWebViewClient.getShouldOverrideUrlLoadingCallCount() > childCallCount;
-              }
-          }.run();
-          assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.PAGE_WITH_LINK_URL),
-                  childWebViewClient.getLastShouldOverrideUrl());
+                new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+                    @Override
+                    protected boolean check() {
+                        return childWebViewClient.hasOnPageFinishedCalled();
+                    }
+                }.run();
+                new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+                    @Override
+                    protected boolean check() {
+                        return childWebViewClient
+                            .getShouldOverrideUrlLoadingCallCount() > childCallCount;
+                    }
+                }.run();
+                assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.PAGE_WITH_LINK_URL),
+                        childWebViewClient.getLastShouldOverrideUrl());
+            }
+
+            final int childCallCount =
+                    childWebViewClient.getShouldOverrideUrlLoadingCallCount();
+            final int mainCallCount = mainWebViewClient.getShouldOverrideUrlLoadingCallCount();
+            clickOnLinkUsingJs("link", childWebViewOnUiThread);
+            new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+                @Override
+                protected boolean check() {
+                    return childWebViewClient
+                        .getShouldOverrideUrlLoadingCallCount() > childCallCount;
+                }
+            }.run();
+            assertEquals(mainCallCount, mainWebViewClient.getShouldOverrideUrlLoadingCallCount());
+            // PAGE_WITH_LINK_URL has a link to BLANK_PAGE_URL (an arbitrary page
+            // also controlled by the test server)
+            assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_PAGE_URL),
+                    childWebViewClient.getLastShouldOverrideUrl());
+        } finally {
+            WebkitUtils.onMainThreadSync(() -> {
+                ViewParent parent = childWebView.getParent();
+                if (parent instanceof ViewGroup) {
+                    ((ViewGroup) parent).removeView(childWebView);
+                }
+                childWebView.destroy();
+            });
         }
-
-        final int childCallCount = childWebViewClient.getShouldOverrideUrlLoadingCallCount();
-        final int mainCallCount = mainWebViewClient.getShouldOverrideUrlLoadingCallCount();
-        clickOnLinkUsingJs("link", childWebViewOnUiThread);
-        new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
-            @Override
-            protected boolean check() {
-                return childWebViewClient.getShouldOverrideUrlLoadingCallCount() > childCallCount;
-            }
-        }.run();
-        assertEquals(mainCallCount, mainWebViewClient.getShouldOverrideUrlLoadingCallCount());
-        // PAGE_WITH_LINK_URL has a link to BLANK_PAGE_URL (an arbitrary page also controlled by the
-        // test server)
-        assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_PAGE_URL),
-                childWebViewClient.getLastShouldOverrideUrl());
     }
 
     private void clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread) {
diff --git a/tests/tests/widget/OWNERS b/tests/tests/widget/OWNERS
index 2f13877..0f25ac1 100644
--- a/tests/tests/widget/OWNERS
+++ b/tests/tests/widget/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 25700
-adamp@google.com
+aelias@google.com
 mount@google.com
+adamp@google.com
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index f75cabf..3d1a7a7 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -400,6 +400,8 @@
     </style>
 
     <style name="Theme.PopupWindowCtsActivity" parent="@android:style/Theme.Holo">
+        <item name="android:windowSwipeToDismiss">false</item>
+        <item name="android:windowLayoutInDisplayCutoutMode">never</item>
     </style>
 
     <style name="TextView_FontResource">
diff --git a/tests/tests/widget/res/values/themes.xml b/tests/tests/widget/res/values/themes.xml
index 938452e..374834a 100644
--- a/tests/tests/widget/res/values/themes.xml
+++ b/tests/tests/widget/res/values/themes.xml
@@ -25,7 +25,7 @@
         <item name="themeString">@string/remoteviews_theme_string</item>
     </style>
 
-    <style name="HorizontalScrollViewCtsActivityTheme" parent="@android:style/Theme.DeviceDefault">
+    <style name="HorizontalScrollViewCtsActivityTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
         <item name="android:windowSwipeToDismiss">false</item>
     </style>
 </resources>
diff --git a/tests/tests/widget/src/android/widget/cts/EditTextTest.java b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
index ca3d7db..c14f51f 100755
--- a/tests/tests/widget/src/android/widget/cts/EditTextTest.java
+++ b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
@@ -381,7 +381,7 @@
 
     private boolean isWatch() {
         return (mActivity.getResources().getConfiguration().uiMode
-                & Configuration.UI_MODE_TYPE_WATCH) == Configuration.UI_MODE_TYPE_WATCH;
+                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH;
     }
 
     @Test
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index c74f21b..d94667c 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -16,6 +16,8 @@
 
 package android.widget.cts;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -34,8 +36,10 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import android.app.Activity;
+import android.app.ActivityOptions;
 import android.app.Instrumentation;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -56,6 +60,7 @@
 import android.widget.TextView;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ActivityScenario;
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
@@ -89,6 +94,8 @@
 
     private AdapterView.OnItemClickListener mItemClickListener;
 
+    private ActivityScenario<ListPopupWindowCtsActivity> mScenario;
+
     /**
      * Item click listener that dismisses our <code>ListPopupWindow</code> when any item
      * is clicked. Note that this needs to be a separate class that is also protected (not
@@ -500,7 +507,7 @@
         final ListView popupListView = mPopupWindow.getListView();
         final Rect rect = new Rect();
         mPopupWindow.getBackground().getPadding(rect);
-        CtsTouchUtils.emulateTapOnView(instrumentation, mActivityRule, popupListView,
+        CtsTouchUtils.emulateTapOnView(instrumentation, null, popupListView,
                 -rect.left - 20, popupListView.getHeight() / 2);
 
         // At this point our popup should not be showing and should have notified its
@@ -515,6 +522,21 @@
 
     @Test
     public void testDismissalOutsideNonModal() {
+        // Close the activity that was launched by setup
+        mActivityRule.finishActivity();
+
+        // Launch activity in fullscreen windowing mode
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(mInstrumentation.getTargetContext(), ListPopupWindowCtsActivity.class);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        mScenario = ActivityScenario.launch(intent, options.toBundle());
+        mScenario.onActivity(activity -> {
+            mActivity = activity;
+            mActivity.getApplicationInfo().setEnableOnBackInvokedCallback(false);
+        });
+
         verifyDismissalViaTouch(false);
     }
 
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index bca2bc7..50ee3b1 100755
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -403,34 +403,6 @@
         TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
                 dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
                 false, Color.BLUE, 1, true);
-        waitForHasFocusMS(SPINNER_HAS_FOCUS_DELAY_MS);
-        // Dismiss the popup with the emulated back key
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-        // Verify that we're not showing the popup
-        PollingCheck.waitFor(() -> !mSpinnerDropdownMode.isPopupShowing());
-
-        // Set yellow background on the popup
-        mActivityRule.runOnUiThread(() ->
-                mSpinnerDropdownMode.setPopupBackgroundDrawable(
-                        mActivity.getDrawable(R.drawable.yellow_fill)));
-
-        // Use instrumentation to emulate a tap on the spinner to bring down its popup
-        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mSpinnerDropdownMode, () -> {
-            mSpinnerDropdownMode.performClick();
-        });
-        // Verify that we're showing the popup
-        PollingCheck.waitFor(() -> mSpinnerDropdownMode.isPopupShowing());
-        // And test its fill
-        dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
-        TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
-                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
-                false, Color.YELLOW, 1, true);
-
-        waitForHasFocusMS(SPINNER_HAS_FOCUS_DELAY_MS);
-        // Dismiss the popup with the emulated escape key
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ESCAPE);
-        // Verify that we're not showing the popup
-        PollingCheck.waitFor(() -> !mSpinnerDropdownMode.isPopupShowing());
     }
 
     @Test
@@ -450,38 +422,5 @@
         PollingCheck.waitFor(() -> mSpinnerDialogMode.isPopupShowing());
         // And test that getPopupBackground returns null
         assertNull(mSpinnerDialogMode.getPopupBackground());
-
-        // Dismiss the popup with the emulated back key
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-        // Verify that we're not showing the popup
-        PollingCheck.waitFor(() -> !mSpinnerDialogMode.isPopupShowing());
-
-        // Set yellow background on the popup
-        mActivityRule.runOnUiThread(() ->
-                mSpinnerDialogMode.setPopupBackgroundDrawable(
-                        mActivity.getDrawable(R.drawable.yellow_fill)));
-
-        // Use instrumentation to emulate a tap on the spinner to bring down its popup
-        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mSpinnerDialogMode, () -> {
-            mSpinnerDialogMode.performClick();
-        });
-        // Verify that we're showing the popup
-        PollingCheck.waitFor(() -> mSpinnerDialogMode.isPopupShowing());
-        // And test that getPopupBackground returns null
-        assertNull(mSpinnerDialogMode.getPopupBackground());
-
-        // Use emulated escape key to close popup
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ESCAPE);
-        // Verify that we're not showing the popup
-        PollingCheck.waitFor(() -> !mSpinnerDropdownMode.isPopupShowing());
-    }
-
-    private void waitForHasFocusMS(int milliseconds) {
-        try {
-            Thread.sleep(milliseconds);
-        } catch (InterruptedException e) {
-            fail("unexpected InterruptedException : "+ e);
-        }
-
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 38dedf6..ca8dfb0 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -64,6 +64,7 @@
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.compatibility.common.util.TestUtils;
@@ -989,7 +990,9 @@
      * us to wait a given amount of time to test that the limit has been enforced/lifted.
      */
     @Test
+    @ApiTest(apis = {"android.widget.Toast#show"})
     public void testRateLimitingToastsWhenInBackground() throws Throwable {
+        assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
         // enable rate limiting to test it
         SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
                 .setToastRateLimitingEnabled(true));
@@ -1051,7 +1054,9 @@
     }
 
     @Test
+    @ApiTest(apis = {"android.widget.Toast#show"})
     public void testAppWithUnlimitedToastsPermissionCanPostUnlimitedToasts() throws Throwable {
+        assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
         // enable rate limiting to test it
         SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
                 .setToastRateLimitingEnabled(true));
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
index 88457ca..3c1401d 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
@@ -200,13 +200,19 @@
 
     @After
     public void tearDown() throws Exception {
+        if (!WifiFeature.isWifiSupported(mContext)) {
+            return;
+        }
+
         // Re-enable networks.
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> {
-                    for (WifiConfiguration savedNetwork : mWifiManager.getConfiguredNetworks()) {
+                    for (WifiConfiguration savedNetwork :
+                            mWifiManager.getConfiguredNetworks()) {
                         mWifiManager.enableNetwork(savedNetwork.networkId, false);
                     }
                 });
+
         // Release the requests after the test.
         if (mNetworkCallback != null) {
             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
@@ -214,6 +220,7 @@
         if (mNrNetworkCallback != null) {
             mConnectivityManager.unregisterNetworkCallback(mNrNetworkCallback);
         }
+
         // Clear any existing app state after each test.
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.removeAppState(myUid(), mContext.getPackageName()));
@@ -304,4 +311,4 @@
         // Ensure that there is only 1 wifi connection available for apps.
         assertThat(mTestHelper.getNumWifiConnections()).isEqualTo(1);
     }
-}
\ No newline at end of file
+}
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 d459364..6d9bbe5 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -1884,6 +1884,7 @@
         TestSoftApCallback lohsSoftApCallback = new TestSoftApCallback(mLock);
         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         setWifiEnabled(false);
+        Thread.sleep(TEST_WAIT_DURATION_MS);
         boolean wifiEnabled = mWifiManager.isWifiEnabled();
         try {
             uiAutomation.adoptShellPermissionIdentity();
@@ -2725,6 +2726,11 @@
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
     public void testTetheredBridgedAp() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
         // check that softap bridged mode is supported by the device
         if (!mWifiManager.isBridgedApConcurrencySupported()) {
             return;
@@ -2789,6 +2795,11 @@
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
     public void testTetheredBridgedApWifiForcedChannel() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
         // check that softap bridged mode is supported by the device
         if (!mWifiManager.isBridgedApConcurrencySupported()) {
             return;
diff --git a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
index d73c707..4632d03 100644
--- a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
@@ -700,7 +700,50 @@
         } finally {
             manager.unregisterUiTranslationStateCallback(mockCallback);
         }
-        // TODO(b/191417938): add a test to verify startUiTranslation + Activity destroyed.
+    }
+
+    @Test
+    public void testActivityDestroyedWithoutFinishTranslation() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        UiTranslationManager manager =
+                sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+
+        // Register callback
+        final Executor executor = Executors.newSingleThreadExecutor();
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
+
+        try {
+            startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+            Mockito.verify(mockCallback, Mockito.times(1))
+                    .onStarted(any(ULocale.class), any(ULocale.class), any(String.class));
+
+            pauseUiTranslation(contentCaptureContext);
+
+            Mockito.verify(mockCallback, Mockito.times(1)).onPaused(any(String.class));
+
+            resumeUiTranslation(contentCaptureContext);
+
+            Mockito.verify(mockCallback, Mockito.times(1))
+                    .onResumed(any(ULocale.class), any(ULocale.class), any(String.class));
+
+            // Make sure onFinished will still be called if Activity is destroyed, even without a
+            // finishTranslation call.
+            mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+            mActivityScenario = null;
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+            Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+        } finally {
+            manager.unregisterUiTranslationStateCallback(mockCallback);
+        }
     }
 
     @Test
@@ -901,6 +944,45 @@
     }
 
     @Test
+    public void testCallbackRegisteredAfterActivityDestroyedWithoutFinishTranslation()
+            throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        UiTranslationManager manager =
+                sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+
+        startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+        pauseUiTranslation(contentCaptureContext);
+
+        resumeUiTranslation(contentCaptureContext);
+
+        // Note: No finishTranslation call; Activity is destroyed.
+        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        mActivityScenario = null;
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        // Register callback
+        final Executor executor = Executors.newSingleThreadExecutor();
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
+
+        try {
+            // Callback should receive no events.
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+            Mockito.verifyZeroInteractions(mockCallback);
+        } finally {
+            manager.unregisterUiTranslationStateCallback(mockCallback);
+        }
+    }
+
+    @Test
     public void testCallbackCalledOnceAfterDuplicateCalls() throws Throwable {
         final Pair<List<AutofillId>, ContentCaptureContext> result =
                 enableServicesAndStartActivityForTranslation();
diff --git a/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java b/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
index 748a704..d0f6adc 100644
--- a/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
+++ b/tests/video/src/android/video/cts/CodecDecoderPerformanceTest.java
@@ -23,6 +23,8 @@
 
 import androidx.test.filters.LargeTest;
 
+import com.android.compatibility.common.util.ApiTest;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -41,7 +43,7 @@
         super(decoderName, testFile, keyPriority, scalingFactor);
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{2}_{3})")
+    @Parameterized.Parameters(name = "{index}_{0}_{2}_{3}")
     public static Collection<Object[]> input() throws IOException {
         final String[] fileList = new String[]{
                 // Video - Filename
@@ -117,6 +119,8 @@
     /**
      * Validates performance of hardware accelerated video decoders
      */
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_PRIORITY",
+            "android.media.MediaFormat#KEY_OPERATING_RATE"})
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testPerformanceOfHardwareVideoDecoders() throws IOException, InterruptedException {
diff --git a/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java b/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
index 462c74b..ff3bf25 100644
--- a/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
+++ b/tests/video/src/android/video/cts/CodecEncoderPerformanceTest.java
@@ -24,6 +24,8 @@
 
 import androidx.test.filters.LargeTest;
 
+import com.android.compatibility.common.util.ApiTest;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -53,7 +55,7 @@
                 isAsync, maxBFrames);
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{2}_{3}_{5}_{6}_{7}_{8})")
+    @Parameterized.Parameters(name = "{index}_{0}_{2}_{3}_{5}_{6}_{7}_{8}")
     public static Collection<Object[]> input() throws IOException {
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // Filename, Recommended AVC bitrate
@@ -121,6 +123,8 @@
     /**
      * Validates performance of hardware accelerated video encoders
      */
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_PRIORITY",
+            "android.media.MediaFormat#KEY_OPERATING_RATE"})
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testPerformanceOfHardwareVideoEncoders() throws IOException, InterruptedException {
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
index c545707..e8902fd 100644
--- a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -42,6 +42,7 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.DeviceReportLog;
 import com.android.compatibility.common.util.MediaPerfUtils;
 import com.android.compatibility.common.util.MediaUtils;
@@ -303,6 +304,15 @@
         this.mMaxBFrames = maxBFrames;
     }
 
+    @ApiTest(apis = {"VideoCapabilities#getSupportedWidths",
+            "VideoCapabilities#getSupportedHeightsFor",
+            "VideoCapabilities#getSupportedFrameRatesFor",
+            "VideoCapabilities#getBitrateRange",
+            "VideoCapabilities#getAchievableFrameRatesFor",
+            "CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+            "CodecCapabilities#COLOR_FormatYUV420Planar",
+            "CodecCapabilities#COLOR_FormatYUV420Flexible",
+            "android.media.MediaFormat#KEY_MAX_B_FRAMES"})
     @Test
     public void testVid() throws Exception {
         if (mType == Type.Qual) {
diff --git a/tests/videocodec/Android.bp b/tests/videocodec/Android.bp
index 3b923da..38dea48 100644
--- a/tests/videocodec/Android.bp
+++ b/tests/videocodec/Android.bp
@@ -27,6 +27,10 @@
         "ctsmediav2common",
     ],
     platform_apis: true,
+    jni_uses_sdk_apis: true,
+    jni_libs: [
+        "libctsvideoqualityutils_jni",
+    ],
     srcs: ["src/**/*.java"],
     // Tag this module as a cts test artifact
     test_suites: [
diff --git a/tests/videocodec/jni/Android.bp b/tests/videocodec/jni/Android.bp
new file mode 100644
index 0000000..8fa1c6f
--- /dev/null
+++ b/tests/videocodec/jni/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 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"],
+}
+
+cc_defaults {
+    name: "cts_videocodec_jni_defaults",
+    shared_libs: [
+        "libmediandk",
+        "liblog",
+    ],
+    header_libs: [
+        "liblog_headers",
+        "libeigen",
+    ],
+    stl: "libc++_static",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    gtest: false,
+    min_sdk_version: "29",
+    sdk_version: "current",
+}
+
+cc_test_library {
+    name: "libctsvideoqualityutils_jni",
+    defaults: [
+        "cts_videocodec_jni_defaults",
+    ],
+    srcs: [
+        "NativeVideoQualityUtils.cpp",
+    ],
+}
diff --git a/tests/videocodec/jni/NativeVideoQualityUtils.cpp b/tests/videocodec/jni/NativeVideoQualityUtils.cpp
new file mode 100644
index 0000000..4ee51ee
--- /dev/null
+++ b/tests/videocodec/jni/NativeVideoQualityUtils.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NativeVideoQualityUtils"
+
+#include <jni.h>
+#include <log/log.h>
+
+#include <Eigen/Dense>
+#include <Eigen/QR>
+#include <string>
+#include <vector>
+
+// Migrate this method to std::format when C++20 becomes available
+template <typename... Args>
+std::string StringFormat(const std::string& format, Args... args) {
+    auto size = std::snprintf(nullptr, 0, format.c_str(), args...);
+    if (size < 0) return {};
+    std::vector<char> buffer(size + 1); // Add 1 for terminating null byte
+    std::snprintf(buffer.data(), buffer.size(), format.c_str(), args...);
+    return std::string(buffer.data(), size); // Exclude the terminating null byte
+}
+
+double polyEval(std::vector<double>& coeffs, double x) {
+    double y = coeffs[0];
+    double xn = x;
+    for (int i = 1; i < coeffs.size(); i++) {
+        y += (coeffs[i] * xn);
+        xn *= x;
+    }
+    return y;
+}
+
+std::vector<double> polyIntegrate(std::vector<double>& coeffs, double coi = 0.0) {
+    std::vector<double> integratedCoeffs(coeffs.size() + 1);
+    integratedCoeffs[0] = coi; // constant of integration
+    for (int i = 1; i < coeffs.size() + 1; i++) {
+        integratedCoeffs[i] = coeffs[i - 1] / i;
+    }
+    return integratedCoeffs;
+}
+
+std::vector<double> polyFit(std::vector<double>& rates, std::vector<double>& qualities, int order) {
+    // y = X * a, y is vector of qualities, X is vandermonde matrix and a is vector of coeffs.
+    Eigen::MatrixXd X(rates.size(), order + 1);
+    Eigen::MatrixXd y(qualities.size(), 1);
+    for (int i = 0; i < rates.size(); ++i) {
+        y(i, 0) = qualities[i];
+        double element = 1;
+        for (int j = 0; j < order + 1; ++j) {
+            X(i, j) = element;
+            element *= rates[i];
+        }
+    }
+    // QR decomposition
+    Eigen::MatrixXd a = X.colPivHouseholderQr().solve(y);
+    std::vector<double> coeffs(order + 1);
+    for (int i = 0; i < order + 1; i++) {
+        coeffs[i] = a(i, 0);
+    }
+    return coeffs;
+}
+
+double getAvgImprovement(std::vector<double>& xA, std::vector<double>& yA, std::vector<double>& xB,
+                         std::vector<double>& yB, int order) {
+    std::vector<double> coeffsA = polyFit(xA, yA, order);
+    std::vector<double> coeffsB = polyFit(xB, yB, order);
+    std::vector<double> integratedCoeffsA = polyIntegrate(coeffsA);
+    std::vector<double> integratedCoeffsB = polyIntegrate(coeffsB);
+    double minX = std::max(*std::min_element(xA.begin(), xA.end()),
+                           *std::min_element(xB.begin(), xB.end()));
+    double maxX = std::min(*std::max_element(xA.begin(), xA.end()),
+                           *std::max_element(xB.begin(), xB.end()));
+    double areaA = polyEval(integratedCoeffsA, maxX) - polyEval(integratedCoeffsA, minX);
+    double areaB = polyEval(integratedCoeffsB, maxX) - polyEval(integratedCoeffsB, minX);
+    return (areaB - areaA) / (maxX - minX);
+}
+
+static jdouble nativeGetBDRate(JNIEnv* env, jobject, jdoubleArray jQualityA, jdoubleArray jRatesA,
+                               jdoubleArray jQualityB, jdoubleArray jRatesB, jboolean selBdSnr,
+                               jobject jRetMsg) {
+    jsize len[4]{env->GetArrayLength(jQualityA), env->GetArrayLength(jRatesA),
+                 env->GetArrayLength(jQualityB), env->GetArrayLength(jRatesB)};
+    std::string msg;
+    if (len[0] != len[1] || len[0] != len[2] || len[0] != len[3]) {
+        msg = StringFormat("array length of quality and bit rates for set A/B are not same, "
+                           "lengths are %d %d %d %d \n",
+                           (int)len[0], (int)len[1], (int)len[2], (int)len[3]);
+    } else if (len[0] < 4) {
+        msg = StringFormat("too few data-points present for bd rate analysis, count %d \n", len[0]);
+    } else {
+        std::vector<double> ratesA(len[0]);
+        env->GetDoubleArrayRegion(jRatesA, 0, len[0], &ratesA[0]);
+        std::vector<double> ratesB(len[0]);
+        env->GetDoubleArrayRegion(jRatesB, 0, len[0], &ratesB[0]);
+        std::vector<double> qualitiesA(len[0]);
+        env->GetDoubleArrayRegion(jQualityA, 0, len[0], &qualitiesA[0]);
+        std::vector<double> qualitiesB(len[0]);
+        env->GetDoubleArrayRegion(jQualityB, 0, len[0], &qualitiesB[0]);
+        // log rate
+        for (int i = 0; i < len[0]; i++) {
+            ratesA[i] = std::log(ratesA[i]);
+            ratesB[i] = std::log(ratesB[i]);
+        }
+        const int order = 3;
+        if (selBdSnr) {
+            return getAvgImprovement(ratesA, qualitiesA, ratesB, qualitiesB, order);
+        } else {
+            double bdRate = getAvgImprovement(qualitiesA, ratesA, qualitiesB, ratesB, order);
+            // In really bad formed data the exponent can grow too large clamp it.
+            if (bdRate > 200) {
+                bdRate = 200;
+            }
+            bdRate = (std::exp(bdRate) - 1) * 100;
+            return bdRate;
+        }
+    }
+    jclass clazz = env->GetObjectClass(jRetMsg);
+    jmethodID mId =
+            env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
+    env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
+    return 0;
+}
+
+int registerAndroidVideoCodecCtsVQUtils(JNIEnv* env) {
+    const JNINativeMethod methodTable[] = {
+            {"nativeGetBDRate", "([D[D[D[DZLjava/lang/StringBuilder;)D", (void*)nativeGetBDRate},
+    };
+    jclass c = env->FindClass("android/videocodec/cts/VideoEncoderQualityRegressionTest");
+    return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
+}
+
+extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) return JNI_ERR;
+    if (registerAndroidVideoCodecCtsVQUtils(env) != JNI_OK) return JNI_ERR;
+    return JNI_VERSION_1_6;
+}
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoDecodeEditEncodeTest.java b/tests/videocodec/src/android/videocodec/cts/VideoDecodeEditEncodeTest.java
index 2ad2607..e546aeb 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoDecodeEditEncodeTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoDecodeEditEncodeTest.java
@@ -47,6 +47,7 @@
 import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.Preconditions;
 
+import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -154,13 +155,15 @@
     private final String mEncoderName;
     private final String mMediaType;
 
+    private final ArrayList<String> mTmpFiles = new ArrayList<>();
+
     public VideoDecodeEditEncodeTest(String encoderName, String mediaType,
             @SuppressWarnings("unused") String allTestParams) {
         mEncoderName = encoderName;
         mMediaType = mediaType;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
@@ -174,6 +177,15 @@
                 false, SELECT_SWITCH);
     }
 
+    @After
+    public void tearDown() {
+        for (String tmpFile : mTmpFiles) {
+            File tmp = new File(tmpFile);
+            if (tmp.exists()) assertTrue("unable to delete file " + tmpFile, tmp.delete());
+        }
+        mTmpFiles.clear();
+    }
+
     private static String getShader(String width, String height, String kernel) {
         return "#extension GL_OES_EGL_image_external : require\n"
                 + "#define KERNEL_SIZE 25\n"
@@ -711,7 +723,7 @@
      */
     @ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
             "android.media.format.MediaFormat#KEY_ALLOW_FRAME_DROP",
-            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_Format32bitABGR8888"})
+            "MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
     @Test
     public void testVideoEdit() throws IOException, InterruptedException {
         VideoChunks sourceChunks = new VideoChunks();
@@ -721,33 +733,38 @@
             outputData[i] = editVideoFile(sourceChunks, KERNELS[i]);
         }
         String tmpPathA = getTempFilePath("");
+        mTmpFiles.add(tmpPathA);
+        String tmpPathB = getTempFilePath("");
+        mTmpFiles.add(tmpPathB);
+
         int muxerFormat = getMuxerFormatForMediaType(mMediaType);
         muxOutput(tmpPathA, muxerFormat, outputData[0].getMediaFormat(), outputData[0].getBuffer(),
                 outputData[0].getChunkInfos());
-        String tmpPathB = getTempFilePath("");
         muxOutput(tmpPathB, muxerFormat, outputData[1].getMediaFormat(), outputData[1].getBuffer(),
                 outputData[1].getChunkInfos());
-        CompareStreams cs = new CompareStreams(mMediaType, tmpPathA, mMediaType, tmpPathB,
-                false, false);
-        double[] avgPSNR = cs.getAvgPSNR();
-        cs.cleanUp();
-        final double weightedAvgPSNR = (4 * avgPSNR[0] + avgPSNR[1] + avgPSNR[2]) / 6;
-        if (weightedAvgPSNR < AVG_ACCEPTABLE_QUALITY) {
-            fail(String.format("Average PSNR of the sequence: %f is < threshold : %f\n",
-                    weightedAvgPSNR, AVG_ACCEPTABLE_QUALITY));
+
+        CompareStreams cs = null;
+        try {
+            cs = new CompareStreams(mMediaType, tmpPathA, mMediaType, tmpPathB, false, false);
+            double[] avgPSNR = cs.getAvgPSNR();
+            final double weightedAvgPSNR = (4 * avgPSNR[0] + avgPSNR[1] + avgPSNR[2]) / 6;
+            if (weightedAvgPSNR < AVG_ACCEPTABLE_QUALITY) {
+                fail(String.format("Average PSNR of the sequence: %f is < threshold : %f\n",
+                        weightedAvgPSNR, AVG_ACCEPTABLE_QUALITY));
+            }
+        } finally {
+            if (cs != null) cs.cleanUp();
         }
         DecodeStreamToYuv yuvRes = new DecodeStreamToYuv(mMediaType, tmpPathA);
         RawResource yuv = yuvRes.getDecodedYuv();
+        mTmpFiles.add(yuv.mFileName);
         double varA = computeVariance(yuv);
-        File tmp = new File(yuv.mFileName);
-        assertTrue(tmp.delete());
+
         yuvRes = new DecodeStreamToYuv(mMediaType, tmpPathB);
         yuv = yuvRes.getDecodedYuv();
+        mTmpFiles.add(yuv.mFileName);
         double varB = computeVariance(yuv);
-        tmp = new File(yuv.mFileName);
-        assertTrue(tmp.delete());
-        assertTrue(new File(tmpPathA).delete());
-        assertTrue(new File(tmpPathB).delete());
+
         Log.d(LOG_TAG, "variance is " + varA + " " + varB);
         assertTrue(String.format("Blurred clip variance is not less than sharpened clip. Variance"
                         + " of blurred clip is %f, variance of sharpened clip is %f", varA, varB),
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoDecoderValidationTest.java b/tests/videocodec/src/android/videocodec/cts/VideoDecoderValidationTest.java
index 5e7313b..825a593 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoDecoderValidationTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoDecoderValidationTest.java
@@ -66,7 +66,7 @@
         mTransfer = transfer;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = false;
         final boolean needAudio = true;
@@ -87,6 +87,7 @@
      * Extract, Decode and Validate. Check description of class {@link VideoDecoderValidationTest}
      */
     @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatYUVP010",
+            "MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Flexible",
             "android.media.MediaFormat#KEY_COLOR_RANGE",
             "android.media.MediaFormat#KEY_COLOR_STANDARD",
             "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java
index 4a2648b..fea3a75 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java
@@ -98,7 +98,7 @@
     private static void addParams(int width, int height, int[] segmentBitRates,
             CompressedResource res) {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
         for (String mediaType : mediaTypes) {
             for (int bitRateMode : bitRateModes) {
@@ -112,7 +112,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{5})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{5}")
     public static Collection<Object[]> input() {
         addParams(1920, 1080, SEGMENT_BITRATES_FULLHD, BIRTHDAY_FULLHD_LANDSCAPE);
         addParams(1080, 1920, SEGMENT_BITRATES_FULLHD, SELFIEGROUP_FULLHD_PORTRAIT);
@@ -183,7 +183,7 @@
         assertTrue(msg + mTestConfig + mTestEnv, mSegmentSizes[segB] / mSegmentSizes[segA] >= 1.15);
     }
 
-    @CddTest(requirements = "5.2/C.2.1")
+    @CddTest(requirements = "5.2/C-2-1")
     @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
     @Test
     public void testAdaptiveBitRate() throws IOException, InterruptedException,
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderFrameRateTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderFrameRateTest.java
index ddee612..369a816 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderFrameRateTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderFrameRateTest.java
@@ -97,11 +97,16 @@
 
     private static void addParams(int width, int height, CompressedResource res) {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] maxBFramesPerSubGop = new int[]{0, 1};
         for (String mediaType : mediaTypes) {
             for (int maxBFrames : maxBFramesPerSubGop) {
                 // mediaType, cfg, resource file, test label
+                if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                        && !mediaType.equals((MediaFormat.MIMETYPE_VIDEO_HEVC))
+                        && maxBFrames != 0) {
+                    continue;
+                }
                 String label = String.format("%dkbps_%dx%d_maxb-%d", BIT_RATE / 1000, width,
                         height, maxBFrames);
                 exhaustiveArgsList.add(new Object[]{mediaType, getVideoEncoderCfgParams(mediaType,
@@ -110,7 +115,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         addParams(1920, 1080, BIRTHDAY_FULLHD_LANDSCAPE);
         addParams(1080, 1920, SELFIEGROUP_FULLHD_PORTRAIT);
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderIntraFrameIntervalTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderIntraFrameIntervalTest.java
index ec3e2bd..a982f9e 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderIntraFrameIntervalTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderIntraFrameIntervalTest.java
@@ -100,15 +100,20 @@
                 .build();
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] maxBFramesPerSubGop = new int[]{0, 1, 2, 3};
         final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
         final int[] intraIntervals = new int[]{0, 2};
         for (String mediaType : mediaTypes) {
             for (int maxBFrames : maxBFramesPerSubGop) {
+                if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                        && !mediaType.equals((MediaFormat.MIMETYPE_VIDEO_HEVC))
+                        && maxBFrames != 0) {
+                    continue;
+                }
                 for (int bitRateMode : bitRateModes) {
                     for (int intraInterval : intraIntervals) {
                         // mediaType, cfg, res, test label
@@ -148,7 +153,7 @@
         RawResource res = RES_YUV_MAP.getOrDefault(mCRes.uniqueLabel(), null);
         assertNotNull("no raw resource found for testing config : " + mEncCfgParams[0] + mTestConfig
                 + mTestEnv, res);
-        encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, true, false);
+        encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, false, false);
         assertEquals("encoder did not encode the requested number of frames \n"
                 + mTestConfig + mTestEnv, FRAME_LIMIT, mOutputCount);
         int lastKeyFrameIdx = 0, currFrameIdx = 0, maxKeyFrameDistance = 0;
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java
index 03ddb80..0b2732a 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java
@@ -93,14 +93,19 @@
                 .build();
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] maxBFramesPerSubGop = new int[]{0, 1};
         for (String mediaType : mediaTypes) {
             for (int maxBFrames : maxBFramesPerSubGop) {
                 // mediaType, cfg, resource file, test label
+                if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                        && !mediaType.equals((MediaFormat.MIMETYPE_VIDEO_HEVC))
+                        && maxBFrames != 0) {
+                    continue;
+                }
                 String label = String.format("%dkbps_%dx%d_maxb-%d", BIT_RATE / 1000, WIDTH,
                         HEIGHT, maxBFrames);
                 exhaustiveArgsList.add(new Object[]{mediaType, getVideoEncoderCfgParams(mediaType,
@@ -133,7 +138,7 @@
         RawResource res = RES_YUV_MAP.getOrDefault(mCRes.uniqueLabel(), null);
         assertNotNull("no raw resource found for testing config : " + mEncCfgParams[0] + mTestConfig
                 + mTestEnv, res);
-        encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, true, false);
+        encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, false, false);
         assertEquals("encoder did not encode the requested number of frames \n"
                 + mTestConfig + mTestEnv, FRAME_LIMIT, mOutputCount);
         int bFramesInSubGop = 0, maxBFramesFound = -1;
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java
index b6518b1..ac810a5 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java
@@ -33,7 +33,6 @@
 import com.android.compatibility.common.util.ApiTest;
 
 import org.junit.AfterClass;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -50,50 +49,27 @@
 /**
  * 1. MinMaxResolutionsTest should query the ranges of supported width and height using
  * MediaCodecInfo.VideoCapabilities, test the min resolution and the max resolution of the encoder.
- * <p></p>
- * Test Params:
- * <p>Input resolution = min/max</p>
- * <p>Number of frames = 30</p>
- * <p>FrameRate = 30</p>
- * <p>Target bitrate = 10 Mbps</p>
- * <p>Bitrate mode = VBR</p>
- * <p>MaxBFrames = 0/1</p>
- * <p>Codec type = AVC/HEVC</p>
- * <p>IFrameInterval = 0/1 second</p>
- * <p></p>
- *
- * 2. MinMaxBitrateTest should query the range of the supported bitrates, and test min/max of them
- * <p></p>
- * Test Params:
- * <p>Input resolution = 720p30fps</p>
- * <p>Number of frames = 300</p>
- * <p>FrameRate = 30</p>
- * <p>Target bitrate = min/max</p>
- * <p>Bitrate mode = CBR/VBR</p>
- * <p>MaxBFrames = 0/1</p>
- * <p>Codec type = AVC/HEVC</p>
- * <p>IFrameInterval = 0/1 second</p>
- * <p></p>
- *
+ * <p> Test Params:  Input configuration = Resolution: min/max, frame rate: 30, bitrate: choose
+ * basing on resolution </p>
+ * 2. MinMaxBitrateTest should query the range of the supported bitrates, and test min/max of them.
+ * <p> Test Params: Input configuration = Resolution: choose basing on bitrate, frame rate: 30,
+ * bitrate: min/max </p>
  * 3. MinMaxFrameRatesTest should query the range of the supported frame rates, and test min/max
  * of them.
- * Test Params:
- * <p>Input resolution = 720p</p>
- * <p>Number of frames = 300</p>
- * <p>FrameRate = min/max</p>
- * <p>Target bitrate = 5Mbps</p>
- * <p>Bitrate mode = CBR/VBR</p>
- * <p>MaxBFrames = 0/1</p>
- * <p>Codec type = AVC/HEVC</p>
- * <p>IFrameInterval = 0/1 second</p>
- * <p></p>
+ * <p> Test Params:  Input configuration = Resolution: 720p, frame rate: min/max, bitrate: 5mbps
+ * </p>
+ * All tests should run for following combinations:
+ * <p>Bitrate mode = CBR/VBR, MaxBFrames = 0/1, Codec type = AVC/HEVC, Intra frame interval = 0/1
+ * second</p>
  */
 @RunWith(Parameterized.class)
 public class VideoEncoderMinMaxTest extends VideoEncoderValidationTestBase {
     private static final float MIN_ACCEPTABLE_QUALITY = 20.0f;  // psnr in dB
     private static final int FRAME_LIMIT = 300;
-    private static final int FRAME_RATE = 30;
-    private static final int BIT_RATE = 10000000;
+    private static final int TARGET_WIDTH = 1280;
+    private static final int TARGET_HEIGHT = 720;
+    private static final int TARGET_FRAME_RATE = 30;
+    private static final int TARGET_BIT_RATE = 5000000;
     private static final List<Object[]> exhaustiveArgsList = new ArrayList<>();
     private static final HashMap<String, RawResource> RES_YUV_MAP = new HashMap<>();
 
@@ -113,91 +89,129 @@
         }
     }
 
-    private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int width,
-            int height, int maxBFrames, int intraInterval) {
+    private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRateMode,
+            int maxBFrames, int intraInterval) {
         return new EncoderConfigParams.Builder(mediaType)
-                .setWidth(width)
-                .setHeight(height)
-                .setBitRate(BIT_RATE)
+                .setWidth(TARGET_WIDTH)
+                .setHeight(TARGET_HEIGHT)
+                .setBitRate(TARGET_BIT_RATE)
+                .setBitRateMode(bitRateMode)
                 .setMaxBFrames(maxBFrames)
                 .setKeyFrameInterval(intraInterval)
-                .setFrameRate(FRAME_RATE)
+                .setFrameRate(TARGET_FRAME_RATE)
                 .build();
     }
 
-    private static void addParams(int width, int height, CompressedResource res) {
+    private static void addParams() {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
                 MediaFormat.MIMETYPE_VIDEO_HEVC};
         final int[] maxBFramesPerSubGop = new int[]{0, 1};
         final int[] intraIntervals = new int[]{0, 1};
+        final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
         for (String mediaType : mediaTypes) {
             for (int maxBFrames : maxBFramesPerSubGop) {
                 for (int intraInterval : intraIntervals) {
-                    // mediaType, cfg, resource file
-                    exhaustiveArgsList.add(new Object[]{mediaType,
-                            getVideoEncoderCfgParams(mediaType, width, height, maxBFrames,
-                                    intraInterval), res});
+                    for (int bitRateMode : bitRateModes) {
+                        // mediaType, cfg, resource file
+                        exhaustiveArgsList.add(
+                                new Object[]{mediaType, getVideoEncoderCfgParams(mediaType,
+                                        bitRateMode, maxBFrames,
+                                        intraInterval), BIRTHDAY_FULLHD_LANDSCAPE});
+                    }
                 }
             }
         }
     }
 
-    private static List<Object> applyMinMaxRanges(MediaCodecInfo.CodecCapabilities caps,
+    private static List<Object> applyMinMaxRanges(MediaCodecInfo.VideoCapabilities caps,
             Object cfgObject) throws CloneNotSupportedException {
-        int minWidth = caps.getVideoCapabilities().getSupportedWidths().getLower();
-        int maxWidth = caps.getVideoCapabilities().getSupportedWidths().getUpper();
-        int minHeight = caps.getVideoCapabilities().getSupportedHeights().getLower();
-        int maxHeight = caps.getVideoCapabilities().getSupportedHeights().getUpper();
-
-        int minBitRate = caps.getVideoCapabilities().getBitrateRange().getLower();
-        int maxBitRate = caps.getVideoCapabilities().getBitrateRange().getUpper();
-
-        int minFrameRate = caps.getVideoCapabilities().getSupportedFrameRates().getLower();
-        int maxFrameRate = caps.getVideoCapabilities().getSupportedFrameRates().getUpper();
-
         List<Object> cfgObjects = new ArrayList<>();
         EncoderConfigParams cfgParam = (EncoderConfigParams) cfgObject;
+        int minW = caps.getSupportedWidths().getLower();
+        int minHForMinW = caps.getSupportedHeightsFor(minW).getLower();
+        int maxHForMinW = caps.getSupportedHeightsFor(minW).getUpper();
+        int minH = caps.getSupportedHeights().getLower();
+        int minWForMinH = caps.getSupportedWidthsFor(minH).getLower();
+        int maxWForMinH = caps.getSupportedWidthsFor(minH).getUpper();
+        int maxW = caps.getSupportedWidths().getUpper();
+        int minHForMaxW = caps.getSupportedHeightsFor(maxW).getLower();
+        int maxHForMaxW = caps.getSupportedHeightsFor(maxW).getUpper();
+        int maxH = caps.getSupportedHeights().getUpper();
+        int minWForMaxH = caps.getSupportedWidthsFor(maxH).getLower();
+        int maxWForMaxH = caps.getSupportedWidthsFor(maxH).getUpper();
+        int minBitRate = caps.getBitrateRange().getLower();
+        int maxBitRate = caps.getBitrateRange().getUpper();
 
-        final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
-        for (int bitRateMode : bitRateModes) {
-            cfgObjects.add((Object) cfgParam.getBuilder()
-                    .setWidth(minWidth)
-                    .setHeight(minHeight)
-                    .setBitRate(minBitRate)
-                    .setBitRateMode(bitRateMode)
-                    .build());
-
-            cfgObjects.add((Object) cfgParam.getBuilder()
-                    .setWidth(maxWidth)
-                    .setHeight(maxHeight)
-                    .setBitRate(maxBitRate)
-                    .setBitRateMode(bitRateMode)
-                    .build());
-
-            cfgObjects.add((Object) cfgParam.getBuilder()
-                    .setFrameRate(minFrameRate)
-                    .setBitRate(5000000)
-                    .setBitRateMode(bitRateMode)
-                    .build());
-
-            cfgObjects.add((Object) cfgParam.getBuilder()
-                    .setFrameRate(maxFrameRate)
-                    .setBitRate(5000000)
-                    .setBitRateMode(bitRateMode)
-                    .build());
+        // min max res & bitrate tests
+        android.util.Range<Double> rates = caps.getSupportedFrameRatesFor(minW, minHForMinW);
+        int frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+        cfgObjects.add(cfgParam.getBuilder().setWidth(minW).setHeight(minHForMinW)
+                .setFrameRate(frameRate).setBitRate(minBitRate).build());
+        rates = caps.getSupportedFrameRatesFor(maxW, maxHForMaxW);
+        frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+        cfgObjects.add(cfgParam.getBuilder().setWidth(maxW).setHeight(maxHForMaxW)
+                .setFrameRate(frameRate).setBitRate(maxBitRate).build());
+        int bitrate;
+        if (minW != minWForMinH || minH != minHForMinW) {
+            rates = caps.getSupportedFrameRatesFor(minWForMinH, minH);
+            frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+            bitrate = caps.getBitrateRange().clamp((int) (maxBitRate / Math.sqrt(
+                    (double) maxW * maxHForMaxW / minWForMinH / minH)));
+            cfgObjects.add(cfgParam.getBuilder().setWidth(minWForMinH).setHeight(minH)
+                    .setFrameRate(frameRate).setBitRate(bitrate).build());
+        }
+        if (maxW != maxWForMaxH || maxH != maxHForMaxW) {
+            rates = caps.getSupportedFrameRatesFor(maxWForMaxH, maxH);
+            frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+            bitrate = caps.getBitrateRange().clamp((int) (maxBitRate / Math.sqrt(
+                    (double) maxW * maxHForMaxW / maxWForMaxH / maxH)));
+            cfgObjects.add(cfgParam.getBuilder().setWidth(maxWForMaxH).setHeight(maxH)
+                    .setFrameRate(frameRate).setBitRate(bitrate).build());
         }
 
-        cfgObjects.add((Object) cfgParam.getBuilder()
-                .setWidth(minWidth)
-                .setHeight(maxHeight)
-                .setBitRateMode(BITRATE_MODE_VBR)
-                .build());
+        rates = caps.getSupportedFrameRatesFor(minW, maxHForMinW);
+        frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+        bitrate = caps.getBitrateRange().clamp((int) (maxBitRate / Math.sqrt(
+                (double) maxW * maxHForMaxW / minW / maxHForMinW)));
+        cfgObjects.add(cfgParam.getBuilder().setWidth(minW).setHeight(maxHForMinW)
+                .setFrameRate(frameRate).setBitRate(bitrate).build());
 
-        cfgObjects.add((Object) cfgParam.getBuilder()
-                .setWidth(maxWidth)
-                .setHeight(minHeight)
-                .setBitRateMode(BITRATE_MODE_VBR)
-                .build());
+        rates = caps.getSupportedFrameRatesFor(maxWForMinH, minH);
+        frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+        bitrate = caps.getBitrateRange().clamp((int) (maxBitRate / Math.sqrt(
+                (double) maxW * maxHForMaxW / maxWForMinH / minH)));
+        cfgObjects.add(cfgParam.getBuilder().setWidth(maxWForMinH).setHeight(minH)
+                .setFrameRate(frameRate).setBitRate(bitrate).build());
+        if (maxW != maxWForMinH || minH != minHForMaxW) {
+            rates = caps.getSupportedFrameRatesFor(maxW, minHForMaxW);
+            frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+            bitrate = caps.getBitrateRange().clamp((int) (maxBitRate / Math.sqrt(
+                    (double) maxW * maxHForMaxW / maxW / minHForMaxW)));
+            cfgObjects.add(cfgParam.getBuilder().setWidth(maxW).setHeight(minHForMaxW)
+                    .setFrameRate(frameRate).setBitRate(bitrate).build());
+        }
+        if (minW != minWForMaxH || maxH != maxHForMinW) {
+            rates = caps.getSupportedFrameRatesFor(minWForMaxH, maxH);
+            frameRate = rates.clamp((double) TARGET_FRAME_RATE).intValue();
+            bitrate = caps.getBitrateRange().clamp((int) (maxBitRate / Math.sqrt(
+                    (double) maxW * maxHForMaxW / minWForMaxH / maxH)));
+            cfgObjects.add(cfgParam.getBuilder().setWidth(minWForMaxH).setHeight(maxH)
+                    .setFrameRate(frameRate).setBitRate(bitrate).build());
+        }
+
+        // min-max frame rate tests
+        try {
+            int minFps = caps.getSupportedFrameRatesFor(TARGET_WIDTH, TARGET_HEIGHT).getLower()
+                    .intValue();
+            cfgObjects.add(cfgParam.getBuilder().setFrameRate(minFps).build());
+        } catch (IllegalArgumentException ignored) {
+        }
+        try {
+            int maxFps = caps.getSupportedFrameRatesFor(TARGET_WIDTH, TARGET_HEIGHT).getUpper()
+                    .intValue();
+            cfgObjects.add(cfgParam.getBuilder().setFrameRate(maxFps).build());
+        } catch (IllegalArgumentException ignored) {
+        }
 
         return cfgObjects;
     }
@@ -205,11 +219,13 @@
     private static List<Object> getMinMaxRangeCfgObjects(Object codecName, Object mediaType,
             Object cfgObject) throws CloneNotSupportedException {
         for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_REGULAR.getCodecInfos()) {
-            for (String type : codecInfo.getSupportedTypes()) {
-                if (codecName.equals(codecInfo.getName()) && mediaType.equals(type)) {
-                    MediaCodecInfo.CodecCapabilities caps =
-                            codecInfo.getCapabilitiesForType(type);
-                    return applyMinMaxRanges(caps, cfgObject);
+            if (codecName.equals(codecInfo.getName())) {
+                for (String type : codecInfo.getSupportedTypes()) {
+                    if (mediaType.equals(type)) {
+                        MediaCodecInfo.CodecCapabilities caps =
+                                codecInfo.getCapabilitiesForType(type);
+                        return applyMinMaxRanges(caps.getVideoCapabilities(), cfgObject);
+                    }
                 }
             }
         }
@@ -226,10 +242,10 @@
                 System.arraycopy(arg, 0, argUpdate, 0, arg.length);
                 argUpdate[2] = obj;
                 EncoderConfigParams cfgVar = (EncoderConfigParams) obj;
-                String label = String.format("%dkbps_%dx%d_%dfps_maxb-%d_%s_i-dist-%d",
-                        cfgVar.mBitRate / 1000, cfgVar.mWidth, cfgVar.mHeight, cfgVar.mFrameRate,
-                        cfgVar.mMaxBFrames, bitRateModeToString(cfgVar.mBitRateMode),
-                        (int) cfgVar.mKeyFrameInterval);
+                String label = String.format("%.2fmbps_%dx%d_%dfps_maxb-%d_%s_i-dist-%d",
+                        cfgVar.mBitRate / 1000000., cfgVar.mWidth, cfgVar.mHeight,
+                        cfgVar.mFrameRate, cfgVar.mMaxBFrames,
+                        bitRateModeToString(cfgVar.mBitRateMode), (int) cfgVar.mKeyFrameInterval);
                 argUpdate[arg.length - 1] = label;
                 argUpdate[arg.length] = paramToString(argUpdate);
                 newParamList.add(argUpdate);
@@ -238,9 +254,9 @@
         return newParamList;
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() throws CloneNotSupportedException {
-        addParams(1280, 720, BIRTHDAY_FULLHD_LANDSCAPE);
+        addParams();
         return updateParamList(prepareParamList(exhaustiveArgsList, true, false, true, false,
                 HARDWARE));
     }
@@ -256,7 +272,13 @@
         mIsLoopBack = true;
     }
 
-    @ApiTest(apis = {"android.media.MediaFormat#KEY_WIDTH",
+    @ApiTest(apis = {"VideoCapabilities#getSupportedWidths",
+            "VideoCapabilities#getSupportedHeightsFor",
+            "VideoCapabilities#getSupportedWidthsFor",
+            "VideoCapabilities#getSupportedHeights",
+            "VideoCapabilities#getSupportedFrameRatesFor",
+            "VideoCapabilities#getBitrateRange",
+            "android.media.MediaFormat#KEY_WIDTH",
             "android.media.MediaFormat#KEY_HEIGHT",
             "android.media.MediaFormat#KEY_BITRATE",
             "android.media.MediaFormat#KEY_FRAME_RATE"})
@@ -265,12 +287,12 @@
         MediaFormat format = mEncCfgParams[0].getFormat();
         ArrayList<MediaFormat> formats = new ArrayList<>();
         formats.add(format);
-        Assume.assumeTrue("Encoder: " + mCodecName + " doesn't support format: " + format,
+        assertTrue("Encoder: " + mCodecName + " doesn't support format: " + format,
                 areFormatsSupported(mCodecName, mMediaType, formats));
         RawResource res = RES_YUV_MAP.getOrDefault(mCRes.uniqueLabel(), null);
         assertNotNull("no raw resource found for testing config : " + mEncCfgParams[0]
                 + mTestConfig + mTestEnv, res);
-        encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, true, true);
+        encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, false, true);
         CompareStreams cs = null;
         StringBuilder msg = new StringBuilder();
         boolean isOk = true;
@@ -289,7 +311,6 @@
         } finally {
             if (cs != null) cs.cleanUp();
         }
-        new File(mMuxedOutputFile).delete();
         assertEquals("encoder did not encode the requested number of frames \n"
                 + mTestConfig + mTestEnv, FRAME_LIMIT, mOutputCount);
         assertTrue("Encountered frames with PSNR less than configured threshold "
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMultiResTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMultiResTest.java
index 0d8db11..54ef2ce 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMultiResTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMultiResTest.java
@@ -99,12 +99,17 @@
 
     private static void addParams(int width, int height, int frameRate) {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
         final int[] maxBFramesPerSubGop = new int[]{0, 1};
         final int[] intraIntervals = new int[]{0, 1};
         for (String mediaType : mediaTypes) {
             for (int maxBFrames : maxBFramesPerSubGop) {
+                if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                        && !mediaType.equals((MediaFormat.MIMETYPE_VIDEO_HEVC))
+                        && maxBFrames != 0) {
+                    continue;
+                }
                 for (int bitRateMode : bitRateModes) {
                     for (int intraInterval : intraIntervals) {
                         // mediaType, cfg, res, label
@@ -121,7 +126,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         addParams(1080, 1920, 30);
         addParams(720, 1280, 30);
@@ -170,7 +175,8 @@
     }
 
     @ApiTest(apis = {"android.media.MediaFormat#KEY_WIDTH",
-            "android.media.MediaFormat#KEY_HEIGHT"})
+            "android.media.MediaFormat#KEY_HEIGHT",
+            "android.media.MediaFormat#KEY_FRAME_RATE"})
     @Test
     public void testMultiRes() throws IOException, InterruptedException {
         MediaFormat format = mEncCfgParams[0].getFormat();
@@ -194,10 +200,9 @@
             final double[] minPSNR = cs.getMinimumPSNR();
             for (int i = 0; i < minPSNR.length; i++) {
                 if (minPSNR[i] < MIN_ACCEPTABLE_QUALITY) {
-                    msg.append(String.format(
-                            "For %d plane, minPSNR is less than tolerance threshold, Got %f, "
-                                    + "Threshold %f",
-                            i, minPSNR[i], MIN_ACCEPTABLE_QUALITY));
+                    msg.append(String.format("For %d plane, minPSNR is less than tolerance"
+                            + " threshold, Got %f, Threshold %f", i, minPSNR[i],
+                            MIN_ACCEPTABLE_QUALITY));
                     isOk = false;
                     break;
                 }
@@ -205,7 +210,6 @@
         } finally {
             if (cs != null) cs.cleanUp();
         }
-        new File(mMuxedOutputFile).delete();
         assertEquals("encoder did not encode the requested number of frames \n"
                 + mTestConfig + mTestEnv, FRAME_LIMIT, mOutputCount);
         assertTrue("Encountered frames with PSNR less than configured threshold "
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderPsnrTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderPsnrTest.java
index 0093da7..fcff06b 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderPsnrTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderPsnrTest.java
@@ -97,7 +97,7 @@
 
     private static void addParams(int bitRate, int width, int height, CompressedResource res) {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
         for (String mediaType : mediaTypes) {
             for (int bitRateMode : bitRateModes) {
@@ -110,7 +110,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         addParams(25000000, 1920, 1080, BIRTHDAY_FULLHD_LANDSCAPE);
         addParams(25000000, 1080, 1920, SELFIEGROUP_FULLHD_PORTRAIT);
@@ -171,7 +171,6 @@
         } finally {
             if (cs != null) cs.cleanUp();
         }
-        new File(mMuxedOutputFile).delete();
         assertEquals("encoder did not encode the requested number of frames \n"
                 + mTestConfig + mTestEnv, FRAME_LIMIT, mOutputCount);
         assertTrue("Encountered frames with PSNR less than configured threshold "
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderQualityRegressionTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderQualityRegressionTest.java
new file mode 100644
index 0000000..bc0d76a3f
--- /dev/null
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderQualityRegressionTest.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2023 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.videocodec.cts;
+
+import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR;
+import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR;
+import static android.mediav2.common.cts.CodecTestBase.ComponentClass.HARDWARE;
+import static android.videocodec.cts.VideoEncoderValidationTestBase.BIRTHDAY_FULLHD_LANDSCAPE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.media.MediaFormat;
+import android.mediav2.common.cts.CodecEncoderTestBase;
+import android.mediav2.common.cts.CodecTestBase;
+import android.mediav2.common.cts.CompareStreams;
+import android.mediav2.common.cts.DecodeStreamToYuv;
+import android.mediav2.common.cts.EncoderConfigParams;
+import android.mediav2.common.cts.RawResource;
+import android.util.Log;
+
+import com.android.compatibility.common.util.ApiTest;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This test is to ensure no quality regression is seen from avc to hevc. Also no quality
+ * regression is seen from '0' b frames to '1' b frame
+ * <p></p>
+ * Global Encode Config:
+ * <p>Input resolution = 1080p30fps</p>
+ * <p>Bitrate mode = VBR/CBR</p>
+ * <p>Codec type = AVC/HEVC</p>
+ * <p>IFrameInterval = 1 seconds</p>
+ * <p></p>
+ */
+@RunWith(Parameterized.class)
+public class VideoEncoderQualityRegressionTest {
+    private static final String LOG_TAG = VideoEncoderQualityRegressionTest.class.getSimpleName();
+    private static final String[] MEDIA_TYPES =
+            {MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC};
+    private static final int WIDTH = 1920;
+    private static final int HEIGHT = 1080;
+    private static final int[] BIT_RATES = {2000000, 4000000, 6000000, 8000000, 10000000, 12000000};
+    private static final int[] BIT_RATE_MODES = {BITRATE_MODE_CBR, BITRATE_MODE_VBR};
+    private static final int[] B_FRAMES = {0, 1};
+    private static final int FRAME_RATE = 30;
+    private static final int KEY_FRAME_INTERVAL = 1;
+    private static final int FRAME_LIMIT = 300;
+    private static final List<Object[]> exhaustiveArgsList = new ArrayList<>();
+    private static final VideoEncoderValidationTestBase.CompressedResource RES =
+            BIRTHDAY_FULLHD_LANDSCAPE;
+    private static RawResource sActiveRawRes = null;
+
+    private final int mBitRateMode;
+    private final ArrayList<String> mTmpFiles = new ArrayList<>();
+
+    static {
+        System.loadLibrary("ctsvideoqualityutils_jni");
+    }
+
+    @Parameterized.Parameters(name = "{index}_{1}")
+    public static Collection<Object[]> input() {
+        for (int bitRateMode : BIT_RATE_MODES) {
+            exhaustiveArgsList.add(new Object[]{bitRateMode,
+                    CodecEncoderTestBase.bitRateModeToString(bitRateMode)});
+        }
+        return exhaustiveArgsList;
+    }
+
+    public VideoEncoderQualityRegressionTest(int bitRateMode,
+            @SuppressWarnings("unused") String testLabel) {
+        mBitRateMode = bitRateMode;
+    }
+
+    @BeforeClass
+    public static void decodeResourceToYuv() throws IOException, InterruptedException {
+        DecodeStreamToYuv yuvRes = new DecodeStreamToYuv(RES.mMediaType, RES.mResFile, FRAME_LIMIT);
+        sActiveRawRes = yuvRes.getDecodedYuv();
+    }
+
+    @AfterClass
+    public static void cleanUpResources() {
+        new File(sActiveRawRes.mFileName).delete();
+        sActiveRawRes = null;
+    }
+
+    @After
+    public void tearDown() {
+        for (String tmpFile : mTmpFiles) {
+            File tmp = new File(tmpFile);
+            if (tmp.exists()) assertTrue("unable to delete file " + tmpFile, tmp.delete());
+        }
+        mTmpFiles.clear();
+    }
+
+    private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
+            int bitRateMode, int maxBFrames) {
+        return new EncoderConfigParams.Builder(mediaType)
+                .setWidth(VideoEncoderQualityRegressionTest.WIDTH)
+                .setHeight(VideoEncoderQualityRegressionTest.HEIGHT)
+                .setBitRate(bitRate)
+                .setBitRateMode(bitRateMode)
+                .setKeyFrameInterval(KEY_FRAME_INTERVAL)
+                .setFrameRate(FRAME_RATE)
+                .setMaxBFrames(maxBFrames)
+                .build();
+    }
+
+    private native double nativeGetBDRate(double[] qualitiesA, double[] ratesA, double[] qualitiesB,
+            double[] ratesB, boolean selBdSnr, StringBuilder retMsg);
+
+    void getQualityRegressionForCfgs(List<EncoderConfigParams[]> cfgsUnion, String[] encoderNames,
+            double minGain) throws IOException, InterruptedException {
+        double[][] psnrs = new double[cfgsUnion.size()][cfgsUnion.get(0).length];
+        double[][] rates = new double[cfgsUnion.size()][cfgsUnion.get(0).length];
+        for (int i = 0; i < cfgsUnion.size(); i++) {
+            EncoderConfigParams[] cfgs = cfgsUnion.get(i);
+            String mediaType = cfgs[0].mMediaType;
+            VideoEncoderValidationTestBase vevtb = new VideoEncoderValidationTestBase(null,
+                    mediaType, null, null, "");
+            vevtb.setLoopBack(true);
+            for (int j = 0; j < cfgs.length; j++) {
+                vevtb.encodeToMemory(encoderNames[i], cfgs[j], sActiveRawRes, FRAME_LIMIT, true,
+                        true);
+                mTmpFiles.add(vevtb.getMuxedOutputFilePath());
+                assertEquals("encoder did not encode the requested number of frames \n",
+                        FRAME_LIMIT, vevtb.getOutputCount());
+                int outSize = vevtb.getOutputManager().getOutStreamSize();
+                double achievedBitRate = ((double) outSize * 8 * FRAME_RATE) / (1000 * FRAME_LIMIT);
+                CompareStreams cs = null;
+                try {
+                    cs = new CompareStreams(sActiveRawRes, mediaType,
+                            vevtb.getMuxedOutputFilePath(), true, true);
+                    final double[] globalPSNR = cs.getGlobalPSNR();
+                    double weightedPSNR = (6 * globalPSNR[0] + globalPSNR[1] + globalPSNR[2]) / 8;
+                    psnrs[i][j] = weightedPSNR;
+                    rates[i][j] = achievedBitRate;
+                } finally {
+                    if (cs != null) cs.cleanUp();
+                }
+                vevtb.deleteMuxedFile();
+            }
+        }
+        StringBuilder retMsg = new StringBuilder();
+        double bdRate = nativeGetBDRate(psnrs[0], rates[0], psnrs[1], rates[1], false, retMsg);
+        if (retMsg.length() != 0) fail(retMsg.toString());
+        for (int i = 0; i < psnrs.length; i++) {
+            retMsg.append(String.format("\nBitrate GlbPsnr Set %d\n", i));
+            for (int j = 0; j < psnrs[i].length; j++) {
+                retMsg.append(String.format("{%f, %f},\n", rates[i][j], psnrs[i][j]));
+            }
+        }
+        retMsg.append(String.format("bd rate %f not < %f", bdRate, minGain));
+        Log.d(LOG_TAG, retMsg.toString());
+        // assuming set B encoding is superior to set A,
+        assumeTrue(retMsg.toString(), bdRate < minGain);
+    }
+
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE",
+            "android.media.MediaFormat#KEY_BITRATE_MODE"})
+    @Test
+    public void testQualityRegressionOverCodecs() throws IOException, InterruptedException {
+        String[] encoderNames = new String[MEDIA_TYPES.length];
+        List<EncoderConfigParams[]> cfgsUnion = new ArrayList<>();
+        for (int i = 0; i < MEDIA_TYPES.length; i++) {
+            EncoderConfigParams[] cfgsOfMediaType = new EncoderConfigParams[BIT_RATES.length];
+            cfgsUnion.add(cfgsOfMediaType);
+            ArrayList<MediaFormat> fmts = new ArrayList<>();
+            for (int j = 0; j < cfgsOfMediaType.length; j++) {
+                cfgsOfMediaType[j] = getVideoEncoderCfgParams(MEDIA_TYPES[i], BIT_RATES[j],
+                        mBitRateMode, 0);
+                fmts.add(cfgsOfMediaType[j].getFormat());
+            }
+            ArrayList<String> encoders = CodecTestBase.selectCodecs(MEDIA_TYPES[i], fmts, null,
+                    true, HARDWARE);
+            Assume.assumeTrue("no encoders present on device that support encoding fmts: " + fmts,
+                    encoders.size() > 0);
+            encoderNames[i] = encoders.get(0);
+        }
+        getQualityRegressionForCfgs(cfgsUnion, encoderNames, 0);
+    }
+
+    void testQualityRegressionOverBFrames(String mediaType)
+            throws IOException, InterruptedException {
+        String[] encoderNames = new String[B_FRAMES.length];
+        List<EncoderConfigParams[]> cfgsUnion = new ArrayList<>();
+        for (int i = 0; i < B_FRAMES.length; i++) {
+            EncoderConfigParams[] cfgs = new EncoderConfigParams[BIT_RATES.length];
+            cfgsUnion.add(cfgs);
+            ArrayList<MediaFormat> fmts = new ArrayList<>();
+            for (int j = 0; j < cfgs.length; j++) {
+                cfgs[j] = getVideoEncoderCfgParams(mediaType, BIT_RATES[j], mBitRateMode,
+                        B_FRAMES[i]);
+                fmts.add(cfgs[j].getFormat());
+            }
+            ArrayList<String> encoders = CodecTestBase.selectCodecs(mediaType, fmts, null, true,
+                    HARDWARE);
+            Assume.assumeTrue("no encoders present on device that support encoding fmts: " + fmts,
+                    encoders.size() > 0);
+            encoderNames[i] = encoders.get(0);
+        }
+        getQualityRegressionForCfgs(cfgsUnion, encoderNames, 0.000001d);
+    }
+
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE",
+            "android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_MAX_B_FRAMES"})
+    @Test
+    public void testQualityRegressionOverBFramesAvc() throws IOException, InterruptedException {
+        testQualityRegressionOverBFrames(MediaFormat.MIMETYPE_VIDEO_AVC);
+    }
+
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE",
+            "android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_MAX_B_FRAMES"})
+    @Test
+    public void testQualityRegressionOverBFramesHevc() throws IOException, InterruptedException {
+        testQualityRegressionOverBFrames(MediaFormat.MIMETYPE_VIDEO_HEVC);
+    }
+}
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderTargetBitrateTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderTargetBitrateTest.java
index cb8ef98..29ab0f5 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderTargetBitrateTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderTargetBitrateTest.java
@@ -106,13 +106,18 @@
 
     private static void addParams(int width, int height, CompressedResource res) {
         final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
-                MediaFormat.MIMETYPE_VIDEO_HEVC};
+                MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_AV1};
         final int[] bitRates = new int[]{5000000, 8000000, 10000000};
         final int[] maxBFramesPerSubGop = new int[]{0, 1};
         final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
         for (String mediaType : mediaTypes) {
             for (int bitRate : bitRates) {
                 for (int maxBFrames : maxBFramesPerSubGop) {
+                    if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                            && !mediaType.equals((MediaFormat.MIMETYPE_VIDEO_HEVC))
+                            && maxBFrames != 0) {
+                        continue;
+                    }
                     for (int bitRateMode : bitRateModes) {
                         // mediaType, cfg, resource file, test label
                         String label = String.format("%dkbps_%dx%d_maxb-%d_%s", bitRate / 1000,
@@ -126,7 +131,7 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         addParams(1920, 1080, BIRTHDAY_FULLHD_LANDSCAPE);
         addParams(1080, 1920, SELFIEGROUP_FULLHD_PORTRAIT);
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
index f1a94e9..b7157c2 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
@@ -82,10 +82,10 @@
         }
     }
 
-    protected static final CompressedResource BIRTHDAY_FULLHD_LANDSCAPE =
+    public static final CompressedResource BIRTHDAY_FULLHD_LANDSCAPE =
             new CompressedResource(MediaFormat.MIMETYPE_VIDEO_AVC, MEDIA_DIR
                     + "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps.mp4");
-    protected static final CompressedResource SELFIEGROUP_FULLHD_PORTRAIT =
+    public static final CompressedResource SELFIEGROUP_FULLHD_PORTRAIT =
             new CompressedResource(MediaFormat.MIMETYPE_VIDEO_AVC, MEDIA_DIR
                     + "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps.mp4");
 
@@ -123,6 +123,11 @@
         mFileLength = mFileInp.length();
     }
 
+    protected void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
+        super.resetContext(isAsync, signalEOSWithLastFrame);
+        mPtsPicTypeMap.clear();
+    }
+
     protected void enqueueInput(int bufferIndex) {
         int frmSize = 3 * mActiveRawRes.mBytesPerSample * mActiveRawRes.mWidth
                 * mActiveRawRes.mHeight / 2;
diff --git a/tools/cts-tradefed/etc/cts-tradefed b/tools/cts-tradefed/etc/cts-tradefed
index 3d57a11..3929235 100755
--- a/tools/cts-tradefed/etc/cts-tradefed
+++ b/tools/cts-tradefed/etc/cts-tradefed
@@ -99,6 +99,9 @@
 for JAR in ${JAR_DIR}/*.jar; do
     JAR_PATH=${JAR_PATH}:${JAR}
 done
+# Move 'tradefed.jar' to the front of the jar path
+TRADEFED_JAR=":${JAR_DIR}/tradefed.jar"
+JAR_PATH="${TRADEFED_JAR}${JAR_PATH/$TRADEFED_JAR}"
 JAR_PATH=${JAR_PATH:1} # Strip off leading ':'
 
 # load any shared libraries for host-side executables
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 4d89c2a..1ffa66b 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -317,4 +317,9 @@
 
     <!-- b/266101051-->
     <option name="compatibility:exclude-filter" value="CtsGameServiceTestCases" />
+
+    <!--- b/260389884 -->
+    <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode" />
+    <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode_withParams" />
+    <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStateStandardMode" />
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-slim-stable.xml b/tools/cts-tradefed/res/config/cts-slim-stable.xml
index 6d64e2c..d36a7b6 100644
--- a/tools/cts-tradefed/res/config/cts-slim-stable.xml
+++ b/tools/cts-tradefed/res/config/cts-slim-stable.xml
@@ -32,8 +32,19 @@
 
   <!-- flaky tests -->
   <option name="compatibility:exclude-filter"
+          value="CtsAppTestCases android.app.cts.ActivityManagerFgsBgStartTest#testOverlappedTempAllowList"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsAppTestCases android.app.cts.ActivityManagerProcessStateTest#testBackgroundCheckActivityService"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsAppTestCases android.app.cts.ActivityManagerProcessStateTest#testFgsSticky1"/>
+  <option name="compatibility:exclude-filter"
       value="CtsAppTestCases android.app.cts.ActivityManagerProcessStateTest#testCantSaveStateLaunchAndSwitch" />
   <option name="compatibility:exclude-filter"
+          value="CtsAppTestCases android.app.cts.ActivityManagerProcessStateTest#testFgsSticky1"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsAppTestCases android.app.cts.AlertDialog_BuilderTest"/>
+  <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.NotificationManagerTest#testNotificationUriPermissionsGranted"/>
+  <option name="compatibility:exclude-filter"
       value="CtsContentTestCases android.content.cts.ContentProviderClientTest#testBulkInsertTimeout"/>
   <option name="compatibility:exclude-filter"
       value="CtsContentTestCases android.content.cts.ContentProviderClientTest#testUncanonicalizeTimeout" />
@@ -42,14 +53,57 @@
   <option name="compatibility:exclude-filter"
       value="CtsContentTestCases android.content.cts.ContentQueryMapTest#testSetKeepUpdated" />
   <option name="compatibility:exclude-filter"
+          value="CtsGraphicsTestCases android.graphics.cts.AnimatorLeakTest#testPauseResume"/>
+  <option name="compatibility:exclude-filter"
       value="CtsLocationFineTestCases android.location.cts.fine.LocationManagerFineTest#testRegisterGnssMeasurementsCallback" />
   <option name="compatibility:exclude-filter" value="CtsTransitionTestCases"/>
   <option name="compatibility:exclude-filter"
       value="CtsVoiceInteractionTestCases android.voiceinteraction.cts.DirectActionsTest" />
   <option name="compatibility:exclude-filter"
       value="CtsWidgetTestCases android.widget.cts.ZoomControlsTest#testHasFocus" />
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.TextViewTest#testOnBackInvokedCallback"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.TextViewTest#testUndo_imeInsertAndDeleteLatin"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.TimePickerTest#testConstructorNullContext2"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToggleButtonTest#testAttributesFromLayout"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToggleButtonTest#testSetChecked"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToolbarTest#testNavigationConfiguration"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToolbarTest#testMenuOverflowShowHide"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToolbarTest#testTitleAndSubtitleContent"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToolbarTest#testCurrentContentInsetsRtl"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ToolbarTest#testMenuContent"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.TwoLineListItemTest#testConstructorWithNullContext2"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.TwoLineListItemTest#testConstructor"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ViewAnimatorTest#testAccessDisplayedChild"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ViewAnimatorTest#testGetBaseline"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ZoomButtonTest#testConstructorWithNullContext2"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ZoomControlsTest#testSetZoomSpeed"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.inline.InlineContentViewTest#testSetSurfaceControlCallback"/>
+<option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ViewFlipperTest#testConstructorNullContext"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsWidgetTestCases android.widget.cts.ViewFlipperTest#testConstructor"/>
 
   <!-- also fails on sdk_phone -->
+  <!-- causes bluetooth crash b/254094190 -->
+  <option name="compatibility:exclude-filter"
+          value="CtsAppTestCases android.app.cts.ActivityManagerProcessStateTest#testFgsSticky3"/>
   <option name="compatibility:exclude-filter"
       value="CtsAppTestCases android.app.cts.SystemFeaturesTest#testLocationFeatures" />
   <option name="compatibility:exclude-filter"
@@ -58,6 +112,12 @@
       value="CtsAppTestCases android.app.cts.SystemFeaturesTest#testSensorFeatures" />
   <option name="compatibility:exclude-filter"
       value="CtsContentTestCases android.content.pm.cts.InstallSessionParamsUnitTest#checkSessionParams[11]" />
+  <option name="compatibility:exclude-filter"
+          value="CtsContentTestCases android.content.pm.cts.ChecksumsTest#testFixedFSVerityDefaultChecksumsIncremental"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsContentTestCases android.content.pm.cts.ChecksumsTest#testFixedFSVerityDefaultChecksums"/>
+  <option name="compatibility:exclude-filter"
+          value="CtsGraphicsTestCases android.graphics.cts.VulkanFeaturesTest#testVulkanHardwareFeatures"/>
 
   <!-- documentsui dependent tests -->
   <option name="compatibility:exclude-filter"
@@ -85,6 +145,9 @@
       value="CtsAppTestCases android.app.cts.NotificationManagerTest#testNotificationManagerBubble_checkIsBubbled_pendingIntent"/>
   <option name="compatibility:exclude-filter"
       value="CtsAppTestCases android.app.cts.NotificationManagerTest#testNotificationManagerBubble_checkIsBubbled_shortcut"/>
+  <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.NotificationManagerBubbleTest"/>
+  <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.NotificationTemplateTest#testPromoteBigPicture_withLargeIcon"/>         |
+  <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.NotificationTemplateTest#testPromoteBigPicture_withBigLargeIcon"/>
   <option name="compatibility:exclude-filter"
       value="CtsOsTestCases android.os.cts.AppHibernationIntegrationTest#testUnusedApp_getsForceStopped" />
   <option name="compatibility:exclude-filter"
@@ -99,11 +162,16 @@
       value="CtsViewTestCases android.view.cts.ViewTest#testGetWindowVisibleDisplayFrame" />
   <option name="compatibility:exclude-filter"
       value="CtsWidgetTestCases android.widget.cts.ToastTest" />
+  <option name="compatibility:exclude-filter" value="CtsSliceTestCases android.slice.cts.SlicePermissionsTest#testPermissionIntent"/>
 
   <!-- other apps dependent tests -->
+  <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.ActivityManagerTest#testHomeVisibilityListener"/>
+  <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.ActivityManagerFgsBgStartTest#testVisibleActivityGracePeriod"/>
   <option name="compatibility:exclude-filter"
       value="CtsContentTestCases android.content.cts.AvailableIntentsTest"/>
   <option name="compatibility:exclude-filter"
+          value="CtsGraphicsTestCases android.graphics.cts.SystemPaletteTest#testThemeStyles"/>
+  <option name="compatibility:exclude-filter"
       value="CtsOsTestCases android.os.cts.AppHibernationIntegrationTest#testAppInfo_RemovePermissionsAndFreeUpSpaceToggleExists" />
   <option name="compatibility:exclude-filter"
       value="CtsOsTestCases android.os.cts.CompanionDeviceManagerTest#testProfiles" />
@@ -130,6 +198,8 @@
   <option name="compatibility:exclude-filter"
       value="CtsGraphicsTestCases android.graphics.drawable.cts.AnimatedImageDrawableTest#testLifeCycle" />
   <option name="compatibility:exclude-filter"
+          value="CtsGraphicsTestCases android.graphics.cts.HardwareRendererTest#isDrawingEnabled_defaultsTrue"/>
+  <option name="compatibility:exclude-filter"
       value="CtsNativeHardwareTestCases" />
   <option name="compatibility:exclude-filter"
       value="CtsViewTestCases android.view.cts.ASurfaceControlTest" />
@@ -160,5 +230,7 @@
   <option name="compatibility:exclude-filter"
       value="CtsViewTestCases android.view.cts.ViewAnimationMatrixTest#testAnimationMatrixClearedWithPassingNull"/>
   <option name="compatibility:exclude-filter" value="CtsUiRenderingTestCases"/>
+  <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.TextureViewTest#testCropRect"/>
+
 
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-system.xml b/tools/cts-tradefed/res/config/cts-system.xml
new file mode 100644
index 0000000..530fe79
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-system.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<configuration description="Runs a subset of CTS tests when vendor image is not changed">
+    <option name="plan" value="cts-system" />
+    <option name="result-attribute" key="system" value="1" />
+
+    <include name="cts" />
+
+    <!-- dEQP tests to be included in this plan-->
+    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-EGL.*" />
+    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-VK.wsi.*" />
+    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES2.functional.prerequisite#*" />
+    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES3.functional.prerequisite#*" />
+    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-VK.api.smoke#*" />
+
+</configuration>
\ No newline at end of file
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
index 9db955c..127d4d7 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
@@ -91,43 +91,43 @@
                     }
                     // Ensure the files requested to be pushed exist.
                     if (prep instanceof FilePusher && ((FilePusher) prep).shouldAppendBitness()) {
+                        if (!((FilePusher) prep).shouldAbortOnFailure()) {
+                            errors.add(String.format("Config %s should not disable abort-on-push-failure", config.getName()));
+                        }
                         for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) {
                             String path = f.getPath();
                             File file32 = FileUtil.findFile(config.getParentFile(), path + "32");
                             File file64 = FileUtil.findFile(config.getParentFile(), path + "64");
                             if (file32 == null || file64 == null) {
-                                // TODO: Enforce should abort on failure is True in CTS
-                                if (((FilePusher) prep).shouldAbortOnFailure()) {
-                                    errors.add(
-                                            String.format(
-                                                    "File %s[32/64] wasn't found in module "
-                                                            + "dependencies while it's expected to "
-                                                            + "be pushed as part of %s. Make sure "
-                                                            + "that it's added in the Android.bp "
-                                                            + "file of the module under "
-                                                            + "'data_device_bins_both' field.",
-                                                    path, config.getName()));
-                                    continue;
-                                }
+                                errors.add(
+                                        String.format(
+                                                "File %s[32/64] wasn't found in module "
+                                                        + "dependencies while it's expected to "
+                                                        + "be pushed as part of %s. Make sure "
+                                                        + "that it's added in the Android.bp "
+                                                        + "file of the module under "
+                                                        + "'data_device_bins_both' field.",
+                                                        path, config.getName()));
+                                continue;
                             }
                         }
                     } else if (prep instanceof PushFilePreparer) {
+                        if (!((PushFilePreparer) prep).shouldAbortOnFailure()) {
+                            errors.add(String.format("Config %s should not disable abort-on-push-failure", config.getName()));
+                        }
                         for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) {
                             String path = f.getPath();
                             // Use findFiles to also match top-level dir, which is a valid push spec
                             Set<String> toBePushed = FileUtil.findFiles(config.getParentFile(),
                                                                         path);
                             if (toBePushed.isEmpty()) {
-                                // TODO: Enforce should abort on failure is True in CTS
-                                if (((PushFilePreparer) prep).shouldAbortOnFailure()) {
-                                    errors.add(
-                                            String.format(
-                                                    "File %s wasn't found in module dependencies "
-                                                            + "while it's expected to be pushed "
-                                                            + "as part of %s. Make sure that it's added in the Android.bp file of the module under 'data' field.",
-                                                    path, config.getName()));
-                                    continue;
-                                }
+                                errors.add(
+                                        String.format(
+                                                "File %s wasn't found in module dependencies "
+                                                        + "while it's expected to be pushed "
+                                                        + "as part of %s. Make sure that it's added in the Android.bp file of the module under 'data' field.",
+                                                        path, config.getName()));
+                                continue;
                             }
                         }
                     }
diff --git a/tools/vm-tests-tf/Android.bp b/tools/vm-tests-tf/Android.bp
index 09afedb..450f947 100644
--- a/tools/vm-tests-tf/Android.bp
+++ b/tools/vm-tests-tf/Android.bp
@@ -182,10 +182,8 @@
 java_test_host {
     name: "vm-tests-tf",
     static_libs: [
-        "vm-tests-tf-lib"
-    ],
-    libs: [
         "compatibility-host-vm-targetprep",
+        "vm-tests-tf-lib",
     ],
     test_config: "AndroidTest.xml",
     test_suites: [
diff --git a/tools/vm-tests-tf/targetprep/Android.bp b/tools/vm-tests-tf/targetprep/Android.bp
index 76cb248..3aa8ea3 100644
--- a/tools/vm-tests-tf/targetprep/Android.bp
+++ b/tools/vm-tests-tf/targetprep/Android.bp
@@ -17,7 +17,7 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-java_test_host {
+java_library_host {
     name: "compatibility-host-vm-targetprep",
     srcs: ["src/**/*.java"],
     libs: [
@@ -25,10 +25,4 @@
         "cts-tradefed",
         "tradefed",
     ],
-
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
 }