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",
- ],
}