Merge "Ensure device unlocked for screenshot tests." into tm-dev
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgradeWrongSHA_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgradeWrongSHA_apk.asciipb
index f866875..a9d7348 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: "7552332"
+ build_id: "8572644"
target: "CtsShim"
source_file: "aosp_arm64/CtsShimPrivUpgradeWrongSHA.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/cts"
- git_branch: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgrade_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__arm_CtsShimPrivUpgrade_apk.asciipb
index ccefcc1..62ab040 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: "7552332"
+ build_id: "8572644"
target: "CtsShim"
source_file: "aosp_arm64/CtsShimPrivUpgrade.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/cts"
- git_branch: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgradeWrongSHA_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgradeWrongSHA_apk.asciipb
index 264169d..a20b738 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: "7552332"
+ build_id: "8572644"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShimPrivUpgradeWrongSHA.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/cts"
- git_branch: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgrade_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_appsecurity_test-apps_PrivilegedUpdateApp_apk__x86_CtsShimPrivUpgrade_apk.asciipb
index 543d7cc..3371432 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: "7552332"
+ build_id: "8572644"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShimPrivUpgrade.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/cts"
- git_branch: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
index 6a1a592..7806ac3 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v1_apex.asciipb
index c01e04d..280dc99 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index 91c5d50..2b13a41 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index d7e36fc..c852f2c 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apex.asciipb
index 849bab8..566d73d 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index e59bbb1..7f394da 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_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
new file mode 100644
index 0000000..c3b3d1c
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+ android_build_drop {
+ build_id: "8572644"
+ target: "CtsShim"
+ source_file: "aosp_arm64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
+ }
+ dest_file: "hostsidetests/stagedinstall/testdata/apex//arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
+ version: ""
+ version_group: ""
+ git_project: "platform/cts"
+ git_branch: "tm-dev"
+ transform: TRANSFORM_NONE
+ transform_options {
+ }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 4aeed69..8ad7148 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index 21717fc..c5bf540 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index 74573f6..b43824e4 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
index 5672e5c..86dd2d0 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index acc83c0..63e244b 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
index 13268eb..d301677 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index 355f90b..0a0fa3a 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index b840674..cde81d7 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index 60a8a3e..4b7066b 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index c360e44..64f31fb 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index 9941db2..6430590 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index e041816..b103b78 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index 987a82a..b3f859b 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 2531fbb..eced4cc 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_apex.asciipb
index 6e6b103..f0a1f9a 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
index 655689a..d730662 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index ba0e7b80..f617b9a 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index c470fe8..21a4921 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
index 09b85f6..9fee80e 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v1_apex.asciipb
index c057c89..e00e0c0 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index 82422cb..70ea7a4 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index f29ff0d..fe22126 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apex.asciipb
index 8f2a136..4f7f762 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index 766bf19..76f970a 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_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
new file mode 100644
index 0000000..405905e
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
@@ -0,0 +1,15 @@
+drops {
+ android_build_drop {
+ build_id: "8572644"
+ target: "CtsShim"
+ source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
+ }
+ dest_file: "hostsidetests/stagedinstall/testdata/apex//x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
+ version: ""
+ version_group: ""
+ git_project: "platform/cts"
+ git_branch: "tm-dev"
+ transform: TRANSFORM_NONE
+ transform_options {
+ }
+}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index b88b655..ba4d65d 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index 9d7558d..a0cc1809 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index e5c6b65..a491c76 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
index 0be6a59..bc87363 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index f1e7a2c..1399178 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
index a986691..70a1d02 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index be1b3a8..10f11a4 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index be9efdc..ec33561 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index d675fce..57bd84b 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index f3774cc..d2dd61b 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index 2f7c565..3ec6a81 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 5bbee67..43416aa 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index d8a6bd5..f6e5294 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 207fa1d..4e9edcd 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_apex.asciipb
index 6ef3eb5..5391c48 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
index 5264200..bc44538 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index face859..4257f29 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apex__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index 84a1dbe..022a4bb 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: "7552332"
+ build_id: "8572644"
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: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__arm_CtsShimTargetPSdk_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__arm_CtsShimTargetPSdk_apk.asciipb
index d62c281..3f1c95d 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: "7552332"
+ build_id: "8572644"
target: "CtsShim"
source_file: "aosp_arm64/CtsShimTargetPSdk.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/cts"
- git_branch: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__x86_CtsShimTargetPSdk_apk.asciipb b/.prebuilt_info/prebuilt_info_hostsidetests_stagedinstall_testdata_apk_CtsShimTargetPSdk__x86_CtsShimTargetPSdk_apk.asciipb
index cb1fd5f..d4a6c09 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: "7552332"
+ build_id: "8572644"
target: "CtsShim"
source_file: "aosp_x86_64/CtsShimTargetPSdk.apk"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/cts"
- git_branch: "sc-dev"
+ git_branch: "tm-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 96eb23b..45eb773 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -6014,8 +6014,6 @@
<intent-filter>
<action android:name="android.telephony.VisualVoicemailService"/>
</intent-filter>
- <meta-data android:name="ApiTest"
- android:value="android.telephony.VisualVoicemailService#onCellServiceConnected|android.telephony.VisualVoicemailService#onSimRemoved"/>
</service>
<activity
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java
index 2fe31d4..ea3b9b7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java
@@ -36,6 +36,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
@@ -64,6 +66,7 @@
private static ActivityManager sActivityManager;
private static String sAppPackageName;
+ private static ExecutorService sExecutorService;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -71,6 +74,7 @@
sContext = this;
sActivityManager = sContext.getSystemService(ActivityManager.class);
+ sExecutorService = Executors.newSingleThreadExecutor();
// Setup the UI.
setContentView(R.layout.logcat_read_logs);
@@ -106,65 +110,74 @@
*/
public void runLogcatInForegroundAllowOnlyOnce() {
Log.d(TAG, "Inside runLogcatInForeground()");
- BufferedReader reader = null;
- try {
- // Dump the logcat most recent 10 lines before the compile command,
- // and check if there are logs about compiling the test package.
- java.lang.Process logcat = new ProcessBuilder(
- Arrays.asList("logcat", "-b", "system", "-t",
- Integer.toString(NUM_OF_LINES_FG))).start();
- reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
- logcat.waitFor();
- List<String> logcatOutput = new ArrayList<>();
- String current;
- Integer lineCount = 0;
- while ((current = reader.readLine()) != null) {
- logcatOutput.add(current);
- lineCount++;
- }
+ sExecutorService.execute(new Runnable() {
- Log.d(TAG, "Logcat system allow line count: " + lineCount);
- Log.d(TAG, "Logcat system allow output: " + logcatOutput);
+ public void run() {
+ BufferedReader reader = null;
+ try {
- try {
+ // Dump the logcat most recent 10 lines before the compile command,
+ // and check if there are logs about compiling the test package.
+ java.lang.Process logcat = new ProcessBuilder(
+ Arrays.asList("logcat", "-b", "system", "-t",
+ Integer.toString(NUM_OF_LINES_FG))).start();
+ reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
+ logcat.waitFor();
- assertTrue("System log output is null", logcatOutput.size() != 0);
+ List<String> logcatOutput = new ArrayList<>();
+ String current;
+ Integer lineCount = 0;
+ while ((current = reader.readLine()) != null) {
+ logcatOutput.add(current);
+ lineCount++;
+ }
- // Check if the logcatOutput is not null. If logcatOutput is null,
- // it throws an assertion error
- assertNotNull(logcatOutput.get(0), "logcat output should not be null");
+ Log.d(TAG, "Logcat system allow line count: " + lineCount);
+ Log.d(TAG, "Logcat system allow output: " + logcatOutput);
- boolean allowLog = logcatOutput.get(0).contains(SYSTEM_LOG_START);
- assertTrue("Allow system log access containe log", allowLog);
+ try {
- boolean allowLineCount = lineCount > NUM_OF_LINES_FG;
- assertTrue("Allow system log access count", allowLineCount);
+ assertTrue("System log output is null", logcatOutput.size() != 0);
- Log.d(TAG, "Logcat system allow log contains: " + allowLog + " lineCount: "
- + lineCount + " larger than: " + allowLineCount);
+ // Check if the logcatOutput is not null. If logcatOutput is null,
+ // it throws an assertion error
+ assertNotNull(logcatOutput.get(0), "logcat output should not be null");
- } catch (AssertionError e) {
- fail("User Consent Allow Testing failed");
- }
+ boolean allowLog = logcatOutput.get(0).contains(SYSTEM_LOG_START);
+ assertTrue("Allow system log access containe log", allowLog);
- } catch (Exception e) {
- Log.e(TAG, "User Consent Testing failed");
- } finally {
- try {
- if (reader != null) {
- reader.close();
+ boolean allowLineCount = lineCount > NUM_OF_LINES_FG;
+ assertTrue("Allow system log access count", allowLineCount);
+
+ Log.d(TAG, "Logcat system allow log contains: " + allowLog + " lineCount: "
+ + lineCount + " larger than: " + allowLineCount);
+
+ } catch (AssertionError e) {
+ fail("User Consent Allow Testing failed");
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "User Consent Testing failed");
+ } finally {
+ try {
+ if (reader != null) {
+ reader.close();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "Could not close reader: " + e.getMessage());
+ }
}
- } catch (IOException e) {
- Log.d(TAG, "Could not close reader: " + e.getMessage());
}
- }
+ });
}
private void fail(CharSequence reason) {
- Toast.makeText(this, reason, Toast.LENGTH_LONG).show();
- Log.e(TAG, reason.toString());
- setTestResultAndFinish(false);
+ runOnUiThread(() -> {
+ Toast.makeText(this, reason, Toast.LENGTH_LONG).show();
+ Log.e(TAG, reason.toString());
+ setTestResultAndFinish(false);
+ });
}
/**
@@ -172,44 +185,51 @@
*/
public void runLogcatInForegroundDontAllow() {
Log.d(TAG, "Inside runLogcatInForeground()");
- BufferedReader reader = null;
- try {
- java.lang.Process logcat = new ProcessBuilder(
- Arrays.asList("logcat", "-b", "system", "-t",
- Integer.toString(NUM_OF_LINES_FG))).start();
- logcat.waitFor();
- // Merge several logcat streams, and take the last N lines
- reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
- assertNotNull(reader);
+ sExecutorService.execute(new Runnable() {
- List<String> logcatOutput = new ArrayList<>();
- String current;
- int lineCount = 0;
- while ((current = reader.readLine()) != null) {
- logcatOutput.add(current);
- lineCount++;
- }
+ public void run() {
+ BufferedReader reader = null;
+ try {
+ java.lang.Process logcat = new ProcessBuilder(
+ Arrays.asList("logcat", "-b", "system", "-t",
+ Integer.toString(NUM_OF_LINES_FG))).start();
+ logcat.waitFor();
- Log.d(TAG, "Logcat system deny line count:" + lineCount);
+ // Merge several logcat streams, and take the last N lines
+ reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
+ assertNotNull(reader);
- try {
- assertTrue("Deny System log access", lineCount == NUM_OF_LINES_BG);
- } catch (AssertionError e) {
- fail("User Consent Deny Testing failed");
- }
+ List<String> logcatOutput = new ArrayList<>();
+ String current;
+ int lineCount = 0;
+ while ((current = reader.readLine()) != null) {
+ logcatOutput.add(current);
+ lineCount++;
+ }
- } catch (Exception e) {
- Log.e(TAG, "User Consent Testing failed");
- } finally {
- try {
- if (reader != null) {
- reader.close();
+ Log.d(TAG, "Logcat system deny line count:" + lineCount);
+
+ try {
+ assertTrue("Deny System log access", lineCount == NUM_OF_LINES_BG);
+ } catch (AssertionError e) {
+ fail("User Consent Deny Testing failed");
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "User Consent Testing failed");
+ } finally {
+ try {
+ if (reader != null) {
+ reader.close();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "Could not close reader: " + e.getMessage());
+ }
}
- } catch (IOException e) {
- Log.d(TAG, "Could not close reader: " + e.getMessage());
}
- }
+ });
+
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java
index 6ddcf71..8d2fe90 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ManagedUserPositiveTestActivity.java
@@ -214,7 +214,10 @@
}
private Intent createSetOrganizationNameIntent() {
- return new Intent(CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
+ return new Intent(this, CommandReceiverActivity.class)
+ .putExtra(CommandReceiverActivity.EXTRA_COMMAND,
+ CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
+ .putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true)
.putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME, "Foo, Inc.");
}
}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/UserControlDisabledPackages.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/UserControlDisabledPackages.java
index c47db87..3c57540 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/UserControlDisabledPackages.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/UserControlDisabledPackages.java
@@ -17,7 +17,9 @@
package com.android.bedstead.harrier.policies;
import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER;
import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_GLOBALLY;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
@@ -28,6 +30,9 @@
* {@code DevicePolicyManager#setUserControlDisabledPackages(ComponentName, List)} and
* {@code DevicePolicyManager#getUserControlDisabledPackages(ComponentName)}.
*/
-@EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER | APPLIES_GLOBALLY)
+@EnterprisePolicy(dpc = {
+ APPLIED_BY_DEVICE_OWNER | APPLIES_GLOBALLY,
+ APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
+})
public final class UserControlDisabledPackages {
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Versions.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Versions.java
index 8444cb2..bd37257 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Versions.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Versions.java
@@ -34,13 +34,14 @@
private static final String TAG = "Versions";
- public static final int T = CUR_DEVELOPMENT;
+ public static final int T = Build.VERSION_CODES.TIRAMISU;
+ public static final int U = Build.VERSION_CODES.CUR_DEVELOPMENT;
/** Any version. */
public static final int ANY = -1;
private static final ImmutableSet<String> DEVELOPMENT_CODENAMES =
- ImmutableSet.of("Sv2", "T", "Tiramisu");
+ ImmutableSet.of("UpsideDownCake");
private Versions() {
diff --git a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
index e8da4b0..c3dfb95 100644
--- a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
@@ -119,6 +119,8 @@
*/
@Test
public void testRemoveClonedProfileMediaProviderCleanup() throws Exception {
+ assumeTrue(isAtLeastT());
+
String cloneProfileImage = NONCE + "cloneProfileImage.png";
// Inserting blank image in clone profile
@@ -178,6 +180,8 @@
@Test
public void testCrossUserMediaAccess() throws Exception {
+ assumeTrue(isAtLeastT());
+
// Install the app in both the user spaces
installPackage(APP_A, "--user all");
diff --git a/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java b/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java
index 37c7b2d..c0b098a 100644
--- a/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java
+++ b/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java
@@ -178,6 +178,8 @@
// remove volumes that belong to owner profile
volumeListIncludingShared.removeAll(volumeList);
+ assertThat(volumeListIncludingShared.size()).isGreaterThan(0);
+
// remaining volumes should belong to the clone user.
for (StorageVolume vol : volumeListIncludingShared) {
assertThat(vol.getOwner().getIdentifier()).isEqualTo(cloneUserId);
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/ContactsIndexerMultiUserTest.java b/hostsidetests/appsearch/src/android/appsearch/cts/ContactsIndexerMultiUserTest.java
index 6ebd2b1..7fba4c9 100644
--- a/hostsidetests/appsearch/src/android/appsearch/cts/ContactsIndexerMultiUserTest.java
+++ b/hostsidetests/appsearch/src/android/appsearch/cts/ContactsIndexerMultiUserTest.java
@@ -40,7 +40,6 @@
public class ContactsIndexerMultiUserTest extends AppSearchHostTestBase {
private static int sSecondaryUserId;
- private static int sTertiaryUserId;
@BeforeClassWithInfo
public static void setUpClass(TestInformation testInfo) throws Exception {
@@ -49,8 +48,6 @@
sSecondaryUserId = testInfo.getDevice().createUser("Test User #1");
assertThat(testInfo.getDevice().startUser(sSecondaryUserId)).isTrue();
- sTertiaryUserId = testInfo.getDevice().createUser("Test User #2");
- assertThat(testInfo.getDevice().startUser(sTertiaryUserId)).isTrue();
}
@Before
@@ -58,11 +55,7 @@
if (!getDevice().isUserRunning(sSecondaryUserId)) {
getDevice().startUser(sSecondaryUserId, /*waitFlag=*/ true);
}
- if (!getDevice().isUserRunning(sTertiaryUserId)) {
- getDevice().startUser(sTertiaryUserId, /*waitFlag=*/ true);
- }
installPackageAsUser(TARGET_APK_A, /*grantPermission=*/ true, sSecondaryUserId);
- installPackageAsUser(TARGET_APK_A, /*grantPermission=*/ true, sTertiaryUserId);
}
@AfterClassWithInfo
@@ -70,9 +63,6 @@
if (sSecondaryUserId > 0) {
testInfo.getDevice().removeUser(sSecondaryUserId);
}
- if (sTertiaryUserId > 0) {
- testInfo.getDevice().removeUser(sTertiaryUserId);
- }
}
@Test
@@ -80,8 +70,5 @@
runContactsIndexerDeviceTestAsUserInPkgA("testFullUpdateJobIsScheduled",
sSecondaryUserId,
Collections.singletonMap(USER_ID_KEY, String.valueOf(sSecondaryUserId)));
- runContactsIndexerDeviceTestAsUserInPkgA("testFullUpdateJobIsScheduled",
- sTertiaryUserId,
- Collections.singletonMap(USER_ID_KEY, String.valueOf(sTertiaryUserId)));
}
}
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
index 5c8aaa5..f1730f6 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 3cb1a4b..cdb279a 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
index 3bfa2bb..42135bc 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 0c69d99..f9e6f96 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/neuralnetworks/app/src/com/android/nn/stats/app/NnapiDeviceActivity.java b/hostsidetests/neuralnetworks/app/src/com/android/nn/stats/app/NnapiDeviceActivity.java
index e372fb9..7dc4015 100644
--- a/hostsidetests/neuralnetworks/app/src/com/android/nn/stats/app/NnapiDeviceActivity.java
+++ b/hostsidetests/neuralnetworks/app/src/com/android/nn/stats/app/NnapiDeviceActivity.java
@@ -21,7 +21,7 @@
import android.util.Log;
/**
- * A simple activity which triggers libneuralnetworks.so to push WestWorld atoms.
+ * A simple activity which triggers libneuralnetworks.so to push statsd atoms.
*/
public class NnapiDeviceActivity extends Activity {
private static final String TAG = NnapiDeviceActivity.class.getSimpleName();
@@ -33,7 +33,7 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Log.i(TAG, "Triggering libneuralnetworks.so to push WestWorld atoms.");
+ Log.i(TAG, "Triggering libneuralnetworks.so to push statsd atoms.");
trigger_libneuralnetworks_atoms();
}
diff --git a/hostsidetests/packagemanager/dynamicmime/src/android/dynamicmime/cts/RebootTestCases.java b/hostsidetests/packagemanager/dynamicmime/src/android/dynamicmime/cts/RebootTestCases.java
index a26de84..d6fb65e 100644
--- a/hostsidetests/packagemanager/dynamicmime/src/android/dynamicmime/cts/RebootTestCases.java
+++ b/hostsidetests/packagemanager/dynamicmime/src/android/dynamicmime/cts/RebootTestCases.java
@@ -40,6 +40,8 @@
private static final String PACKAGE_TEST_APP = "android.dynamicmime.testapp";
private static final String PACKAGE_REBOOT_TESTS = PACKAGE_TEST_APP + ".reboot";
+ private static final int SETTINGS_WRITE_TIMEOUT_MS = 10_000;
+
@Test
public void testGroupWithExactType() throws DeviceNotAvailableException {
runTestWithReboot("SingleAppTest", "testGroupWithExactType");
@@ -213,6 +215,7 @@
private void runTestWithReboot(String testClassName, String testMethodName)
throws DeviceNotAvailableException {
runPreReboot(testClassName, testMethodName);
+ waitForSettingsWrite();
getDevice().reboot();
runPostReboot(testClassName, testMethodName);
}
@@ -223,6 +226,13 @@
testMethodName);
}
+ private void waitForSettingsWrite() {
+ try {
+ Thread.sleep(SETTINGS_WRITE_TIMEOUT_MS);
+ } catch (InterruptedException ignored) {
+ }
+ }
+
private void runPreReboot(String testClassName, String testMethodName)
throws DeviceNotAvailableException {
runDeviceTests(PACKAGE_TEST_APP, PACKAGE_REBOOT_TESTS + ".PreReboot" + testClassName,
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index 86383ec..17edaae 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -21,8 +21,7 @@
manifest: "ScopedStorageTestHelper/TestAppA.xml",
static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
@@ -54,8 +53,7 @@
manifest: "ScopedStorageTestHelper/TestAppB.xml",
static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
@@ -71,8 +69,7 @@
manifest: "ScopedStorageTestHelper/TestAppC.xml",
static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
@@ -136,8 +133,7 @@
manifest: "ScopedStorageTestHelper/TestAppFileManager.xml",
static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
@@ -153,8 +149,7 @@
manifest: "ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml",
static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
@@ -170,8 +165,7 @@
manifest: "ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml",
static_libs: ["cts-scopedstorage-lib"],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
@@ -232,8 +226,7 @@
"cts",
],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
java_resources: [
":CtsScopedStorageTestAppA",
@@ -378,6 +371,7 @@
"truth-prebuilt",
"cts-scopedstorage-lib",
"androidx.test.uiautomator_uiautomator",
+ "modules-utils-build_system",
],
compile_multilib: "both",
test_suites: [
@@ -386,8 +380,7 @@
"cts",
],
sdk_version: "test_current",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
min_sdk_version: "30",
libs: [
"android.test.base",
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 1a3bff9..6e87ad3 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -143,6 +143,7 @@
import androidx.test.filters.SdkSuppress;
import com.android.cts.install.lib.TestApp;
+import com.android.modules.utils.build.SdkLevel;
import com.google.common.io.Files;
@@ -1263,12 +1264,18 @@
@Test
public void testReadStorageInvalidation() throws Exception {
- testAppOpInvalidation(
+ if (SdkLevel.isAtLeastT()) {
+ testAppOpInvalidation(
APP_C,
new File(getDcimDir(), "read_storage.jpg"),
Manifest.permission.READ_MEDIA_IMAGES,
AppOpsManager.OPSTR_READ_MEDIA_IMAGES,
/* forWrite */ false);
+ } else {
+ testAppOpInvalidation(APP_C, new File(getDcimDir(), "read_storage.jpg"),
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, /* forWrite */ false);
+ }
}
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java
new file mode 100644
index 0000000..ee835f5
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.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 android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39797 extends StsExtraBusinessLogicHostTestBase {
+
+ @AsbSecurityTest(cveBugId = 209607104)
+ @Test
+ public void testPocCVE_2021_39797() throws Exception {
+ ITestDevice device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2021_39797_test";
+ final String targetPkg = "android.security.cts.CVE_2021_39797_target";
+ uninstallPackage(device, testPkg);
+ uninstallPackage(device, targetPkg);
+
+ /* 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);
+
+ installPackage("CVE-2021-39797-test.apk");
+ installPackage("CVE-2021-39797-target.apk");
+ String previous = AdbUtils.runCommandLine("settings get global hidden_api_policy", device);
+
+ /* Set the property hidden_api_policy to 1 in order to access the vulnerable function
+ getMainActivityLaunchIntent of class LauncherApps */
+ AdbUtils.runCommandLine("settings put global hidden_api_policy 1", device);
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testTaskOverride");
+
+ /* Restore the property hidden_api_policy to its previous value */
+ AdbUtils.runCommandLine("settings put global hidden_api_policy " + previous, device);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/Android.bp
new file mode 100644
index 0000000..4a58ef3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * 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: "CVE-2021-39797-target",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/AndroidManifest.xml
new file mode 100644
index 0000000..514c75a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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_2021_39797_target">
+ <application android:label="CVE-2021-39797-target">
+ <activity android:name=".TargetActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/src/android/security/cts/CVE_2021_39797_target/TargetActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/src/android/security/cts/CVE_2021_39797_target/TargetActivity.java
new file mode 100644
index 0000000..b49da17
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/target-app/src/android/security/cts/CVE_2021_39797_target/TargetActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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_39797_target;
+
+import android.app.Activity;
+
+public class TargetActivity extends Activity {
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/Android.bp
new file mode 100644
index 0000000..aa4e813
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * 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: "CVE-2021-39797-test",
+ defaults: ["cts_support_defaults"],
+ 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-2021-39797/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..31c61f7b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?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_2021_39797_test">
+ <application android:label="CVE-2021-39797-test">
+ <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>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39797_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/res/values/integers.xml
new file mode 100644
index 0000000..363df00
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/res/values/integers.xml
@@ -0,0 +1,21 @@
+<?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>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="noAssumptionFailure">0</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/res/values/strings.xml
new file mode 100644
index 0000000..e61e413
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/res/values/strings.xml
@@ -0,0 +1,45 @@
+<?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="appUiErrorTargetApp">Timed out waiting on UI of CVE_2021_39797_target App</string>
+ <string name="appUiErrorTestApp">Timed out waiting on UI of CVE_2021_39797_test App</string>
+ <string name="attrTaskOverlay">android.activity.taskOverlay</string>
+ <string name="attrLaunchTaskId">android.activity.launchTaskId</string>
+ <string name="attrPIntentLaunchFlags">android.activity.pendingIntentLaunchFlags</string>
+ <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+ <string name="errorMessage">Device is vulnerable to b/209607104 !!</string>
+ <string name="errorNullCheckPIntent">getMainActivityLaunchIntent returned null, it is expected
+ to return a non-null result</string>
+ <string name="flagTaskSwapped">taskSwapped</string>
+ <string name="invokeExceptionMsg">Got an exception while calling Method.invoke() on
+ LauncherApps method getMainActivityLaunchIntent instance</string>
+ <string name="messageKey">message</string>
+ <string name="noMethodExceptionMsg">Got NoSuchMethodException for LauncherApps method
+ getMainActivityLaunchIntent</string>
+ <string name="resultKey">result</string>
+ <string name="sharedPreferences">prefs</string>
+ <string name="startIntentSenderExceptionMsg">Got an exception while calling startIntentSender
+ </string>
+ <string name="targetPkg">android.security.cts.CVE_2021_39797_target</string>
+ <string name="targetActivityName">android.security.cts.CVE_2021_39797_target.TargetActivity
+ </string>
+ <string name="targetFunction">getMainActivityLaunchIntent</string>
+ <string name="taskId">taskId</string>
+ <string name="timedOutPocActivity">Timed out waiting on a result from PocActivity</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/src/android/security/cts/CVE_2021_39797_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/src/android/security/cts/CVE_2021_39797_test/DeviceTest.java
new file mode 100644
index 0000000..d9a2da3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/src/android/security/cts/CVE_2021_39797_test/DeviceTest.java
@@ -0,0 +1,127 @@
+/**
+ * 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_39797_test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+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.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+
+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.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ static final int TIMEOUT_MS = 10000;
+
+ @Test
+ public void testTaskOverride() {
+ Context context = getApplicationContext();
+ assumeNotNull(context);
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ assumeNotNull(device);
+ String targetPkg = context.getString(R.string.targetPkg);
+ String targetActivityName = context.getString(R.string.targetActivityName);
+
+ // Start the TargetActivity to make it a recent task when we start the PocActivity
+ Intent targetIntent = new Intent();
+ targetIntent.setComponent(new ComponentName(targetPkg, targetActivityName));
+ targetIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(targetIntent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(context.getString(R.string.activityNotFoundMsg, targetIntent), e);
+ }
+ assumeTrue(context.getString(R.string.appUiErrorTargetApp),
+ device.wait(Until.hasObject(By.pkg(targetPkg)), TIMEOUT_MS));
+
+ // Start the PocActivity
+ device.pressHome();
+ Intent intent = new Intent(context, PocActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(context.getString(R.string.activityNotFoundMsg, intent), e);
+ }
+
+ // Wait on a result from PocActivity
+ SharedPreferences sharedPrefs = context.getSharedPreferences(
+ context.getString(R.string.sharedPreferences), Context.MODE_APPEND);
+ assumeNotNull(sharedPrefs);
+ final Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key.equals(context.getString(R.string.resultKey))) {
+ preferenceChanged.release();
+ }
+ }
+ };
+ sharedPrefs.registerOnSharedPreferenceChangeListener(listener);
+ try {
+ preferenceChanged.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ assumeNoException(context.getString(R.string.timedOutPocActivity), e);
+ }
+ int result = sharedPrefs.getInt(context.getString(R.string.resultKey),
+ context.getResources().getInteger(R.integer.assumptionFailure));
+ String message = sharedPrefs.getString(context.getString(R.string.messageKey),
+ context.getString(R.string.defaultSemaphoreMsg));
+ assumeTrue(message,
+ result != context.getResources().getInteger(R.integer.assumptionFailure));
+
+ // Try launching the TargetActivity again. Without fix, it is supposed to be hijacked by
+ // the PocActivity and PocActivity should be started in its place.
+ try {
+ context.startActivity(targetIntent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(context.getString(R.string.activityNotFoundMsg, targetIntent), e);
+ }
+
+ // Wait for the UI of TargetActivity
+ boolean targetActivityDisplayed =
+ device.wait(Until.hasObject(By.pkg(targetPkg)), TIMEOUT_MS);
+
+ // Check if the PocActivity task came up on the screen replacing the TargetActivity task
+ boolean taskSwapped =
+ sharedPrefs.getBoolean(context.getString(R.string.flagTaskSwapped), false);
+
+ // Fail the test only if TargetActivity did not appear on the screen and the task of
+ // TargetActivity is hijacked by the PocActivity
+ assertFalse(context.getString(R.string.errorMessage),
+ !targetActivityDisplayed && taskSwapped);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/src/android/security/cts/CVE_2021_39797_test/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/src/android/security/cts/CVE_2021_39797_test/PocActivity.java
new file mode 100644
index 0000000..42eff75
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39797/test-app/src/android/security/cts/CVE_2021_39797_test/PocActivity.java
@@ -0,0 +1,110 @@
+/*
+ * 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_39797_test;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentSender.SendIntentException;
+import android.content.SharedPreferences;
+import android.content.pm.LauncherApps;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class PocActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences prefs =
+ getSharedPreferences(getString(R.string.sharedPreferences), MODE_PRIVATE);
+ if (prefs == null) {
+ return;
+ }
+ int taskIdSaved = prefs.getInt(getString(R.string.taskId), -1);
+ if (taskIdSaved == -1) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(getString(R.string.taskId), getTaskId());
+ editor.apply();
+ } else {
+ if ((taskIdSaved - 1) == getTaskId()) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(getString(R.string.flagTaskSwapped), true);
+ editor.apply();
+ }
+ setResult(prefs, getResources().getInteger(R.integer.noAssumptionFailure), "");
+ return;
+ }
+
+ Method method;
+ try {
+ method = LauncherApps.class.getMethod(getString(R.string.targetFunction),
+ ComponentName.class, Bundle.class, UserHandle.class);
+ } catch (NoSuchMethodException e) {
+ setResult(prefs, getResources().getInteger(R.integer.assumptionFailure),
+ getString(R.string.noMethodExceptionMsg));
+ return;
+ }
+
+ Bundle options = new Bundle();
+ options.putBoolean(getString(R.string.attrTaskOverlay), true);
+ options.putInt(getString(R.string.attrLaunchTaskId), getTaskId() - 1);
+
+ PendingIntent pi;
+ try {
+ pi = (PendingIntent) method.invoke(getSystemService(LauncherApps.class),
+ getIntent().getComponent(), options,
+ UserHandle.getUserHandleForUid(Process.myUid()));
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ setResult(prefs, getResources().getInteger(R.integer.assumptionFailure),
+ getString(R.string.invokeExceptionMsg));
+ return;
+ }
+ if (pi == null) {
+ setResult(prefs, getResources().getInteger(R.integer.assumptionFailure),
+ getString(R.string.errorNullCheckPIntent));
+ return;
+ }
+
+ Bundle sendOptions = new Bundle();
+ sendOptions.putInt(getString(R.string.attrPIntentLaunchFlags),
+ Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+
+ try {
+ startIntentSender(pi.getIntentSender(), null, 0, 0, 0, sendOptions);
+ } catch (SendIntentException e) {
+ setResult(prefs, getResources().getInteger(R.integer.assumptionFailure),
+ getString(R.string.startIntentSenderExceptionMsg));
+ return;
+ }
+ setResult(prefs, getResources().getInteger(R.integer.noAssumptionFailure), "");
+ }
+
+ private void setResult(SharedPreferences sh, int result, String message) {
+ if (sh != null) {
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
+ }
+ }
+}
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 791d0dd..c2dc28f 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 0a26d23..880ab4a 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 5ed2c7e..8c84cd5 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 133f7f7..b519bbe 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 6ce5397..38e2339 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
new file mode 100644
index 0000000..3d7bf51
--- /dev/null
+++ 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 4228ffe..f4bc7e8 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 de090f1..59e9fe1 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
index 162044c..353949b 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 9d68887..c39b790 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 44f7613..da25328 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 389871d..3eaf372 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 f8fa44f..6f38273 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 9658818..1969746 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 3440043..be642bf 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
index d6f7d8f..7bebb77 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 cc214f8..8006022 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 dab82a0..3465dbb 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 9706f2f..67743a9 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 f305cff..aa1c10c 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 3122c96..b345bca 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 0f5134d..c3bab7c 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 a83bf51..4733bad 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 703b641..6972daa 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 806ccc7..4cda1c6 100644
--- a/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/arm/com.android.apex.cts.shim_not_pre_installed.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v1.apex
index a94ae75..030c53b 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 a9c2758..b090a96 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 5ed2c7e..c498b32 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 133f7f7..e83ec07 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 6ce5397..4545b1c 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
new file mode 100644
index 0000000..298fd85
--- /dev/null
+++ 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 4228ffe..d911fe0 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 de090f1..053df91a 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
index 19ec142..65a5473 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 9d68887..9f94684 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 9929c3d..8fd510c 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 389871d..baae3e3 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 3f2fc50..1e80788 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 cf628ab..c064928 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 ba5af3b..685f347 100644
--- a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex b/hostsidetests/stagedinstall/testdata/apex/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
index 38c073f..f2329ae 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 cc214f8..bb2d96e 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 dab82a0..fd00bd5 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 9706f2f..e7da653 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 f305cff..32bf141 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 7f3e9ec..1bd8b1b 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 0f5134d..2f7a2e5 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 1aeb0b0..38fe019 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 20f1c85..68505d5 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 806ccc7..7fd07b5 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 65f2a3b..3d01f0e 100644
--- a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
+++ b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/arm/CtsShimTargetPSdk.apk
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk b/hostsidetests/stagedinstall/testdata/apk/CtsShimTargetPSdk/x86/CtsShimTargetPSdk.apk
index 65f2a3b..3d01f0e 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/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 e356ea6..3a45dc0 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
@@ -226,6 +226,7 @@
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, 117);
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, 118);
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS, 119);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO, 120);
}
@Test
diff --git a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java
index 0e7b8b5..db6207d 100644
--- a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java
+++ b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java
@@ -16,6 +16,7 @@
package android.alarmmanager.alarmtestapp.cts;
+import android.alarmmanager.alarmtestapp.cts.common.FgsTester;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -24,6 +25,8 @@
public class TestAlarmReceiver extends BroadcastReceiver{
private static final String TAG = TestAlarmReceiver.class.getSimpleName();
private static final String PACKAGE_NAME = "android.alarmmanager.alarmtestapp.cts";
+ private static final String INSTRUMENTATION_PACKAGE = "android.alarmmanager.cts";
+
public static final String ACTION_REPORT_ALARM_EXPIRED = PACKAGE_NAME + ".action.ALARM_EXPIRED";
public static final String EXTRA_ALARM_COUNT = PACKAGE_NAME + ".extra.ALARM_COUNT";
public static final String EXTRA_ID = PACKAGE_NAME + ".extra.ID";
@@ -33,10 +36,18 @@
final int count = intent.getIntExtra(Intent.EXTRA_ALARM_COUNT, 1);
final long id = intent.getLongExtra(EXTRA_ID, -1);
Log.d(TAG, "Alarm " + id + " expired " + count + " times");
- final Intent reportAlarmIntent = new Intent(ACTION_REPORT_ALARM_EXPIRED);
- reportAlarmIntent.putExtra(EXTRA_ALARM_COUNT, count);
- reportAlarmIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- reportAlarmIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ final Intent reportAlarmIntent = new Intent(ACTION_REPORT_ALARM_EXPIRED)
+ .putExtra(EXTRA_ALARM_COUNT, count)
+ .setPackage(INSTRUMENTATION_PACKAGE)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ if (intent.getBooleanExtra(TestAlarmScheduler.EXTRA_TEST_FGS, false)) {
+ final String result = FgsTester.tryStartingFgs(context);
+ Log.d(TAG, "FGS start result: " + result);
+ reportAlarmIntent.putExtra(FgsTester.EXTRA_FGS_START_RESULT, result);
+ }
context.sendBroadcast(reportAlarmIntent);
}
}
diff --git a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmScheduler.java b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmScheduler.java
index d9db0b0..78eb875 100644
--- a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmScheduler.java
+++ b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmScheduler.java
@@ -40,6 +40,7 @@
public static final String EXTRA_TYPE = PACKAGE_NAME + ".extra.TYPE";
public static final String ACTION_SET_ALARM_CLOCK = PACKAGE_NAME + ".action.SET_ALARM_CLOCK";
public static final String EXTRA_ALARM_CLOCK_INFO = PACKAGE_NAME + ".extra.ALARM_CLOCK_INFO";
+ public static final String EXTRA_TEST_FGS = PACKAGE_NAME + ".extra.TEST_FGS";
public static final String ACTION_CANCEL_ALL_ALARMS = PACKAGE_NAME + ".action.CANCEL_ALARMS";
@Override
@@ -49,6 +50,7 @@
receiverIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
final long id = SystemClock.elapsedRealtime();
receiverIntent.putExtra(TestAlarmReceiver.EXTRA_ID, id);
+ receiverIntent.putExtra(EXTRA_TEST_FGS, intent.getBooleanExtra(EXTRA_TEST_FGS, false));
final PendingIntent alarmClockSender = PendingIntent.getBroadcast(context, 0,
receiverIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
final PendingIntent alarmSender = PendingIntent.getBroadcast(context, 1, receiverIntent,
diff --git a/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/FgsTester.java b/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/FgsTester.java
new file mode 100644
index 0000000..f3e0be6
--- /dev/null
+++ b/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/FgsTester.java
@@ -0,0 +1,45 @@
+/*
+ * 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.alarmmanager.alarmtestapp.cts.common;
+
+import android.app.ForegroundServiceStartNotAllowedException;
+import android.content.Context;
+import android.content.Intent;
+
+public class FgsTester {
+ public static final String EXTRA_FGS_START_RESULT =
+ "android.alarmmanager.alarmtestapp.cts.common.extra.FGS_START_RESULT";
+
+ private FgsTester() {
+ }
+
+ public static String tryStartingFgs(Context context) {
+ String result;
+ try {
+ // Try starting a foreground service.
+ Intent i = new Intent(context, TestService.class);
+ context.startForegroundService(i);
+
+ result = ""; // Indicates success
+ } catch (ForegroundServiceStartNotAllowedException e) {
+ result = "ForegroundServiceStartNotAllowedException was thrown";
+ } catch (Exception e) {
+ result = "Unexpected exception was thrown: " + e;
+ }
+ return result;
+ }
+}
diff --git a/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/PermissionStateChangedReceiver.java b/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/PermissionStateChangedReceiver.java
index 9adc4a7..573d10c 100644
--- a/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/PermissionStateChangedReceiver.java
+++ b/tests/AlarmManager/app_common/src/android/alarmmanager/alarmtestapp/cts/common/PermissionStateChangedReceiver.java
@@ -17,7 +17,6 @@
package android.alarmmanager.alarmtestapp.cts.common;
import android.app.AlarmManager;
-import android.app.ForegroundServiceStartNotAllowedException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -30,41 +29,26 @@
public class PermissionStateChangedReceiver extends BroadcastReceiver {
private static final String TAG = PermissionStateChangedReceiver.class.getSimpleName();
private static final String PACKAGE_NAME = "android.alarmmanager.alarmtestapp.cts.common";
-
private static final String MAIN_CTS_PACKAGE = "android.alarmmanager.cts";
- public static String ACTION_FGS_START_RESULT = PACKAGE_NAME + ".action.FGS_START_RESULT";
- public static String EXTRA_FGS_START_RESULT = PACKAGE_NAME + ".extra.FGS_START_RESULT";
+ public static final String ACTION_FGS_START_RESULT = PACKAGE_NAME + ".action.FGS_START_RESULT";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Broadcast received: " + intent);
if (AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
.equals(intent.getAction())) {
- tryStartingFgs(context);
+
+ final String result = FgsTester.tryStartingFgs(context);
+
+ // Send the result broadcast to the main CTS package.
+ final Intent response = new Intent(ACTION_FGS_START_RESULT);
+ response.setPackage(MAIN_CTS_PACKAGE);
+ response.putExtra(FgsTester.EXTRA_FGS_START_RESULT, result);
+
+ Log.d(TAG, "Sending response: " + result);
+ context.sendBroadcast(response);
}
}
- private void tryStartingFgs(Context context) {
- String result = "Unknown failure";
- try {
- // Try starting a foreground service.
- Intent i = new Intent(context, TestService.class);
- context.startForegroundService(i);
-
- result = ""; // Indicates success
- } catch (ForegroundServiceStartNotAllowedException e) {
- result = "ForegroundServiceStartNotAllowedException was thrown";
- } catch (Exception e) {
- result = "Unexpected exception was thrown: " + e;
- }
-
- // Send the result broadcast to the main CTS package.
- Intent response = new Intent(ACTION_FGS_START_RESULT);
- response.setPackage(MAIN_CTS_PACKAGE);
- response.putExtra(EXTRA_FGS_START_RESULT, result);
-
- Log.d(TAG, "Sending response: " + result);
- context.sendBroadcast(response);
- }
}
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
index 0cf62ed..44780e7 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
@@ -26,6 +26,9 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
+import android.alarmmanager.alarmtestapp.cts.TestAlarmReceiver;
+import android.alarmmanager.alarmtestapp.cts.TestAlarmScheduler;
+import android.alarmmanager.alarmtestapp.cts.common.FgsTester;
import android.alarmmanager.alarmtestapp.cts.common.PermissionStateChangedReceiver;
import android.alarmmanager.alarmtestapp.cts.common.RequestReceiver;
import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
@@ -34,6 +37,7 @@
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -142,6 +146,7 @@
.with("allow_while_idle_quota", ALLOW_WHILE_IDLE_QUOTA)
.with("allow_while_idle_compat_quota", ALLOW_WHILE_IDLE_COMPAT_QUOTA)
.with("allow_while_idle_window", ALLOW_WHILE_IDLE_WINDOW)
+ .with("kill_on_schedule_exact_alarm_revoked", false)
.commitAndAwaitPropagation();
}
@@ -155,8 +160,6 @@
public void enableChanges() {
Utils.enableChangeForSelf(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION);
Utils.enableChangeForSelf(AlarmManager.ENABLE_USE_EXACT_ALARM);
- Utils.enableChange(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, TEST_APP_PACKAGE,
- sContext.getUserId());
}
@After
@@ -191,14 +194,14 @@
PackageManager.DONT_KILL_APP));
}
- private void resetAppOps() throws IOException {
+ @After
+ public void resetAppOps() throws IOException {
AppOpsUtils.reset(TEST_APP_PACKAGE);
+ AppOpsUtils.reset(TEST_APP_30);
}
@After
public void restoreAlarmManagerConstants() throws IOException {
- // App ops must be reset while kill_on_schedule_exact_alarm_revoked=false
- resetAppOps();
mDeviceConfigHelper.restoreAll();
}
@@ -247,21 +250,25 @@
}
@Test
+ public void scheduleExactAlarmChangeDisabled() {
+ assertFalse(CompatChanges.isChangeEnabled(
+ AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT));
+ }
+
+ @Test
public void defaultBehaviorWhenChangeDisabled() throws Exception {
setAppOp(TEST_APP_PACKAGE, AppOpsManager.MODE_DEFAULT);
- mDeviceConfigHelper.with("schedule_exact_alarm_denied_by_default", false)
- .commitAndAwaitPropagation();
assertTrue(getCanScheduleExactAlarmFromTestApp(TEST_APP_PACKAGE));
mDeviceConfigHelper.with("exact_alarm_deny_list", TEST_APP_PACKAGE)
.commitAndAwaitPropagation();
- // Just to give some time for the app kill to complete.
- Thread.sleep(1000);
assertFalse(getCanScheduleExactAlarmFromTestApp(TEST_APP_PACKAGE));
}
@Test
- public void noPermissionByDefault() throws Exception {
+ public void defaultBehaviorWhenChangeEnabled() throws Exception {
+ Utils.enableChange(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, TEST_APP_PACKAGE,
+ sContext.getUserId());
setAppOp(TEST_APP_PACKAGE, AppOpsManager.MODE_DEFAULT);
assertFalse(getCanScheduleExactAlarmFromTestApp(TEST_APP_PACKAGE));
}
@@ -362,6 +369,61 @@
() -> mWhitelistManager.addToWhitelist(sContext.getOpPackageName()));
}
+ private void setAlarmClockForFgs(long triggerRTC, String testAppName) throws Exception {
+ final CountDownLatch resultLatch = new CountDownLatch(1);
+ final AtomicInteger result = new AtomicInteger(-1);
+
+ AlarmManager.AlarmClockInfo alarmInfo = new AlarmManager.AlarmClockInfo(triggerRTC, null);
+
+ final Intent requestToTestApp = new Intent(TestAlarmScheduler.ACTION_SET_ALARM_CLOCK)
+ .setClassName(testAppName, TestAlarmScheduler.class.getName())
+ .putExtra(TestAlarmScheduler.EXTRA_ALARM_CLOCK_INFO, alarmInfo)
+ .putExtra(TestAlarmScheduler.EXTRA_TEST_FGS, true)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ sContext.sendOrderedBroadcast(requestToTestApp, null, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ result.set(getResultCode());
+ resultLatch.countDown();
+ }
+ }, null, Activity.RESULT_CANCELED, null, null);
+
+ assertTrue("Timed out waiting for response from helper app " + testAppName,
+ resultLatch.await(10, TimeUnit.SECONDS));
+ assertEquals(Activity.RESULT_OK, result.get());
+ }
+
+ @Test
+ public void alarmClockAllowsFGS() throws Exception {
+ setAppOp(TEST_APP_PACKAGE, AppOpsManager.MODE_ALLOWED);
+
+ final long triggerRtc = System.currentTimeMillis() + 5_000;
+ setAlarmClockForFgs(triggerRtc, TEST_APP_PACKAGE);
+
+ final AtomicReference<String> resultHolder = new AtomicReference<>();
+ final CountDownLatch alarmLatch = new CountDownLatch(1);
+
+ final IntentFilter filter = new IntentFilter(TestAlarmReceiver.ACTION_REPORT_ALARM_EXPIRED);
+ final BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "Received response intent: " + intent);
+ resultHolder.set(intent.getStringExtra(FgsTester.EXTRA_FGS_START_RESULT));
+ alarmLatch.countDown();
+ }
+ };
+ sContext.registerReceiver(receiver, filter);
+ try {
+ Thread.sleep(5_000);
+ assertTrue("AlarmClock expiration not reported",
+ alarmLatch.await(30, TimeUnit.SECONDS));
+ assertEquals("FGS result should be empty", "", resultHolder.get());
+ } finally {
+ sContext.unregisterReceiver(receiver);
+ }
+ }
+
@Test
public void setAlarmClockWithPermission() throws Exception {
final long now = System.currentTimeMillis();
@@ -383,7 +445,6 @@
TEST_APP_PACKAGE);
}
-
@Test
public void setExactAwiWithoutPermissionOrWhitelist() throws Exception {
revokeAppOp(TEST_APP_PACKAGE);
@@ -577,7 +638,7 @@
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received response intent: " + intent);
resultHolder.set(intent.getStringExtra(
- PermissionStateChangedReceiver.EXTRA_FGS_START_RESULT));
+ FgsTester.EXTRA_FGS_START_RESULT));
latch.countDown();
}
};
@@ -618,7 +679,7 @@
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received response intent: " + intent);
resultHolder.set(intent.getStringExtra(
- PermissionStateChangedReceiver.EXTRA_FGS_START_RESULT));
+ FgsTester.EXTRA_FGS_START_RESULT));
latch.countDown();
}
};
diff --git a/tests/MediaProviderTranscode/Android.bp b/tests/MediaProviderTranscode/Android.bp
index 54ee715..cbf6fe2 100644
--- a/tests/MediaProviderTranscode/Android.bp
+++ b/tests/MediaProviderTranscode/Android.bp
@@ -32,8 +32,7 @@
],
min_sdk_version: "30",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
certificate: "media",
java_resources: [":CtsTranscodeTestAppSupportsHevc", ":CtsTranscodeTestAppSupportsSlowMotion"]
}
diff --git a/tests/app/app/src/android/app/stubs/CommandReceiver.java b/tests/app/app/src/android/app/stubs/CommandReceiver.java
index 5e154f7..26ab62b 100644
--- a/tests/app/app/src/android/app/stubs/CommandReceiver.java
+++ b/tests/app/app/src/android/app/stubs/CommandReceiver.java
@@ -19,15 +19,19 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ForegroundServiceStartNotAllowedException;
+import android.app.IActivityManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
+import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -61,6 +65,7 @@
public static final int COMMAND_START_FOREGROUND_SERVICE_STICKY = 20;
public static final int COMMAND_STOP_FOREGROUND_SERVICE_STICKY = 21;
public static final int COMMAND_EMPTY = 22;
+ public static final int COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME = 23;
public static final int RESULT_CHILD_PROCESS_STARTED = IBinder.FIRST_CALL_TRANSACTION;
public static final int RESULT_CHILD_PROCESS_STOPPED = IBinder.FIRST_CALL_TRANSACTION + 1;
@@ -170,6 +175,9 @@
break;
case COMMAND_EMPTY:
break;
+ case COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME:
+ doStartForegroundServiceSpoofPackageName(context, intent);
+ break;
}
}
@@ -371,6 +379,56 @@
}).start();
}
+ /**
+ * Directly call IActivityManager.startService() using a spoofed packageName which is known to
+ * be allowlisted by Android framework to be able to start foreground service
+ * from the background. Framework will disallow the foreground service to start from the
+ * background and a ForegroundServiceStartNotAllowedException will be caught.
+ * @param context
+ * @param commandIntent
+ */
+ private void doStartForegroundServiceSpoofPackageName(Context context, Intent commandIntent) {
+ String targetPackage = getTargetPackage(commandIntent);
+ Intent fgsIntent = new Intent();
+ fgsIntent.putExtras(commandIntent);
+ fgsIntent.setComponent(new ComponentName(targetPackage, FG_SERVICE_NAME));
+ int command = LocalForegroundService.COMMAND_START_FOREGROUND;
+ fgsIntent.putExtras(LocalForegroundService.newCommand(command));
+ try {
+ final PackageManager pm = context.getPackageManager();
+ String spoofPackageName = pm.getAttentionServicePackageName();
+ if (TextUtils.isEmpty(spoofPackageName)) {
+ Log.d(TAG, "getAttentionServicePackageName() returns empty");
+ spoofPackageName = pm.getSystemCaptionsServicePackageName();
+ }
+ if (TextUtils.isEmpty(spoofPackageName)) {
+ Log.d(TAG, "getSystemCaptionsServicePackageName() returns empty");
+ spoofPackageName = "android";
+ }
+ Log.d(TAG, "spoofPackageName: " + spoofPackageName);
+ final IBinder activityProxy = android.os.ServiceManager.getService("activity");
+ // Call IActivityManager.startService() directly using a spoofed packageName.
+ IActivityManager.Stub.asInterface(activityProxy).startService(
+ context.getIApplicationThread(),
+ fgsIntent,
+ null,
+ true,
+ spoofPackageName,
+ null,
+ android.os.Process.myUserHandle().getIdentifier()
+ );
+ } catch (ForegroundServiceStartNotAllowedException e) {
+ Log.d(TAG, "startForegroundService gets an "
+ + " ForegroundServiceStartNotAllowedException", e);
+ } catch (LinkageError e) {
+ // IActivityManager.startService() is a hidden API, access hidden API could get
+ // LinkageError, consider the test as pass if we get LinkageError.
+ Log.d(TAG, "startForegroundService gets an LinkageError", e);
+ } catch (RemoteException e) {
+ Log.d(TAG, "startForegroundService gets an RemoteException", e);
+ }
+ }
+
private String getTargetPackage(Intent intent) {
return intent.getStringExtra(EXTRA_TARGET_PACKAGE);
}
diff --git a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
index 0f98cdf..ff40aff 100644
--- a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
@@ -60,6 +60,7 @@
import android.platform.test.annotations.AsbSecurityTest;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.server.wm.settings.SettingsSession;
import android.support.test.uiautomator.UiDevice;
import android.util.Log;
@@ -2015,6 +2016,52 @@
}
/**
+ * IActivityManager.startService() is called directly (does not go through
+ * {@link Context#startForegroundService(Intent)}, a spoofed packageName "com.google.android.as"
+ * is used as callingPackage. Although "com.google.android.as" is allowlisted to start
+ * foreground service from the background, but framework will detect this is a spoofed
+ * packageName and disallow foreground service start from the background.
+ * @throws Exception
+ */
+ @Test
+ public void testSpoofPackageName() throws Exception {
+ ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
+ PACKAGE_NAME_APP1, 0);
+ WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
+ WAITFOR_MSEC);
+ // CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME needs access
+ // to hidden API PackageManager.getAttentionServicePackageName() and
+ // PackageManager.getSystemCaptionsServicePackageName(), so we need to call
+ // hddenApiSettings.set("*") to exempt the hidden APIs.
+ SettingsSession<String> hiddenApiSettings = new SettingsSession<>(
+ Settings.Global.getUriFor(
+ Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS),
+ Settings.Global::getString, Settings.Global::putString);
+ hiddenApiSettings.set("*");
+ try {
+ // Enable the FGS background startForeground() restriction.
+ enableFgsRestriction(true, true, null);
+ // Start FGS in BG state.
+ WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
+ waiter.prepare(ACTION_START_FGS_RESULT);
+ CommandReceiver.sendCommand(mContext,
+ CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME,
+ PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+ // APP1 does not enter FGS state
+ try {
+ waiter.doWait(WAITFOR_MSEC);
+ fail("Service should not enter foreground service state");
+ } catch (Exception e) {
+ }
+ } finally {
+ uid1Watcher.finish();
+ if (hiddenApiSettings != null) {
+ hiddenApiSettings.close();
+ }
+ }
+ }
+
+ /**
* Turn on the FGS BG-launch restriction. DeviceConfig can turn on restriction on the whole
* device (across all apps). AppCompat can turn on restriction on a single app package.
* @param enable true to turn on restriction, false to turn off.
diff --git a/tests/app/src/android/app/cts/WallpaperManagerTest.java b/tests/app/src/android/app/cts/WallpaperManagerTest.java
index fc640a5..7fbd297 100644
--- a/tests/app/src/android/app/cts/WallpaperManagerTest.java
+++ b/tests/app/src/android/app/cts/WallpaperManagerTest.java
@@ -29,7 +29,6 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import android.Manifest;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.app.stubs.R;
@@ -52,8 +51,6 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.compatibility.common.util.CddTest;
-
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -71,9 +68,6 @@
private static final boolean DEBUG = false;
private static final String TAG = "WallpaperManagerTest";
- private static final long MAX_WAIT_TIME_SECS = 2;
- private static final long MAX_WAIT_TIME_MS = MAX_WAIT_TIME_SECS * 1000;
- private static final long WAIT_TIME_INCR_MS = 100;
private WallpaperManager mWallpaperManager;
private Context mContext;
@@ -81,7 +75,6 @@
private BroadcastReceiver mBroadcastReceiver;
private CountDownLatch mCountDownLatch;
private boolean mEnableWcg;
- private boolean mAcquiredWallpaperDimmingPermission = false;
@Before
public void setUp() throws Exception {
@@ -113,24 +106,6 @@
if (mBroadcastReceiver != null) {
mContext.unregisterReceiver(mBroadcastReceiver);
}
- if (mAcquiredWallpaperDimmingPermission) {
- try {
- mWallpaperManager.setWallpaperDimAmount(0f);
- assertDimAmountEqualsTo(0f);
- } finally {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .dropShellPermissionIdentity();
- mAcquiredWallpaperDimmingPermission = false;
- }
- }
- }
-
- private void ensureSetWallpaperDimAmountPermissionIsGranted() {
- if (!mAcquiredWallpaperDimmingPermission) {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .adoptShellPermissionIdentity(Manifest.permission.SET_WALLPAPER_DIM_AMOUNT);
- mAcquiredWallpaperDimmingPermission = true;
- }
}
@Test
@@ -428,96 +403,6 @@
}
}
- @Test
- public void testGetWallpaperDimAmountWithNoPermission_shouldThrowException() {
- Assert.assertThrows(SecurityException.class,
- () -> mWallpaperManager.getWallpaperDimAmount());
- }
-
- @Test
- public void testSetWallpaperDimAmountWithNoPermission_shouldThrowException() {
- Assert.assertThrows(SecurityException.class,
- () -> {
- float dimAmount = 0.5f;
- mWallpaperManager.setWallpaperDimAmount(dimAmount);
- assertDimAmountEqualsTo(dimAmount);
- });
- }
-
- @Test
- public void setWallpaperDimAmount_withinBound_shouldSetDimAmount() {
- ensureSetWallpaperDimAmountPermissionIsGranted();
-
- float dimAmount = 0.6f;
- mWallpaperManager.setWallpaperDimAmount(dimAmount);
- assertDimAmountEqualsTo(dimAmount);
-
- // Remove additional dimming and verify that the dim amount is set to 0 again
- mWallpaperManager.setWallpaperDimAmount(0f);
- assertDimAmountEqualsTo(0f);
- }
-
- @Test
- public void setWallpaperDimAmountBeyondRange_shouldBeBounded() {
- ensureSetWallpaperDimAmountPermissionIsGranted();
-
- // Setting dim amount < 0 should be bounded to lower limit 0.0
- mWallpaperManager.setWallpaperDimAmount(-1f);
- assertDimAmountEqualsTo(0f);
-
- // Setting dim amount > 1 should be bounded to upper limit 1.0
- mWallpaperManager.setWallpaperDimAmount(1.5f);
- assertDimAmountEqualsTo(1f);
- }
-
- @CddTest(requirement = "3.8.7.1/H-1-2")
- @Test
- public void setWallpaperDimAmount_changingWallpaperShouldRemainDimmed() throws IOException {
- ensureSetWallpaperDimAmountPermissionIsGranted();
-
- float dimAmount = 0.65f;
- mWallpaperManager.setWallpaperDimAmount(dimAmount);
- mWallpaperManager.setResource(R.drawable.robot);
-
- assertDimAmountEqualsTo(dimAmount);
- }
-
- @Test
- public void colorHintsOnDimTest() throws IOException {
- ensureSetWallpaperDimAmountPermissionIsGranted();
-
- Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(tmpWallpaper);
- canvas.drawColor(Color.WHITE);
-
- mWallpaperManager.setBitmap(tmpWallpaper);
-
- WallpaperColors colors = mWallpaperManager
- .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- int colorHints = colors.getColorHints();
- // Color hints support dark text on white wallpaper
- Assert.assertEquals(WallpaperColors.HINT_SUPPORTS_DARK_TEXT,
- colorHints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT);
-
- float lowDimAmount = 0.1f;
- mWallpaperManager.setWallpaperDimAmount(lowDimAmount);
- assertDimAmountEqualsTo(lowDimAmount);
- colors = mWallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- colorHints = colors.getColorHints();
- // Color hints still support dark text on white wallpaper that is not dimmed enough
- Assert.assertEquals(WallpaperColors.HINT_SUPPORTS_DARK_TEXT,
- colorHints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT);
-
- float higherDimAmount = 0.7f;
- mWallpaperManager.setWallpaperDimAmount(higherDimAmount);
- assertDimAmountEqualsTo(higherDimAmount);
- colors = mWallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- colorHints = colors.getColorHints();
- // Dimmed white wallpaper does not support dark text
- Assert.assertNotEquals(WallpaperColors.HINT_SUPPORTS_DARK_TEXT,
- colorHints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT);
- }
-
private void assertBitmapDimensions(Bitmap bitmap) {
int maxSize = getMaxTextureSize();
boolean safe = false;
@@ -686,20 +571,6 @@
return spy(new TestableColorListener());
}
- private void assertDimAmountEqualsTo(float dimAmount) {
- float storedDimAmount = -1f;
- for (int i = 0; i < MAX_WAIT_TIME_MS; i += WAIT_TIME_INCR_MS) {
- storedDimAmount = mWallpaperManager.getWallpaperDimAmount();
- if (dimAmount == storedDimAmount) break;
- try {
- Thread.sleep(WAIT_TIME_INCR_MS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Assert.assertEquals(dimAmount, storedDimAmount, /* delta */ 0f);
- }
-
public class TestableColorListener implements WallpaperManager.OnColorsChangedListener {
@Override
public void onColorsChanged(WallpaperColors colors, int which) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractWebViewTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractWebViewTestCase.java
index 7720bc8..d2bd91a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractWebViewTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AbstractWebViewTestCase.java
@@ -18,6 +18,10 @@
import android.autofillservice.cts.activities.AbstractWebViewActivity;
import android.autofillservice.cts.testcore.IdMode;
import android.autofillservice.cts.testcore.UiBot;
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.InstrumentationRegistry;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -45,4 +49,20 @@
public static void resetReplierMode() {
sReplier.setIdMode(IdMode.RESOURCE_ID);
}
+
+ /**
+ * @return whether the preventable IME feature as specified by {@code
+ * config_preventImeStartupUnlessTextEditor} is enabled.
+ */
+ protected static boolean isPreventImeStartup() {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ try {
+ return context.getResources().getBoolean(
+ Resources.getSystem().getIdentifier(
+ "config_preventImeStartupUnlessTextEditor", "bool", "android"));
+ } catch (Resources.NotFoundException e) {
+ // Assume this is not enabled.
+ return false;
+ }
+ }
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/FillEventHistoryCommonTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/FillEventHistoryCommonTestCase.java
index 416c79a..9ab86ce 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/FillEventHistoryCommonTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/FillEventHistoryCommonTestCase.java
@@ -574,12 +574,12 @@
enableService();
// Set expectations.
- final CannedFillResponse.Builder builder = createTestResponseBuilder();
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ true);
sReplier.addResponse(builder.build());
// Trigger autofill and set the save UI not show reason with
// NO_SAVE_UI_REASON_NO_SAVE_INFO.
- triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_NO_SAVE_INFO);
+ triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_NO_SAVE_INFO, /* withDataSet= */ true);
// Finish the context by login in and it will trigger to check if the save UI should be
// shown.
@@ -603,17 +603,8 @@
enableService();
// Set expectations.
- final CannedFillResponse.Builder builder = createTestResponseBuilder();
- builder.setSaveInfoFlags(SaveInfo.FLAG_DELAY_SAVE);
- sReplier.addResponse(builder.build());
-
- // Trigger autofill and set the save UI not show reason with
- // NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG.
- triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG);
-
- // Finish the context by login in and it will trigger to check if the save UI should be
- // shown.
- tapLogin();
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ true);
+ contextCommitted_whileDelaySave(builder, /* withDataSet= */ true);
// Verify that the save UI should not be shown and the history should include the reason.
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
@@ -624,6 +615,38 @@
assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG);
}
+ @Test
+ public void testContextCommitted_noSaveUi_whileDelaySave_noDataset() throws Exception {
+ enableService();
+
+ // Set expectations.
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ false);
+ contextCommitted_whileDelaySave(builder, /* withDataSet= */ false);
+
+ // Verify that the save UI should not be shown and the history should include the reason.
+ mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
+
+ final List<Event> verifyEvents = InstrumentedAutoFillService.getFillEvents(1);
+ final Event event = verifyEvents.get(0);
+
+ assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG);
+ }
+
+ // TODO: refine the helper function
+ private void contextCommitted_whileDelaySave(CannedFillResponse.Builder builder,
+ boolean withDataSet) throws Exception {
+ builder.setSaveInfoFlags(SaveInfo.FLAG_DELAY_SAVE);
+ sReplier.addResponse(builder.build());
+
+ // Trigger autofill and set the save UI not show reason with
+ // NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG.
+ triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG, withDataSet);
+
+ // Finish the context by login in and it will trigger to check if the save UI should be
+ // shown.
+ tapLogin();
+ }
+
/**
* Tests scenario where the context was committed, the save dialog was not shown because there
* was empty value for required ids.
@@ -633,17 +656,8 @@
enableService();
// Set expectations.
- final CannedFillResponse.Builder builder = createTestResponseBuilder();
- builder.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD);
- sReplier.addResponse(builder.build());
-
- // Trigger autofill and set the save UI not show reason with
- // NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED.
- triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED);
-
- // Finish the context by login in and it will trigger to check if the save UI should be
- // shown.
- tapLogin();
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ true);
+ contextCommitted_whileEmptyValueForRequiredIds(builder, /* withDataSet= */ true);
// Verify that the save UI should not be shown and the history should include the reason.
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
@@ -654,6 +668,38 @@
assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED);
}
+ @Test
+ public void testContextCommitted_noSaveUi_whileEmptyValueForRequiredIds_noDataset()
+ throws Exception {
+ enableService();
+
+ // Set expectations.
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ false);
+ contextCommitted_whileEmptyValueForRequiredIds(builder, /* withDataSet= */ false);
+
+ // Verify that the save UI should not be shown and the history should include the reason.
+ mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
+
+ final List<Event> verifyEvents = InstrumentedAutoFillService.getFillEvents(1);
+ final Event event = verifyEvents.get(0);
+
+ assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED);
+ }
+
+ private void contextCommitted_whileEmptyValueForRequiredIds(CannedFillResponse.Builder builder,
+ boolean withDataSet) throws Exception {
+ builder.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD);
+ sReplier.addResponse(builder.build());
+
+ // Trigger autofill and set the save UI not show reason with
+ // NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED.
+ triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED, withDataSet);
+
+ // Finish the context by login in and it will trigger to check if the save UI should be
+ // shown.
+ tapLogin();
+ }
+
/**
* Tests scenario where the context was committed, the save dialog was not shown because no
* value has been changed.
@@ -663,13 +709,16 @@
enableService();
// Set expectations.
- final CannedFillResponse.Builder builder = createTestResponseBuilder();
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ true);
builder.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD);
sReplier.addResponse(builder.build());
// Trigger autofill and set the save UI not show reason with
// NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED.
- triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_NO_VALUE_CHANGED);
+ // This test will compare the autofilled value and the ViewState value so the dataset
+ // is needed in this case.
+ triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_NO_VALUE_CHANGED,
+ /* withDataSet= */ true);
// Finish the context by login in and it will trigger to check if the save UI should be
// shown.
@@ -693,7 +742,33 @@
enableService();
// Set expectations.
- final CannedFillResponse.Builder builder = createTestResponseBuilder();
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ true);
+ contextCommitted_whileFieldsFailedValidation(builder, /* withDataSet= */ true);
+
+
+ final List<Event> verifyEvents = InstrumentedAutoFillService.getFillEvents(2);
+ final Event event = verifyEvents.get(1);
+
+ assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED);
+ }
+
+ @Test
+ public void testContextCommitted_noSaveUi_whileFieldsFailedValidation_noDataSet()
+ throws Exception {
+ enableService();
+
+ // Set expectations.
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ false);
+ contextCommitted_whileFieldsFailedValidation(builder, /* withDataSet= */ false);
+
+ final List<Event> verifyEvents = InstrumentedAutoFillService.getFillEvents(1);
+ final Event event = verifyEvents.get(0);
+
+ assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED);
+ }
+
+ private void contextCommitted_whileFieldsFailedValidation(CannedFillResponse.Builder builder,
+ boolean withDataSet) throws Exception {
builder.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
.setSaveInfoVisitor((contexts, saveInfoBuilder) -> {
final Validator validator =
@@ -704,7 +779,7 @@
// Trigger autofill and set the save UI not show reason with
// NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED.
- triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED);
+ triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED, withDataSet);
// Finish the context by login in and it will trigger to check if the save UI should be
// shown.
@@ -712,11 +787,6 @@
// Verify that the save UI should not be shown and the history should include the reason.
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
-
- final List<Event> verifyEvents = InstrumentedAutoFillService.getFillEvents(2);
- final Event event = verifyEvents.get(1);
-
- assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED);
}
/**
@@ -728,13 +798,13 @@
enableService();
// Set expectations.
- final CannedFillResponse.Builder builder = createTestResponseBuilder();
+ CannedFillResponse.Builder builder = createTestResponseBuilder(/* withDataSet= */ true);
builder.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD);
sReplier.addResponse(builder.build());
// Trigger autofill and set the save UI not show reason with
// NO_SAVE_UI_REASON_DATASET_MATCH.
- triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_DATASET_MATCH);
+ triggerAutofillForSaveUiCondition(NO_SAVE_UI_REASON_DATASET_MATCH, /* withDataSet= */ true);
// Finish the context by login in and it will trigger to check if the save UI should be
// shown.
@@ -749,28 +819,33 @@
assertThat(event.getNoSaveUiReason()).isEqualTo(NO_SAVE_UI_REASON_DATASET_MATCH);
}
- private CannedFillResponse.Builder createTestResponseBuilder() {
- return new CannedFillResponse.Builder()
- .addDataset(new CannedDataset.Builder()
- .setId("id1")
- .setField(ID_USERNAME, BACKDOOR_USERNAME)
- .setField(ID_PASSWORD, "whatever")
- .setPresentation("dataset1", isInlineMode())
- .build())
- .setFillResponseFlags(FillResponse.FLAG_TRACK_CONTEXT_COMMITED);
+ private CannedFillResponse.Builder createTestResponseBuilder(boolean withDataSet) {
+ CannedFillResponse.Builder builder = new CannedFillResponse.Builder();
+ if (withDataSet) {
+ builder.addDataset(new CannedDataset.Builder()
+ .setId("id1")
+ .setField(ID_USERNAME, BACKDOOR_USERNAME)
+ .setField(ID_PASSWORD, "whatever")
+ .setPresentation("dataset1", isInlineMode())
+ .build());
+ }
+ return builder.setFillResponseFlags(FillResponse.FLAG_TRACK_CONTEXT_COMMITED);
}
/**
* Triggers autofill on username first and set the behavior of the different conditions so that
* the save UI should not be shown.
*/
- private void triggerAutofillForSaveUiCondition(int reason) throws Exception {
+ private void triggerAutofillForSaveUiCondition(int reason, boolean withDataSet)
+ throws Exception {
// Trigger autofill on username and check the suggestion is shown.
mUiBot.focusByRelativeId(ID_USERNAME);
mUiBot.waitForIdle();
sReplier.getNextFillRequest();
- mUiBot.assertDatasets("dataset1");
+ if (withDataSet) {
+ mUiBot.assertDatasets("dataset1");
+ }
if (reason == NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED) {
// Set empty value on password to meet that there was empty value for required ids.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
index 1e3535e..94fe54d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
@@ -76,6 +76,7 @@
import android.widget.Spinner;
import android.widget.TimePicker;
+import org.junit.Ignore;
import org.junit.Test;
import java.util.Arrays;
@@ -573,6 +574,7 @@
}
@Test
+ @Ignore("b/232198065 Fix touch mode problem in ActivityTestRule")
public void autofillOneListValueToSpinner() throws Exception {
autofillListValue(AutofillValue.forList(1), 1, true);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java
index 9cf27f1..bbb30dc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/FillEventHistoryTest.java
@@ -109,8 +109,10 @@
sReplier.getNextSaveRequest();
// Assert it
- final List<Event> events = InstrumentedAutoFillService.getFillEvents(1);
- assertFillEventForSaveShown(events.get(0), NULL_DATASET_ID);
+ final List<Event> events = InstrumentedAutoFillService.getFillEvents(2);
+ FillEventHistory.Event event = events.get(0);
+ assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
+ assertFillEventForSaveShown(events.get(1), NULL_DATASET_ID);
}
@@ -159,10 +161,12 @@
// ...and check again
{
- final List<Event> events = InstrumentedAutoFillService.getFillEvents(3);
+ final List<Event> events = InstrumentedAutoFillService.getFillEvents(4);
assertFillEventForDatasetShown(events.get(0), UI_TYPE_MENU);
assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID, UI_TYPE_MENU);
assertFillEventForDatasetShown(events.get(2), UI_TYPE_MENU);
+ FillEventHistory.Event event = events.get(3);
+ assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java
index 698ba48..0be57ea 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/WebViewActivityTest.java
@@ -42,6 +42,7 @@
import android.view.KeyEvent;
import android.view.ViewStructure.HtmlInfo;
+import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;
@@ -107,6 +108,9 @@
}
private void autofillOneDatasetTest(boolean usesAppContext) throws Exception {
+ // TODO(b/226240255) WebView does not inform the autofill service about editText (re-)entry
+ Assume.assumeFalse(isPreventImeStartup());
+
// Set service.
enableService();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
index bbf4325..f0e7e83 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
@@ -22,14 +22,18 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ROLE_HOLDER_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SECURITY_TYPE;
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID;
import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
+import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_NFC;
import static android.app.admin.ProvisioningException.ERROR_PRE_CONDITION_FAILED;
import static android.content.Intent.EXTRA_USER;
import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
@@ -186,11 +190,15 @@
private static final String NFC_INTENT_PROVISIONING_SAMPLE = "NFC provisioning sample";
private static final Intent NFC_INTENT_NO_NDEF_RECORD = new Intent(ACTION_NDEF_DISCOVERED);
private static final HashMap<String, String> NFC_DATA_VALID = createNfcIntentData();
- private static final HashMap<String, String> NFC_DATA_EMPTY = new HashMap();
+ private static final HashMap<String, String> NFC_DATA_EMPTY = new HashMap<>();
private static final Map<String, String> NFC_DATA_WITH_COMPONENT_NAME =
Map.of(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, NFC_INTENT_COMPONENT_NAME);
+ private static final Bundle EXPECTED_BUNDLE_WITH_COMPONENT_NAME =
+ createExpectedBundleWithComponentName();
private static final Map<String, String> NFC_DATA_WITH_ADMIN_PACKAGE_NAME =
Map.of(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, NFC_INTENT_PACKAGE_NAME);
+ private static final Bundle EXPECTED_BUNDLE_WITH_PACKAGE_NAME =
+ createExpectedBundleWithPackageName();
private static final TestAppProvider sTestAppProvider = new TestAppProvider();
private static final TestApp sDpcApp = sTestAppProvider.query()
@@ -199,6 +207,11 @@
.get();
private static final PersistableBundle ADMIN_EXTRAS_BUNDLE = createAdminExtrasBundle();
+ private static final PersistableBundle ROLE_HOLDER_EXTRAS_BUNDLE =
+ createRoleHolderExtrasBundle();
+ private static final String ADMIN_EXTRAS_PROPERTIES = createAdminExtrasProperties();
+ private static final String ROLE_HOLDER_EXTRAS_PROPERTIES =
+ createRoleHolderExtrasProperties();
private static final String TEST_KEY = "test_key";
private static final String TEST_VALUE = "test_value";
private static final UserType MANAGED_PROFILE_USER_TYPE =
@@ -933,8 +946,9 @@
sDevicePolicyManager.createProvisioningIntentFromNfcIntent(nfcIntent);
assertThat(provisioningIntent).isNotNull();
- assertThat(provisioningBundleToMap(provisioningIntent.getExtras()))
- .containsAtLeastEntriesIn(NFC_DATA_VALID);
+ assertThat(provisioningIntent.getAction())
+ .isEqualTo(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE);
+ assertBundlesEqual(provisioningIntent.getExtras(), createExpectedValidBundle());
}
@Test
@@ -957,8 +971,9 @@
sDevicePolicyManager.createProvisioningIntentFromNfcIntent(nfcIntent);
assertThat(provisioningIntent).isNotNull();
- assertThat(provisioningBundleToMap(provisioningIntent.getExtras()))
- .containsAtLeastEntriesIn(NFC_DATA_WITH_COMPONENT_NAME);
+ assertThat(provisioningIntent.getAction())
+ .isEqualTo(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE);
+ assertBundlesEqual(provisioningIntent.getExtras(), EXPECTED_BUNDLE_WITH_COMPONENT_NAME);
}
@Test
@@ -970,8 +985,9 @@
sDevicePolicyManager.createProvisioningIntentFromNfcIntent(nfcIntent);
assertThat(provisioningIntent).isNotNull();
- assertThat(provisioningBundleToMap(provisioningIntent.getExtras()))
- .containsAtLeastEntriesIn(NFC_DATA_WITH_ADMIN_PACKAGE_NAME);
+ assertThat(provisioningIntent.getAction())
+ .isEqualTo(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE);
+ assertBundlesEqual(provisioningIntent.getExtras(), EXPECTED_BUNDLE_WITH_PACKAGE_NAME);
}
@Test
@@ -1036,7 +1052,7 @@
}
private static HashMap<String, String> createNfcIntentData() {
- HashMap<String, String> nfcIntentInput = new HashMap<String, String>();
+ HashMap<String, String> nfcIntentInput = new HashMap<>();
nfcIntentInput.putAll(
Map.of(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, NFC_INTENT_COMPONENT_NAME,
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, NFC_INTENT_PACKAGE_NAME,
@@ -1044,9 +1060,10 @@
EXTRA_PROVISIONING_TIME_ZONE, NFC_INTENT_TIMEZONE,
EXTRA_PROVISIONING_WIFI_SSID, NFC_INTENT_WIFI_SSID,
EXTRA_PROVISIONING_WIFI_SECURITY_TYPE, NFC_INTENT_WIFI_SECURITY_TYPE,
- EXTRA_PROVISIONING_WIFI_PASSWORD, NFC_INTENT_WIFI_PASSWORD)
+ EXTRA_PROVISIONING_WIFI_PASSWORD, NFC_INTENT_WIFI_PASSWORD,
+ EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, createAdminExtrasProperties(),
+ EXTRA_PROVISIONING_ROLE_HOLDER_EXTRAS_BUNDLE, createRoleHolderExtrasProperties())
);
-
return nfcIntentInput;
}
@@ -1075,22 +1092,6 @@
return nfcIntent;
}
- private Map<String, String> provisioningBundleToMap(Bundle bundle) {
- Map<String, String> map = new HashMap();
-
- for (String key : bundle.keySet()) {
- if(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME.equals(key)) {
- ComponentName componentName = bundle.getParcelable(key);
- map.put(key, componentName.getPackageName() + "/" + componentName.getClassName());
- }
- else {
- map.put(key, bundle.getString(key));
- }
- }
-
- return map;
- }
-
private NdefMessage createNdefMessage(Map<String, String> provisioningValues, String mime)
throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
@@ -1106,6 +1107,58 @@
return new NdefMessage(new NdefRecord[]{record});
}
+ private static PersistableBundle createAdminExtrasBundle() {
+ PersistableBundle result = new PersistableBundle();
+ result.putString("admin-extras-key", "admin extras value");
+ return result;
+ }
+
+ private static String createAdminExtrasProperties() {
+ return "admin-extras-key=admin extras value\n";
+ }
+
+ private static PersistableBundle createRoleHolderExtrasBundle() {
+ PersistableBundle result = new PersistableBundle();
+ result.putString("role-holder-extras-key", "role holder extras value");
+ return result;
+ }
+
+ private static String createRoleHolderExtrasProperties() {
+ return "role-holder-extras-key=role holder extras value\n";
+ }
+
+ private static Bundle createExpectedBundleWithComponentName() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ ComponentName.unflattenFromString(NFC_INTENT_COMPONENT_NAME));
+ bundle.putInt(EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_NFC);
+ return bundle;
+ }
+
+ private static Bundle createExpectedBundleWithPackageName() {
+ Bundle bundle = new Bundle();
+ bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, NFC_INTENT_PACKAGE_NAME);
+ bundle.putInt(EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_NFC);
+ return bundle;
+ }
+
+ private static Bundle createExpectedValidBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ ComponentName.unflattenFromString(NFC_INTENT_COMPONENT_NAME));
+ bundle.putString(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, NFC_INTENT_PACKAGE_NAME);
+ bundle.putString(EXTRA_PROVISIONING_LOCALE, NFC_INTENT_LOCALE);
+ bundle.putString(EXTRA_PROVISIONING_TIME_ZONE, NFC_INTENT_TIMEZONE);
+ bundle.putString(EXTRA_PROVISIONING_WIFI_SSID, NFC_INTENT_WIFI_SSID);
+ bundle.putString(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE, NFC_INTENT_WIFI_SECURITY_TYPE);
+ bundle.putString(EXTRA_PROVISIONING_WIFI_PASSWORD, NFC_INTENT_WIFI_PASSWORD);
+ bundle.putParcelable(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, ADMIN_EXTRAS_BUNDLE);
+ bundle.putParcelable(EXTRA_PROVISIONING_ROLE_HOLDER_EXTRAS_BUNDLE,
+ ROLE_HOLDER_EXTRAS_BUNDLE);
+ bundle.putInt(EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_NFC);
+ return bundle;
+ }
+
@Postsubmit(reason = "New test")
@Test
@EnsureDoesNotHavePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
@@ -1559,14 +1612,6 @@
sDevicePolicyManager.getDevicePolicyManagementRoleHolderPackage();
}
- private static PersistableBundle createAdminExtrasBundle() {
- PersistableBundle result = new PersistableBundle();
- result.putString("key1", "value1");
- result.putInt("key2", 2);
- result.putBoolean("key3", true);
- return result;
- }
-
private static void assertBundlesEqual(BaseBundle bundle1, BaseBundle bundle2) {
if (bundle1 != null) {
assertWithMessage("Intent bundles are not equal")
@@ -1574,9 +1619,19 @@
assertWithMessage("Intent bundles are not equal")
.that(bundle1.keySet().size()).isEqualTo(bundle2.keySet().size());
for (String key : bundle1.keySet()) {
- assertWithMessage("Intent bundles are not equal")
- .that(bundle1.get(key))
- .isEqualTo(bundle2.get(key));
+ if (bundle1.get(key) != null && bundle1.get(key) instanceof PersistableBundle) {
+ assertWithMessage("Intent bundles are not equal")
+ .that(bundle2.containsKey(key)).isTrue();
+ assertWithMessage("Intent bundles are not equal")
+ .that(bundle2.get(key)).isInstanceOf(PersistableBundle.class);
+ assertBundlesEqual(
+ (PersistableBundle) bundle1.get(key),
+ (PersistableBundle) bundle2.get(key));
+ } else {
+ assertWithMessage("Intent bundles are not equal")
+ .that(bundle1.get(key))
+ .isEqualTo(bundle2.get(key));
+ }
}
} else {
assertWithMessage("Intent bundles are not equal").that(bundle2).isNull();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
index 82195db..fcf71d0 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
@@ -40,6 +40,7 @@
import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
import com.android.bedstead.harrier.annotations.enterprise.PolicyAppliesTest;
+import com.android.bedstead.harrier.annotations.enterprise.PolicyDoesNotApplyTest;
import com.android.bedstead.harrier.policies.UserControlDisabledPackages;
import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
import com.android.bedstead.nene.TestApis;
@@ -175,9 +176,10 @@
DPC_COMPONENT_NAME);
String testAppPackageName = sTestApp.packageName();
- sDeviceState.dpc().devicePolicyManager().setUserControlDisabledPackages(DPC_COMPONENT_NAME,
- Arrays.asList(testAppPackageName));
try (TestAppInstance instance = sTestApp.install()) {
+ sDeviceState.dpc().devicePolicyManager().setUserControlDisabledPackages(
+ DPC_COMPONENT_NAME, Arrays.asList(testAppPackageName));
+
instance.activities().any().start();
sActivityManager.forceStopPackage(testAppPackageName);
@@ -194,6 +196,36 @@
}
}
+ @EnsureHasPermission(value = permission.FORCE_STOP_PACKAGES)
+ @PolicyDoesNotApplyTest(policy = UserControlDisabledPackages.class)
+ @Postsubmit(reason = "new test")
+ public void setUserControlDisabledPackages_launchActivity_verifyPackageStopped()
+ throws Exception {
+ List<String> originalDisabledPackages =
+ sDeviceState.dpc().devicePolicyManager().getUserControlDisabledPackages(
+ DPC_COMPONENT_NAME);
+ String testAppPackageName = sTestApp.packageName();
+
+ try (TestAppInstance instance = sTestApp.install()) {
+ sDeviceState.dpc().devicePolicyManager().setUserControlDisabledPackages(
+ DPC_COMPONENT_NAME, Arrays.asList(testAppPackageName));
+
+ instance.activities().any().start();
+
+ sActivityManager.forceStopPackage(testAppPackageName);
+
+ try {
+ assertPackageStopped(testAppPackageName);
+ } finally {
+ stopPackage(sTestApp.pkg());
+ }
+ } finally {
+ sDeviceState.dpc().devicePolicyManager().setUserControlDisabledPackages(
+ DPC_COMPONENT_NAME,
+ originalDisabledPackages);
+ }
+ }
+
private void stopPackage(Package pkg) throws Exception {
sDeviceState.dpc().devicePolicyManager().setUserControlDisabledPackages(DPC_COMPONENT_NAME,
Collections.emptyList());
@@ -201,9 +233,15 @@
pkg.forceStop();
}
+ private void assertPackageStopped(String packageName)
+ throws Exception {
+ assertWithMessage("Package %s not stopped", packageName)
+ .that(isPackageStopped(packageName)).isTrue();
+ }
+
private void assertPackageNotStopped(String packageName)
throws Exception {
- assertWithMessage("Package %s not stopped for", packageName)
+ assertWithMessage("Package %s stopped", packageName)
.that(isPackageStopped(packageName)).isFalse();
}
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index f714f77..b49a5cd 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -73,7 +73,7 @@
android:process=":SecondProcess"
android:exported="true"/>
- <provider android:name="android.server.wm.lifecycle.LifecycleLog"
+ <provider android:name="android.server.wm.lifecycle.EventLog"
android:authorities="android.server.wm.lifecycle.logprovider"
android:exported="true"/>
diff --git a/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml b/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
index 27f2870..70c0190 100644
--- a/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/jetpack/AndroidManifest.xml
@@ -45,7 +45,7 @@
/>
<!-- The provider properties must match the shared one defined in the util module. -->
- <provider android:name="android.server.wm.lifecycle.LifecycleLog"
+ <provider android:name="android.server.wm.lifecycle.EventLog"
android:authorities="android.server.wm.lifecycle.logprovider"
android:exported="true"/>
</application>
diff --git a/tests/framework/base/windowmanager/jetpack/SignedApp/src/android/server/wm/jetpack/signed/SignedEmbeddingActivity.java b/tests/framework/base/windowmanager/jetpack/SignedApp/src/android/server/wm/jetpack/signed/SignedEmbeddingActivity.java
index d2f6f2b..b332543 100644
--- a/tests/framework/base/windowmanager/jetpack/SignedApp/src/android/server/wm/jetpack/signed/SignedEmbeddingActivity.java
+++ b/tests/framework/base/windowmanager/jetpack/SignedApp/src/android/server/wm/jetpack/signed/SignedEmbeddingActivity.java
@@ -22,11 +22,13 @@
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityCrossUidInSplit;
import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
+import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.EXTRA_EMBED_ACTIVITY;
import static org.junit.Assume.assumeNotNull;
import android.app.Activity;
import android.content.ComponentName;
+import android.content.Intent;
import android.os.Bundle;
import android.server.wm.jetpack.utils.TestActivityKnownEmbeddingCerts;
import android.server.wm.jetpack.utils.TestValueCountConsumer;
@@ -52,6 +54,21 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (getIntent().getBooleanExtra(EXTRA_EMBED_ACTIVITY, false)) {
+ startActivityInSplit();
+ }
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ if (intent.getBooleanExtra(EXTRA_EMBED_ACTIVITY, false)) {
+ startActivityInSplit();
+ }
+ }
+
+ void startActivityInSplit() {
ActivityEmbeddingComponent embeddingComponent;
try {
assumeExtensionSupportedDevice();
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java
index 0092ed2..aa79a5d 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java
@@ -120,12 +120,14 @@
/**
* Tests that embedding an activity across UIDs is allowed if an activity requires a
- * permission that the host has.
+ * certificate that the host has.
*/
@Test
public void testCrossUidActivityEmbeddingIsAllowedWithPermission() {
// Start an activity that will attempt to embed TestActivityKnownEmbeddingCerts
- startActivityNewTask(SIGNED_EMBEDDING_ACTIVITY);
+ Bundle extras = new Bundle();
+ extras.putBoolean(EXTRA_EMBED_ACTIVITY, true);
+ startActivityNoWait(mContext, SIGNED_EMBEDDING_ACTIVITY, extras);
waitAndAssertResumed(EMBEDDED_ACTIVITY_ID);
TestActivityWithId embeddedActivity = getResumedActivityById(EMBEDDED_ACTIVITY_ID);
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 2ad5b78..98cfb2b 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
@@ -28,9 +28,9 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_RESUME;
import static android.server.wm.lifecycle.LifecycleConstants.ON_START;
import static android.server.wm.lifecycle.LifecycleConstants.ON_STOP;
-import static android.server.wm.lifecycle.LifecycleVerifier.assertOrder;
-import static android.server.wm.lifecycle.LifecycleVerifier.checkOrder;
-import static android.server.wm.lifecycle.LifecycleVerifier.transition;
+import static android.server.wm.lifecycle.TransitionVerifier.assertOrder;
+import static android.server.wm.lifecycle.TransitionVerifier.checkOrder;
+import static android.server.wm.lifecycle.TransitionVerifier.transition;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
@@ -44,9 +44,9 @@
import android.server.wm.jetpack.utils.TestActivityWithId2;
import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
import android.server.wm.jetpack.utils.TestValueCountConsumer;
-import android.server.wm.lifecycle.LifecycleLog;
-import android.server.wm.lifecycle.LifecycleLog.LifecycleLogClient;
-import android.server.wm.lifecycle.LifecycleTracker;
+import android.server.wm.lifecycle.EventLog;
+import android.server.wm.lifecycle.EventLog.EventLogClient;
+import android.server.wm.lifecycle.EventTracker;
import android.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -71,9 +71,9 @@
private static final String TEST_OWNER = "TEST_OWNER";
private static final String ON_SPLIT_STATES_UPDATED = "ON_SPLIT_STATES_UPDATED";
- private LifecycleLogClient mLifecycleLogClient;
- private LifecycleLog mLifecycleLog;
- private LifecycleTracker mLifecycleTracker;
+ private EventLogClient mEventLogClient;
+ private EventLog mEventLog;
+ private EventTracker mLifecycleTracker;
private LifecycleCallbacks mLifecycleCallbacks;
@Override
@@ -82,26 +82,26 @@
mSplitInfoConsumer = new SplitInfoLifecycleConsumer<>();
mActivityEmbeddingComponent.setSplitInfoCallback(mSplitInfoConsumer);
- mLifecycleLogClient = LifecycleLogClient.create(TEST_OWNER,
+ mEventLogClient = EventLogClient.create(TEST_OWNER,
mInstrumentation.getTargetContext());
// Log transitions for all activities that belong to this app.
- mLifecycleLog = new LifecycleLog();
- mLifecycleLog.clear();
+ mEventLog = new EventLog();
+ mEventLog.clear();
// Track transitions and allow waiting for pending activity states.
- mLifecycleTracker = new LifecycleTracker(mLifecycleLog);
+ mLifecycleTracker = new EventTracker(mEventLog);
mLifecycleCallbacks = new LifecycleCallbacks();
- ((Application) mInstrumentation.getContext().getApplicationContext())
- .registerActivityLifecycleCallbacks(mLifecycleCallbacks);
+ mApplication.registerActivityLifecycleCallbacks(mLifecycleCallbacks);
}
@Override
public void tearDown() {
super.tearDown();
- ((Application) mInstrumentation.getContext().getApplicationContext())
- .unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
- mLifecycleLogClient.close();
+ mApplication.unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
+ if (mEventLogClient != null) {
+ mEventLogClient.close();
+ }
}
/**
@@ -110,7 +110,6 @@
*/
@Test
public void testSecondaryActivityLaunch_replacing() {
- mLifecycleLog.clear();
Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
SplitPairRule splitPairRule = createWildcardSplitPairRuleWithPrimaryActivityClass(
@@ -124,9 +123,9 @@
transition(TestConfigChangeHandlingActivity.class, ON_CREATE),
transition(TestActivityWithId.class, ON_CREATE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Init split states");
- mLifecycleLog.clear();
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Init split states");
+ mEventLog.clear();
// Launch a replacing secondary activity
Activity secondaryActivity2 = startActivityAndVerifySplit(primaryActivity,
@@ -136,8 +135,8 @@
transition(TestActivityWithId.class, ON_DESTROY),
transition(TestActivityWithId2.class, ON_CREATE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected2));
- assertOrder(mLifecycleLog, expected2, "Replace secondary container activity");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected2));
+ assertOrder(mEventLog, expected2, "Replace secondary container activity");
waitAndAssertResumed(primaryActivity);
waitAndAssertResumed(secondaryActivity2);
}
@@ -148,7 +147,6 @@
*/
@Test
public void testSecondaryActivityLaunch_nonReplacing() {
- mLifecycleLog.clear();
Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
SplitPairRule splitPairRule = createWildcardSplitPairRuleWithPrimaryActivityClass(
@@ -163,9 +161,9 @@
transition(TestConfigChangeHandlingActivity.class, ON_CREATE),
transition(TestActivityWithId.class, ON_CREATE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Init split states");
- mLifecycleLog.clear();
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Init split states");
+ mEventLog.clear();
// Launch a secondary activity on top
Activity secondaryActivity2 = startActivityAndVerifySplit(primaryActivity,
@@ -175,8 +173,8 @@
transition(TestActivityWithId.class, ON_PAUSE),
transition(TestActivityWithId2.class, ON_CREATE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected2));
- assertOrder(mLifecycleLog, expected2, "Launch second secondary activity");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected2));
+ assertOrder(mEventLog, expected2, "Launch second secondary activity");
waitAndAssertResumed(primaryActivity);
waitAndAssertResumed(secondaryActivity2);
waitAndAssertNotVisible(secondaryActivity1);
@@ -187,7 +185,6 @@
*/
@Test
public void testSecondaryActivityLaunch_multiSplit() {
- mLifecycleLog.clear();
Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
SplitPairRule splitPairRule = createWildcardSplitPairRuleWithPrimaryActivityClass(
@@ -202,9 +199,9 @@
transition(TestConfigChangeHandlingActivity.class, ON_CREATE),
transition(TestActivityWithId.class, ON_CREATE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Init split states");
- mLifecycleLog.clear();
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Init split states");
+ mEventLog.clear();
// Launch another secondary activity to side
splitPairRule = createWildcardSplitPairRuleWithPrimaryActivityClass(
@@ -217,8 +214,8 @@
transition(TestConfigChangeHandlingActivity.class, ON_PAUSE),
transition(TestActivityWithId2.class, ON_CREATE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected2));
- assertOrder(mLifecycleLog, expected2, "Launch second secondary activity to side");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected2));
+ assertOrder(mEventLog, expected2, "Launch second secondary activity to side");
waitAndAssertNotVisible(primaryActivity);
waitAndAssertResumed(secondaryActivity);
waitAndAssertResumed(secondaryActivity2);
@@ -239,7 +236,7 @@
Activity secondaryActivity = startActivityAndVerifySplit(primaryActivity,
TestActivityWithId.class, splitPairRule,
"secondaryActivity1", mSplitInfoConsumer);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish secondary activity
secondaryActivity.finish();
@@ -247,8 +244,8 @@
transition(TestActivityWithId.class, ON_PAUSE),
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED),
transition(TestActivityWithId.class, ON_DESTROY));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish secondary activity");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish secondary activity");
waitAndAssertResumed(primaryActivity);
}
@@ -271,7 +268,7 @@
Activity secondaryActivity = startActivityAndVerifySplit(primaryActivity,
TestActivityWithId.class, splitPairRule,
"secondaryActivity1", mSplitInfoConsumer);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish secondary activity, should trigger finishing of the primary as well
secondaryActivity.finish();
@@ -279,8 +276,8 @@
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED),
transition(TestActivityWithId.class, ON_DESTROY),
transition(TestConfigChangeHandlingActivity.class, ON_DESTROY));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish secondary activity with dependents");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish secondary activity with dependents");
}
/**
@@ -302,15 +299,15 @@
Activity secondaryActivity = startActivityAndVerifySplit(primaryActivity,
TestActivityWithId.class, splitPairRule,
"secondaryActivity1", mSplitInfoConsumer);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish primary activity
primaryActivity.finish();
List<Pair<String, String>> expected = List.of(
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED),
transition(TestConfigChangeHandlingActivity.class, ON_DESTROY));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish primary activity only");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish primary activity only");
waitAndAssertResumed(secondaryActivity);
}
@@ -332,7 +329,7 @@
// Launch a secondary activity to side
startActivityAndVerifySplit(primaryActivity, TestActivityWithId.class, splitPairRule,
"secondaryActivity1", mSplitInfoConsumer);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish primary activity should trigger finishing of the secondary as well.
primaryActivity.finish();
@@ -340,8 +337,8 @@
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED),
transition(TestActivityWithId.class, ON_DESTROY),
transition(TestConfigChangeHandlingActivity.class, ON_DESTROY));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish primary activity with dependents");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish primary activity with dependents");
}
/**
@@ -370,7 +367,7 @@
"secondaryActivity2", mSplitInfoConsumer);
waitAndAssertResumed(secondaryActivity);
waitAndAssertResumed(secondaryActivity2);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish the last activity
secondaryActivity2.finish();
@@ -378,8 +375,8 @@
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED),
transition(TestActivityWithId2.class, ON_DESTROY),
transition(TestConfigChangeHandlingActivity.class, ON_RESUME));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish last activity in multi-split");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish last activity in multi-split");
}
/**
@@ -409,7 +406,7 @@
"secondaryActivity2", mSplitInfoConsumer);
waitAndAssertResumed(secondaryActivity);
waitAndAssertResumed(secondaryActivity2);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish the middle activity
secondaryActivity.finish();
@@ -419,8 +416,8 @@
transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED),
transition(TestActivityWithId.class, ON_DESTROY),
transition(TestConfigChangeHandlingActivity.class, ON_STOP));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish middle activity in multi-split");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish middle activity in multi-split");
}
/**
@@ -447,7 +444,7 @@
"secondaryActivity2", mSplitInfoConsumer);
waitAndAssertResumed(secondaryActivity);
waitAndAssertResumed(secondaryActivity2);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish the middle activity
secondaryActivity.finish();
@@ -458,8 +455,8 @@
transition(TestActivityWithId.class, ON_DESTROY),
transition(TestConfigChangeHandlingActivity.class, ON_STOP));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected, "Finish middle activity in multi-split");
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected, "Finish middle activity in multi-split");
}
/**
@@ -489,7 +486,7 @@
"secondaryActivity2", mSplitInfoConsumer);
waitAndAssertResumed(secondaryActivity);
waitAndAssertResumed(secondaryActivity2);
- mLifecycleLog.clear();
+ mEventLog.clear();
// Finish the middle activity
secondaryActivity.finish();
@@ -497,45 +494,45 @@
List<Pair<String, String>> expected = List.of(
transition(TestActivityWithId2.class, ON_DESTROY),
transition(TestActivityWithId.class, ON_DESTROY));
- mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mLifecycleLog, expected));
- assertOrder(mLifecycleLog, expected,
+ mLifecycleTracker.waitForConditionWithTimeout(() -> checkOrder(mEventLog, expected));
+ assertOrder(mEventLog, expected,
"Finish middle activity in multi-split with dependents");
mLifecycleTracker.waitForConditionWithTimeout(() ->
- mLifecycleLog.getLog().contains(transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED)));
+ mEventLog.getLog().contains(transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED)));
assertTrue("Split state change must be observed",
- mLifecycleLog.getLog().contains(transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED)));
+ mEventLog.getLog().contains(transition(TEST_OWNER, ON_SPLIT_STATES_UPDATED)));
}
private final class LifecycleCallbacks implements
Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
- mLifecycleLogClient.onActivityCallback(ON_CREATE, activity);
+ mEventLogClient.onCallback(ON_CREATE, activity);
}
@Override
public void onActivityStarted(Activity activity) {
- mLifecycleLogClient.onActivityCallback(ON_START, activity);
+ mEventLogClient.onCallback(ON_START, activity);
}
@Override
public void onActivityResumed(Activity activity) {
- mLifecycleLogClient.onActivityCallback(ON_RESUME, activity);
+ mEventLogClient.onCallback(ON_RESUME, activity);
}
@Override
public void onActivityPaused(Activity activity) {
- mLifecycleLogClient.onActivityCallback(ON_PAUSE, activity);
+ mEventLogClient.onCallback(ON_PAUSE, activity);
}
@Override
public void onActivityStopped(Activity activity) {
- mLifecycleLogClient.onActivityCallback(ON_STOP, activity);
+ mEventLogClient.onCallback(ON_STOP, activity);
}
@Override
public void onActivityDestroyed(Activity activity) {
- mLifecycleLogClient.onActivityCallback(ON_DESTROY, activity);
+ mEventLogClient.onCallback(ON_DESTROY, activity);
}
@Override
@@ -547,7 +544,7 @@
@Override
public void accept(T value) {
super.accept(value);
- mLifecycleLogClient.onActivityCallback(ON_SPLIT_STATES_UPDATED, TEST_OWNER);
+ mEventLogClient.onCallback(ON_SPLIT_STATES_UPDATED, TEST_OWNER);
}
}
}
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
new file mode 100644
index 0000000..a929e86
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPolicyTests.java
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+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;
+import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
+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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.server.wm.ActivityManagerTestBase;
+import android.server.wm.Condition;
+import android.server.wm.NestedShellPermission;
+import android.server.wm.WindowManagerState;
+import android.server.wm.jetpack.utils.TestActivityKnownEmbeddingCerts;
+import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.window.extensions.WindowExtensions;
+import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
+import androidx.window.extensions.embedding.SplitPairRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.function.BooleanSupplier;
+
+/**
+ * Tests for the {@link androidx.window.extensions} implementation provided on the device (and only
+ * if one is available) for the Activity Embedding functionality. Specifically tests security
+ * policies that should be applied by the system.
+ *
+ * Build/Install/Run:
+ * atest CtsWindowManagerJetpackTestCases:ActivityEmbeddingPolicyTests
+ */
+@RunWith(AndroidJUnit4.class)
+public class ActivityEmbeddingPolicyTests extends ActivityManagerTestBase {
+ protected ActivityEmbeddingComponent mActivityEmbeddingComponent;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ // TODO(b/207070762): remove the assumption after shell transition enabled.
+ assumeFalse(ENABLE_SHELL_TRANSITIONS);
+ assumeExtensionSupportedDevice();
+ WindowExtensions windowExtensions = getWindowExtensions();
+ assumeNotNull(windowExtensions);
+ mActivityEmbeddingComponent = windowExtensions.getActivityEmbeddingComponent();
+ assumeNotNull(mActivityEmbeddingComponent);
+ }
+
+ @After
+ public void tearDown() {
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ NestedShellPermission.run(() -> am.forceStopPackage("android.server.wm.jetpack.second"));
+ NestedShellPermission.run(() -> am.forceStopPackage("android.server.wm.jetpack.signed"));
+ }
+
+ /**
+ * Verifies that all input is dropped for activities that are embedded and being animated with
+ * untrusted embedding.
+ */
+ @Test
+ public void testInputDuringAnimationIsNotAllowed_untrustedEmbedding() {
+ Activity primaryActivity = startActivityNewTask(mContext, mInstrumentation,
+ TestConfigChangeHandlingActivity.class, null /* activityId */);
+
+ SplitPairRule splitPairRule = createWildcardSplitPairRule(true /* shouldClearTop */);
+ mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));
+
+ // Extend the animation scale, so that the test has enough time to catch the state during
+ // transition.
+ UiAutomation automation = mInstrumentation.getUiAutomation();
+ automation.setAnimationScale(2f);
+
+ try {
+ startActivityFromActivity(primaryActivity, SECOND_UNTRUSTED_EMBEDDING_ACTIVITY,
+ "initialSecondaryActivity", Bundle.EMPTY);
+
+ // Verify that the embedded activity drops input during animation
+ mWmState.waitForAppTransitionRunningOnDisplay(primaryActivity.getDisplayId());
+ waitForOrFailWithRapidRetry(
+ "Embedded activity must drop all input for the duration of animation",
+ () -> {
+ mWmState.computeState();
+ return mWmState.getActivity(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY)
+ .getLastDropInputMode() == 1 /* DropInputMode.ALL */;
+ });
+
+ // Verify that the embedded activity drops input if obscured after animation
+ mWmState.waitForAppTransitionIdleOnDisplay(primaryActivity.getDisplayId());
+ assertEquals(
+ "Embedded activity must drop input if obscured in untrusted embedding",
+ 2 /* DropInputMode.OBSCURED */,
+ mWmState.getActivity(
+ SECOND_UNTRUSTED_EMBEDDING_ACTIVITY).getLastDropInputMode());
+ } finally {
+ automation.setAnimationScale(1f);
+ }
+ }
+
+ /**
+ * Verifies that all input is dropped for activities that are embedded and being animated with
+ * trusted embedding.
+ */
+ @Test
+ public void testInputDuringAnimationIsNotAllowed_trustedEmbedding() {
+ // Extend the animation scale, so that the test has enough time to catch the state during
+ // transition.
+ UiAutomation automation = mInstrumentation.getUiAutomation();
+ automation.setAnimationScale(2f);
+
+ try {
+ // Start an activity that will attempt to embed TestActivityKnownEmbeddingCerts
+ startActivityOnDisplaySingleTop(mContext, DEFAULT_DISPLAY, SIGNED_EMBEDDING_ACTIVITY,
+ Bundle.EMPTY);
+ mWmState.waitForActivityState(SIGNED_EMBEDDING_ACTIVITY,
+ WindowManagerState.STATE_RESUMED);
+ mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
+
+ Bundle embedExtra = new Bundle();
+ embedExtra.putBoolean(EXTRA_EMBED_ACTIVITY, true);
+ startActivityOnDisplaySingleTop(mContext, DEFAULT_DISPLAY, SIGNED_EMBEDDING_ACTIVITY,
+ embedExtra);
+
+ // Verify that the embedded activity drops input during animation
+ final ComponentName embeddedActivityComponent = new ComponentName(mContext,
+ TestActivityKnownEmbeddingCerts.class);
+ mWmState.waitForAppTransitionRunningOnDisplay(DEFAULT_DISPLAY);
+ waitForOrFailWithRapidRetry(
+ "Embedded activity must drop all input for the duration of animation",
+ () -> {
+ mWmState.computeState();
+ return mWmState.getActivity(embeddedActivityComponent)
+ .getLastDropInputMode() == 1 /* DropInputMode.ALL */;
+ });
+
+ // Verify that the embedded activity drops input if obscured after animation
+ mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
+ assertEquals(
+ "Embedded activity must not drop input if obscured in trusted embedding",
+ 0 /* DropInputMode.NONE */,
+ mWmState.getActivity(embeddedActivityComponent).getLastDropInputMode());
+ } finally {
+ automation.setAnimationScale(1f);
+ }
+ }
+
+ static void waitForOrFailWithRapidRetry(@NonNull String message,
+ @NonNull BooleanSupplier condition) {
+ Condition.waitFor(new Condition<>(message, condition)
+ .setRetryIntervalMs(50)
+ .setRetryLimit(100)
+ .setOnFailure(unusedResult -> fail("FAILED because unsatisfied: " + message)));
+ }
+}
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 4e5cdc0..fb9f5e8 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
@@ -17,6 +17,7 @@
package android.server.wm.jetpack.utils;
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.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -31,6 +32,7 @@
import static org.junit.Assert.assertTrue;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.app.Application;
import android.app.Instrumentation;
import android.content.ComponentName;
@@ -56,6 +58,7 @@
public class WindowManagerJetpackTestBase {
public static final String ACTIVITY_ID_LABEL = "ActivityID";
+ public static final String EXTRA_EMBED_ACTIVITY = "EmbedActivity";
public Instrumentation mInstrumentation;
public Context mContext;
@@ -88,23 +91,46 @@
public Activity startActivityNewTask(@NonNull Class activityClass,
@Nullable String activityId) {
- final Intent intent = new Intent(mContext, activityClass);
+ return startActivityNewTask(mContext, mInstrumentation, activityClass, activityId);
+ }
+
+ public static Activity startActivityNewTask(@NonNull Context context,
+ @NonNull Instrumentation instrumentation, @NonNull Class 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);
}
- final Activity activity = mInstrumentation.startActivitySync(intent);
- return activity;
+ return instrumentation.startActivitySync(intent);
}
/**
* Start an activity using a component name. Can be used for activities from a different UIDs.
*/
- public void startActivityNewTask(@NonNull ComponentName activityComponent) {
- final Intent intent = new Intent();
- intent.setClassName(activityComponent.getPackageName(), activityComponent.getClassName());
- intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ public static void startActivityNoWait(@NonNull Context context,
+ @NonNull ComponentName activityComponent, @NonNull Bundle extras) {
+ final Intent intent = new Intent()
+ .setClassName(activityComponent.getPackageName(), activityComponent.getClassName())
+ .addFlags(FLAG_ACTIVITY_NEW_TASK)
+ .putExtras(extras);
+ context.startActivity(intent);
+ }
+
+ /**
+ * Start an activity using a component name on the specified display with
+ * {@link FLAG_ACTIVITY_SINGLE_TOP}. Can be used for activities from a different UIDs.
+ */
+ public static void startActivityOnDisplaySingleTop(@NonNull Context context,
+ int displayId, @NonNull ComponentName activityComponent, @NonNull Bundle extras) {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(displayId);
+
+ Intent intent = new Intent()
+ .addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP)
+ .setComponent(activityComponent)
+ .putExtras(extras);
+ context.startActivity(intent, options.toBundle());
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index 5e7ea21..92d738c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -21,7 +21,6 @@
import static android.server.wm.app.Components.KeepClearRectsActivity.EXTRA_KEEP_CLEAR_RECTS;
import static android.view.Display.DEFAULT_DISPLAY;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -55,11 +54,12 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Callable;
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
public class KeepClearRectsTests extends WindowManagerTestBase {
- private static final long FOCUS_VIEW_CHECK_TIMEOUT = 3000;
+ private static final long SAME_ELEMENT_ASSERTION_TIMEOUT = 3000;
private static final List<Rect> TEST_KEEP_CLEAR_RECTS =
Arrays.asList(new Rect(0, 0, 25, 25),
new Rect(30, 0, 50, 25),
@@ -82,7 +82,7 @@
}
@Test
- public void testSetPreferKeepClearAttr() {
+ public void testSetPreferKeepClearAttr() throws Exception {
final Intent intent = new Intent(mContext, TestActivity.class);
intent.putExtra(USE_KEEP_CLEAR_ATTR_LAYOUT, true);
mTestSession.launchTestActivityOnDisplaySync(null, intent, DEFAULT_DISPLAY);
@@ -90,11 +90,12 @@
// To be kept in sync with res/layout/keep_clear_attr_activity
final Rect keepClearRect = new Rect(0, 0, 25, 25);
- assertSameElements(Arrays.asList(keepClearRect), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(keepClearRect),
+ () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testSetPreferKeepClearSingleView() {
+ public void testSetPreferKeepClearSingleView() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -102,11 +103,12 @@
final View v = createTestViewInActivity(activity, keepClearRect);
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
- assertSameElements(Arrays.asList(keepClearRect), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(keepClearRect),
+ () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testSetPreferKeepClearTwoViews() {
+ public void testSetPreferKeepClearTwoViews() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -115,29 +117,30 @@
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
final List<Rect> expected = new ArrayList(Arrays.asList(keepClearRect));
- assertSameElements(expected, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(expected, () -> getKeepClearRectsForActivity(activity));
final Rect keepClearRect2 = new Rect(25, 25, 50, 50);
final View v2 = createTestViewInActivity(activity, keepClearRect2);
mTestSession.runOnMainSyncAndWait(() -> v2.setPreferKeepClear(true));
expected.addAll(Arrays.asList(keepClearRect2));
- assertSameElements(expected, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(expected, () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testSetMultipleKeepClearRectsSingleView() {
+ public void testSetMultipleKeepClearRectsSingleView() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final View v = createTestViewInActivity(activity);
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testSetMultipleKeepClearRectsTwoViews() {
+ public void testSetMultipleKeepClearRectsTwoViews() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -150,7 +153,7 @@
final List<Rect> expected = new ArrayList(TEST_KEEP_CLEAR_RECTS);
expected.addAll(TEST_KEEP_CLEAR_RECTS_2);
- assertSameElements(expected, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(expected, () -> getKeepClearRectsForActivity(activity));
}
@Test
@@ -169,25 +172,25 @@
}
@Test
- public void testGetPreferKeepClearRectsSingleView() {
+ public void testGetPreferKeepClearRectsSingleView() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final Rect viewBounds = new Rect(0, 0, 60, 60);
final View v = createTestViewInActivity(activity, viewBounds);
- assertSameElements(EMPTY_LIST, v.getPreferKeepClearRects());
+ assertSameElementsEventually(EMPTY_LIST, () -> v.getPreferKeepClearRects());
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, v.getPreferKeepClearRects());
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS, () -> v.getPreferKeepClearRects());
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS_2));
- assertSameElements(TEST_KEEP_CLEAR_RECTS_2, v.getPreferKeepClearRects());
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS_2, () -> v.getPreferKeepClearRects());
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClearRects(EMPTY_LIST));
- assertSameElements(EMPTY_LIST, v.getPreferKeepClearRects());
+ assertSameElementsEventually(EMPTY_LIST, () -> v.getPreferKeepClearRects());
}
@Test
- public void testGettersPreferKeepClearRectsTwoViews() {
+ public void testGettersPreferKeepClearRectsTwoViews() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -201,66 +204,72 @@
});
assertTrue(v1.isPreferKeepClear());
- assertSameElements(TEST_KEEP_CLEAR_RECTS, v2.getPreferKeepClearRects());
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS, () -> v2.getPreferKeepClearRects());
mTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(false));
assertFalse(v1.isPreferKeepClear());
- assertSameElements(TEST_KEEP_CLEAR_RECTS, v2.getPreferKeepClearRects());
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS, () -> v2.getPreferKeepClearRects());
mTestSession.runOnMainSyncAndWait(() -> {
v1.setPreferKeepClear(true);
v2.setPreferKeepClearRects(EMPTY_LIST);
});
assertTrue(v1.isPreferKeepClear());
- assertSameElements(EMPTY_LIST, v2.getPreferKeepClearRects());
+ assertSameElementsEventually(EMPTY_LIST, () -> v2.getPreferKeepClearRects());
}
@Test
- public void testSetPreferKeepClearCombinesWithMultipleRects() {
+ public void testSetPreferKeepClearCombinesWithMultipleRects() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final Rect viewBounds = new Rect(0, 0, 60, 60);
final View v = createTestViewInActivity(activity, viewBounds);
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
final List<Rect> combinedRects = new ArrayList<>(TEST_KEEP_CLEAR_RECTS);
combinedRects.add(viewBounds);
- assertSameElements(combinedRects, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(combinedRects, () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(false));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testIgnoreKeepClearRectsFromGoneViews() {
+ public void testIgnoreKeepClearRectsFromGoneViews() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final Rect viewBounds = new Rect(0, 0, 60, 60);
final View v = createTestViewInActivity(activity, viewBounds);
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
- assertSameElements(Arrays.asList(viewBounds), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setVisibility(View.GONE));
- assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST, () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setVisibility(View.VISIBLE));
- assertSameElements(Arrays.asList(viewBounds), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> {
v.setPreferKeepClear(false);
v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
});
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setVisibility(View.GONE));
- assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST, () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setVisibility(View.VISIBLE));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
final Rect viewBounds2 = new Rect(60, 60, 90, 90);
final View v2 = createTestViewInActivity(activity, viewBounds2);
@@ -268,36 +277,39 @@
final List<Rect> expected = new ArrayList(TEST_KEEP_CLEAR_RECTS);
expected.add(viewBounds2);
- assertSameElements(expected, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(expected, () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setVisibility(View.GONE));
- assertSameElements(Arrays.asList(viewBounds2), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(viewBounds2),
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> {
v.setVisibility(View.VISIBLE);
v2.setVisibility(View.GONE);
});
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> {
v.setVisibility(View.VISIBLE);
v2.setVisibility(View.VISIBLE);
});
- assertSameElements(expected, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(expected, () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testIgnoreKeepClearRectsFromDetachedViews() {
+ public void testIgnoreKeepClearRectsFromDetachedViews() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final Rect viewBounds = new Rect(0, 0, 60, 60);
final View v = createTestViewInActivity(activity, viewBounds);
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
- assertSameElements(Arrays.asList(viewBounds), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> ((ViewGroup) v.getParent()).removeView(v));
- assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST, () -> getKeepClearRectsForActivity(activity));
}
@Test
@@ -312,26 +324,22 @@
final Rect viewBounds = new Rect(0, 0, 60, 60);
final View v = createTestViewInActivity(activity, viewBounds);
- assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST, () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> {
v.setFocusable(true);
v.requestFocus();
});
- PollingCheck.check("Expected focused view bounds as keep clear area",
- preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
- () -> hasSameElements(Arrays.asList(viewBounds),
- getKeepClearRectsForActivity(activity)));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setFocusable(false));
- PollingCheck.check("Expected no keep clear areas after clearing focus, but found some",
- preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
- () -> hasSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity)));
+ assertSameElementsEventually(EMPTY_LIST, () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testKeepClearRectsGetTranslatedToWindowSpace() {
+ public void testKeepClearRectsGetTranslatedToWindowSpace() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -345,28 +353,31 @@
expected.add(newRect);
}
- assertSameElements(expected, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(expected, () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testSetKeepClearRectsOnDisplaySingleWindow() {
+ public void testSetKeepClearRectsOnDisplaySingleWindow() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final Rect keepClearRect = new Rect(0, 0, 25, 25);
final View v = createTestViewInActivity(activity, keepClearRect);
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
- assertSameElements(Arrays.asList(keepClearRect), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(keepClearRect),
+ () -> getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> {
v.setPreferKeepClear(false);
v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
});
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
final List<Rect> expectedRectsInScreenSpace =
getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName());
- assertSameElements(expectedRectsInScreenSpace, getKeepClearRectsOnDefaultDisplay());
+ assertSameElementsEventually(expectedRectsInScreenSpace,
+ () -> getKeepClearRectsOnDefaultDisplay());
activity.finishAndRemoveTask();
assertTrue(Collections.disjoint(
@@ -375,14 +386,15 @@
}
@Test
- public void testKeepClearRectsOnDisplayTwoWindows() {
+ public void testKeepClearRectsOnDisplayTwoWindows() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity, viewBounds);
mTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
- assertSameElements(Arrays.asList(viewBounds), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity));
final String title = "KeepClearRectsTestWindow";
mTestSession.runOnMainSyncAndWait(() -> {
@@ -398,18 +410,20 @@
});
mWmState.waitAndAssertWindowSurfaceShown(title, true);
- assertSameElements(Arrays.asList(viewBounds), getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity));
}
@Test
- public void testKeepClearRectsOnDisplayTwoFullscreenActivities() {
+ public void testKeepClearRectsOnDisplayTwoFullscreenActivities() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity1 = mTestSession.getActivity();
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity1, viewBounds);
mTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
- assertSameElements(Arrays.asList(viewBounds), getKeepClearRectsForActivity(activity1));
+ assertSameElementsEventually(Arrays.asList(viewBounds),
+ () -> getKeepClearRectsForActivity(activity1));
final TestActivitySession<TranslucentTestActivity> translucentTestSession =
createManagedTestActivitySession();
@@ -419,18 +433,19 @@
final View v2 = createTestViewInActivity(activity2);
mTestSession.runOnMainSyncAndWait(() -> v2.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity2));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity2));
mWmState.assertVisibility(activity1.getComponentName(), true);
mWmState.assertVisibility(activity2.getComponentName(), true);
// Since both activities are fullscreen, WM only takes the keep clear areas from the top one
- assertSameElements(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
- activity2.getComponentName()), getKeepClearRectsOnDefaultDisplay());
+ assertSameElementsEventually(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
+ activity2.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
- public void testDisplayHasKeepClearRectsOnlyFromVisibleWindows() {
+ public void testDisplayHasKeepClearRectsOnlyFromVisibleWindows() throws Exception {
final TestActivitySession<TranslucentTestActivity> translucentTestSession =
createManagedTestActivitySession();
translucentTestSession.launchTestActivityOnDisplaySync(
@@ -440,24 +455,25 @@
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity1, viewBounds);
translucentTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
- assertSameElements(getRectsInScreenSpace(Arrays.asList(viewBounds),
- activity1.getComponentName()),
- getKeepClearRectsOnDefaultDisplay());
+ assertSameElementsEventually(getRectsInScreenSpace(Arrays.asList(viewBounds),
+ activity1.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity2 = mTestSession.getActivity();
final View v2 = createTestViewInActivity(activity2);
mTestSession.runOnMainSyncAndWait(() -> v2.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity2));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity2));
mWmState.waitAndAssertVisibilityGone(activity1.getComponentName());
mWmState.assertVisibility(activity2.getComponentName(), true);
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity2));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity2));
}
@Test
- public void testDisplayHasKeepClearAreasFromTwoActivitiesInSplitscreen() {
+ public void testDisplayHasKeepClearAreasFromTwoActivitiesInSplitscreen() throws Exception {
assumeTrue("Skipping test: no split multi-window support",
supportsSplitScreenMultiWindow());
@@ -486,19 +502,19 @@
mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY, true);
mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY2, true);
- assertSameElements(TEST_KEEP_CLEAR_RECTS,
- getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY));
- assertSameElements(TEST_KEEP_CLEAR_RECTS_2,
- getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY2));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS_2,
+ () -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY2));
final List<Rect> expected = new ArrayList();
expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, KEEP_CLEAR_RECTS_ACTIVITY));
expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS_2, KEEP_CLEAR_RECTS_ACTIVITY2));
- assertSameElements(expected, getKeepClearRectsOnDefaultDisplay());
+ assertSameElementsEventually(expected, () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
- public void testUnrestrictedKeepClearRects() {
+ public void testUnrestrictedKeepClearRects() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -507,15 +523,18 @@
v.setUnrestrictedPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
});
- assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
- assertSameElements(EMPTY_LIST, getUnrestrictedKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST, () -> getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST,
+ () -> getUnrestrictedKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> {
v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
});
- assertSameElements(TEST_KEEP_CLEAR_RECTS, getKeepClearRectsForActivity(activity));
- assertSameElements(EMPTY_LIST, getUnrestrictedKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
+ () -> getKeepClearRectsForActivity(activity));
+ assertSameElementsEventually(EMPTY_LIST,
+ () -> getUnrestrictedKeepClearRectsForActivity(activity));
}
private View createTestViewInActivity(TestActivity activity) {
@@ -588,10 +607,11 @@
return result;
}
- private static <T> void assertSameElements(List<T> expected, List<T> actual) {
- if (!hasSameElements(expected, actual)) {
- assertEquals(expected, actual);
- }
+ private static <T> void assertSameElementsEventually(List<T> expected, Callable<List<T>> actual)
+ throws Exception {
+ PollingCheck.check("Lists do not have the same elements.",
+ SAME_ELEMENT_ASSERTION_TIMEOUT,
+ () -> hasSameElements(expected, actual.call()));
}
private static <T> boolean hasSameElements(List<T> fst, List<T> snd) {
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 ace9d8f..4b7242e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
@@ -23,6 +23,7 @@
import static android.server.wm.SplitActivityLifecycleTest.ActivityB.EXTRA_SHOW_WHEN_LOCKED;
import static android.server.wm.WindowManagerState.STATE_STARTED;
import static android.server.wm.WindowManagerState.STATE_STOPPED;
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -497,8 +498,11 @@
*/
@Test
public void testTranslucentAdjacentTaskFragment() {
- // Create ActivityB on top of ActivityA
- Activity activityB = startActivityInWindowingModeFullScreen(ActivityB.class);
+ // Create ActivityB on top of ActivityA.
+ // Make sure ActivityB is launched into the same task as ActivityA so that we can reparent
+ // it to TaskFragment in the same task later.
+ Activity activityB = startActivity(ActivityB.class, DEFAULT_DISPLAY, true /* hasFocus */,
+ WINDOWING_MODE_FULLSCREEN, mOwnerActivity.getTaskId());
waitAndAssertResumedActivity(mActivityB, "Activity B must be resumed.");
waitAndAssertActivityState(mActivityA, STATE_STOPPED,
"Activity A is occluded by Activity B, so it must be stopped.");
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
index 024ea17..283a1f0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
@@ -61,8 +61,6 @@
import androidx.annotation.NonNull;
-import com.android.compatibility.common.util.SystemUtil;
-
import org.junit.Test;
import java.util.ArrayList;
@@ -81,9 +79,7 @@
private static void sendKey(int action, int keyCode, int displayId) {
final KeyEvent keyEvent = new KeyEvent(action, keyCode);
keyEvent.setDisplayId(displayId);
- SystemUtil.runWithShellPermissionIdentity(() -> {
- getInstrumentation().sendKeySync(keyEvent);
- });
+ getInstrumentation().sendKeySync(keyEvent);
}
private static void sendAndAssertTargetConsumedKey(InputTargetActivity target, int keyCode,
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 322355f..2e29a74 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -73,12 +73,11 @@
import java.util.ArrayList;
import java.util.Random;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeoutException;
/**
* Ensure moving windows and tapping is done synchronously.
@@ -728,9 +727,10 @@
eventHover.setSource(InputDevice.SOURCE_MOUSE);
try {
mInstrumentation.sendPointerSync(eventHover);
- fail("Not allowed to inject event to the window from another process.");
- } catch (SecurityException e) {
- // Should not be allowed to inject event to the window from another process.
+ fail("Not allowed to inject to windows owned by another uid from Instrumentation.");
+ } catch (RuntimeException e) {
+ // Should not be allowed to inject event to a window owned by another uid from the
+ // Instrumentation class.
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationSynchronicityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationSynchronicityTests.java
index 20bce66..229104c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationSynchronicityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationSynchronicityTests.java
@@ -64,6 +64,7 @@
import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.WindowUtil;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -83,11 +84,13 @@
private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ @Ignore("b/168446060")
@Test
public void testShowAndHide_renderSynchronouslyBetweenImeWindowAndAppContent() throws Throwable {
runTest(false /* useControlApi */);
}
+ @Ignore("b/168446060")
@Test
public void testControl_rendersSynchronouslyBetweenImeWindowAndAppContent() throws Throwable {
runTest(true /* useControlApi */);
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 aa19b08..65465b2 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -62,6 +62,7 @@
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
+import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -77,7 +78,6 @@
import androidx.annotation.Nullable;
import com.android.compatibility.common.util.PollingCheck;
-import com.android.compatibility.common.util.SystemUtil;
import com.android.cts.mockime.ImeEventStream;
import com.android.cts.mockime.ImeSettings;
import com.android.cts.mockime.MockImeSession;
@@ -844,8 +844,10 @@
}
private void sendPointerSync(MotionEvent event) {
- SystemUtil.runWithShellPermissionIdentity(
- () -> getInstrumentation().sendPointerSync(event));
+ event.setSource(event.getSource() | InputDevice.SOURCE_CLASS_POINTER);
+ // Use UiAutomation to inject into TestActivity because it is started and owned by the
+ // Shell, which has a different uid than this instrumentation.
+ getInstrumentation().getUiAutomation().injectInputEvent(event, true);
}
private static class AnimationCallback extends WindowInsetsAnimation.Callback {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowManagerTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowManagerTestBase.java
index df3f9e3..7977030 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowManagerTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowManagerTestBase.java
@@ -16,6 +16,7 @@
package android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
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;
@@ -64,13 +65,20 @@
static <T extends FocusableActivity> T startActivity(Class<T> cls, int displayId,
boolean hasFocus, int windowingMode) {
+ return startActivity(cls, displayId, hasFocus, windowingMode, INVALID_STACK_ID);
+ }
+
+ static <T extends FocusableActivity> T startActivity(Class<T> cls, int displayId,
+ boolean hasFocus, int windowingMode, int taskId) {
final Bundle options;
- if (displayId == DEFAULT_DISPLAY && windowingMode == WINDOWING_MODE_UNDEFINED) {
+ if (displayId == DEFAULT_DISPLAY && windowingMode == WINDOWING_MODE_UNDEFINED
+ && taskId == INVALID_STACK_ID) {
options = null;
} else {
final ActivityOptions ap= ActivityOptions.makeBasic();
if (displayId != DEFAULT_DISPLAY) ap.setLaunchDisplayId(displayId);
if (windowingMode != WINDOWING_MODE_UNDEFINED) ap.setLaunchWindowingMode(windowingMode);
+ if (taskId != INVALID_STACK_ID) ap.setLaunchTaskId(taskId);
options = ap.toBundle();
}
final T[] activity = (T[]) Array.newInstance(FocusableActivity.class, 1);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
index df015a6..b6eea5a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
@@ -71,10 +71,10 @@
final ActivityTestRule mSlowActivityTestRule = new ActivityTestRule<>(
SlowActivity.class, true /* initialTouchMode */, false /* launchActivity */);
- private static LifecycleLog mLifecycleLog;
+ private static EventLog sEventLog;
protected Context mTargetContext;
- private LifecycleTracker mLifecycleTracker;
+ private EventTracker mTransitionTracker;
@Before
@Override
@@ -83,11 +83,11 @@
mTargetContext = getInstrumentation().getTargetContext();
// Log transitions for all activities that belong to this app.
- mLifecycleLog = new LifecycleLog();
- mLifecycleLog.clear();
+ sEventLog = new EventLog();
+ sEventLog.clear();
// Track transitions and allow waiting for pending activity states.
- mLifecycleTracker = new LifecycleTracker(mLifecycleLog);
+ mTransitionTracker = new EventTracker(sEventLog);
// Some lifecycle tracking activities that have not been destroyed may affect the
// verification of next test because of the lifecycle log. We need to wait them to be
@@ -252,7 +252,7 @@
final void waitAndAssertActivityStates(
Pair<Class<? extends Activity>, String>... activityCallbacks) {
log("Start waitAndAssertActivityCallbacks");
- mLifecycleTracker.waitAndAssertActivityStates(activityCallbacks);
+ mTransitionTracker.waitAndAssertActivityStates(activityCallbacks);
}
/**
@@ -262,35 +262,35 @@
final void waitAndAssertActivityCurrentState(
Class<? extends Activity> activityClass, String expectedState) {
log("Start waitAndAssertActivityCurrentState");
- mLifecycleTracker.waitAndAssertActivityCurrentState(activityClass, expectedState);
+ mTransitionTracker.waitAndAssertActivityCurrentState(activityClass, expectedState);
}
/**
* Blocking call that will wait for activities to perform the expected sequence of transitions.
- * @see LifecycleTracker#waitForActivityTransitions(Class, List)
+ * @see EventTracker#waitForActivityTransitions(Class, List)
*/
final void waitForActivityTransitions(Class<? extends Activity> activityClass,
List<String> expectedTransitions) {
log("Start waitForActivityTransitions");
- mLifecycleTracker.waitForActivityTransitions(activityClass, expectedTransitions);
+ mTransitionTracker.waitForActivityTransitions(activityClass, expectedTransitions);
}
/**
* Blocking call that will wait for activities to perform the expected sequence of transitions.
* After waiting it asserts that the sequence matches the expected.
- * @see LifecycleTracker#waitForActivityTransitions(Class, List)
+ * @see EventTracker#waitForActivityTransitions(Class, List)
*/
final void waitAndAssertActivityTransitions(Class<? extends Activity> activityClass,
List<String> expectedTransitions, String message) {
log("Start waitAndAssertActivityTransition");
- mLifecycleTracker.waitForActivityTransitions(activityClass, expectedTransitions);
+ mTransitionTracker.waitForActivityTransitions(activityClass, expectedTransitions);
- LifecycleVerifier.assertSequence(activityClass, getLifecycleLog(), expectedTransitions,
+ TransitionVerifier.assertSequence(activityClass, getTransitionLog(), expectedTransitions,
message);
}
- LifecycleLog getLifecycleLog() {
- return mLifecycleLog;
+ EventLog getTransitionLog() {
+ return sEventLog;
}
static Pair<Class<? extends Activity>, String> state(Activity activity,
@@ -620,7 +620,7 @@
void moveTaskToPrimarySplitScreenAndVerify(Activity primaryActivity,
Activity secondaryActivity) throws Exception {
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mWmState.computeState(secondaryActivity.getComponentName());
moveActivitiesToSplitScreen(primaryActivity.getComponentName(),
@@ -629,9 +629,9 @@
final Class<? extends Activity> activityClass = primaryActivity.getClass();
final List<String> expectedTransitions =
- new ArrayList<>(LifecycleVerifier.getSplitScreenTransitionSequence(activityClass));
+ new ArrayList<>(TransitionVerifier.getSplitScreenTransitionSequence(activityClass));
final List<String> expectedTransitionForMinimizedDock =
- LifecycleVerifier.appendMinimizedDockTransitionTrail(expectedTransitions);
+ TransitionVerifier.appendMinimizedDockTransitionTrail(expectedTransitions);
final int displayWindowingMode =
getDisplayWindowingModeByActivity(getComponentName(activityClass));
@@ -642,10 +642,10 @@
Collections.singleton(ON_MULTI_WINDOW_MODE_CHANGED));
}
- mLifecycleTracker.waitForActivityTransitions(activityClass, expectedTransitions);
- LifecycleVerifier.assertSequenceMatchesOneOf(
+ mTransitionTracker.waitForActivityTransitions(activityClass, expectedTransitions);
+ TransitionVerifier.assertSequenceMatchesOneOf(
activityClass,
- getLifecycleLog(),
+ getTransitionLog(),
Arrays.asList(expectedTransitions, expectedTransitionForMinimizedDock),
"enterSplitScreen");
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java
index 9dded99..07e4ac0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java
@@ -29,6 +29,12 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_RESUME;
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_LOST;
import static android.server.wm.lifecycle.LifecycleConstants.getComponentName;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEmptySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchAndPauseSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartAndResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeTrue;
@@ -44,7 +50,7 @@
import org.junit.Before;
import org.junit.Test;
-import java.util.Arrays;
+import java.util.Collections;
/**
* Build/Install/Run:
@@ -77,8 +83,8 @@
// Wait and assert resume
waitAndAssertActivityState(getComponentName(FirstActivity.class), STATE_RESUMED,
"Activity should be resumed after launch");
- LifecycleVerifier.assertLaunchSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertLaunchSequence(FirstActivity.class, getTransitionLog());
+ assertLaunchSequence(CallbackTrackingActivity.class, getTransitionLog(),
ON_TOP_POSITION_LOST);
}
@@ -113,10 +119,10 @@
waitAndAssertActivityState(getComponentName(ThirdActivity.class), STATE_RESUMED, message);
// Assert lifecycle
- LifecycleVerifier.assertLaunchSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(SecondActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(ThirdActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertLaunchSequence(FirstActivity.class, getTransitionLog());
+ assertLaunchSequence(SecondActivity.class, getTransitionLog());
+ assertLaunchSequence(ThirdActivity.class, getTransitionLog());
+ assertLaunchSequence(CallbackTrackingActivity.class, getTransitionLog(),
ON_TOP_POSITION_LOST);
}
@@ -150,14 +156,14 @@
waitAndAssertActivityState(getComponentName(ThirdActivity.class), STATE_RESUMED, message);
// Assert lifecycle
- LifecycleVerifier.assertLaunchAndStopSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(SecondActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(ThirdActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ TransitionVerifier.assertLaunchAndStopSequence(FirstActivity.class, getTransitionLog());
+ assertLaunchSequence(SecondActivity.class, getTransitionLog());
+ assertLaunchSequence(ThirdActivity.class, getTransitionLog());
+ assertLaunchSequence(CallbackTrackingActivity.class, getTransitionLog(),
ON_TOP_POSITION_LOST);
// Finish the activity that was occluding the first one
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondActivity.finish();
// Wait and assert the lifecycle
@@ -170,11 +176,10 @@
assertFalse("Activity must be destroyed",
mWmState.containsWindow(
getWindowName(getComponentName(SecondActivity.class))));
- LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertResumeToDestroySequence(SecondActivity.class, getLifecycleLog());
- LifecycleVerifier.assertEmptySequence(ThirdActivity.class, getLifecycleLog(),
- "finishInOtherStack");
- LifecycleVerifier.assertEmptySequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertRestartAndResumeSequence(FirstActivity.class, getTransitionLog());
+ assertResumeToDestroySequence(SecondActivity.class, getTransitionLog());
+ assertEmptySequence(ThirdActivity.class, getTransitionLog(), "finishInOtherStack");
+ assertEmptySequence(CallbackTrackingActivity.class, getTransitionLog(),
"finishInOtherStack");
}
@@ -209,14 +214,14 @@
waitAndAssertActivityState(getComponentName(ThirdActivity.class), STATE_RESUMED, message);
// Assert lifecycle
- LifecycleVerifier.assertLaunchAndPauseSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(TranslucentActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(ThirdActivity.class, getLifecycleLog());
- LifecycleVerifier.assertLaunchSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertLaunchAndPauseSequence(FirstActivity.class, getTransitionLog());
+ assertLaunchSequence(TranslucentActivity.class, getTransitionLog());
+ assertLaunchSequence(ThirdActivity.class, getTransitionLog());
+ assertLaunchSequence(CallbackTrackingActivity.class, getTransitionLog(),
ON_TOP_POSITION_LOST);
// Finish the activity that was occluding the first one
- getLifecycleLog().clear();
+ getTransitionLog().clear();
transparentActivity.finish();
// Wait and assert the lifecycle
@@ -231,13 +236,13 @@
assertFalse("Activity must be destroyed",
mWmState.containsWindow(
getWindowName(getComponentName(TranslucentActivity.class))));
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
- Arrays.asList(ON_RESUME), "finishTranslucentOnTop");
- LifecycleVerifier.assertResumeToDestroySequence(TranslucentActivity.class,
- getLifecycleLog());
- LifecycleVerifier.assertEmptySequence(ThirdActivity.class, getLifecycleLog(),
+ assertSequence(FirstActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_RESUME), "finishTranslucentOnTop");
+ assertResumeToDestroySequence(TranslucentActivity.class,
+ getTransitionLog());
+ assertEmptySequence(ThirdActivity.class, getTransitionLog(),
"finishInOtherStack");
- LifecycleVerifier.assertEmptySequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertEmptySequence(CallbackTrackingActivity.class, getTransitionLog(),
"finishInOtherStack");
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java
index 2465c15..b958cd8 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleKeyguardTests.java
@@ -22,6 +22,11 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_RESUME;
import static android.server.wm.lifecycle.LifecycleConstants.ON_START;
import static android.server.wm.lifecycle.LifecycleConstants.ON_STOP;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchAndStopSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartAndResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartAndResumeSubSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToStopSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
import static org.junit.Assume.assumeTrue;
@@ -33,6 +38,7 @@
import org.junit.Test;
import java.util.Arrays;
+import java.util.Collections;
/**
* Build/Install/Run:
@@ -53,7 +59,7 @@
.setExpectedState(ON_STOP)
.setNoInstance()
.launch();
- LifecycleVerifier.assertLaunchAndStopSequence(FirstActivity.class, getLifecycleLog());
+ assertLaunchAndStopSequence(FirstActivity.class, getTransitionLog());
}
}
@@ -69,19 +75,17 @@
lockScreenSession.setLockCredential().gotoKeyguard();
waitAndAssertActivityStates(state(activity, ON_STOP));
- LifecycleVerifier.assertLaunchAndStopSequence(FirstActivity.class, getLifecycleLog());
- getLifecycleLog().clear();
+ assertLaunchAndStopSequence(FirstActivity.class, getTransitionLog());
+ getTransitionLog().clear();
} // keyguard hidden
// Verify that activity was resumed
if (isCar()) {
- LifecycleVerifier.assertRestartAndResumeSubSequence(FirstActivity.class,
- getLifecycleLog());
+ assertRestartAndResumeSubSequence(FirstActivity.class, getTransitionLog());
waitAndAssertActivityCurrentState(activity.getClass(), ON_RESUME);
} else {
waitAndAssertActivityStates(state(activity, ON_RESUME));
- LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class,
- getLifecycleLog());
+ assertRestartAndResumeSequence(FirstActivity.class, getTransitionLog());
}
}
@@ -97,21 +101,21 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, secondaryActivity);
// Show and hide lock screen
- getLifecycleLog().clear();
+ getTransitionLog().clear();
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.setLockCredential().gotoKeyguard();
waitAndAssertActivityStates(state(firstActivity, ON_STOP));
waitAndAssertActivityStates(state(secondaryActivity, ON_STOP));
- LifecycleVerifier.assertResumeToStopSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertResumeToStopSequence(SideActivity.class, getLifecycleLog());
- getLifecycleLog().clear();
+ assertResumeToStopSequence(FirstActivity.class, getTransitionLog());
+ assertResumeToStopSequence(SideActivity.class, getTransitionLog());
+ getTransitionLog().clear();
} // keyguard hidden
waitAndAssertActivityStates(state(firstActivity, ON_RESUME),
state(secondaryActivity, ON_RESUME));
- LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertRestartAndResumeSequence(SideActivity.class, getLifecycleLog());
+ assertRestartAndResumeSequence(FirstActivity.class, getTransitionLog());
+ assertRestartAndResumeSequence(SideActivity.class, getTransitionLog());
}
@Test
@@ -126,7 +130,7 @@
final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
// Clear the log before launching to Pip
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Launch Pip-capable activity and enter Pip immediately
new Launcher(PipActivity.class)
@@ -138,23 +142,23 @@
waitAndAssertActivityStates(state(firstActivity, ON_RESUME));
// Show and hide lock screen
- getLifecycleLog().clear();
+ getTransitionLog().clear();
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.setLockCredential().gotoKeyguard();
waitAndAssertActivityStates(state(firstActivity, ON_STOP));
waitAndAssertActivityStates(state(PipActivity.class, ON_STOP));
- LifecycleVerifier.assertResumeToStopSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
- Arrays.asList(ON_STOP), "keyguardShown");
- getLifecycleLog().clear();
+ assertResumeToStopSequence(FirstActivity.class, getTransitionLog());
+ assertSequence(PipActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_STOP), "keyguardShown");
+ getTransitionLog().clear();
} // keyguard hidden
// Wait and assert lifecycle
waitAndAssertActivityStates(state(firstActivity, ON_RESUME),
state(PipActivity.class, ON_PAUSE));
- LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
+ assertRestartAndResumeSequence(FirstActivity.class, getTransitionLog());
+ assertSequence(PipActivity.class, getTransitionLog(),
Arrays.asList(ON_RESTART, ON_START, ON_RESUME, ON_PAUSE), "keyguardGone");
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java
index 85bc07e..a1e4a5c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java
@@ -33,7 +33,14 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_LOST;
import static android.server.wm.lifecycle.LifecycleConstants.ON_USER_LEAVE_HINT;
import static android.server.wm.lifecycle.LifecycleConstants.getComponentName;
-import static android.server.wm.lifecycle.LifecycleVerifier.transition;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertOrder;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRecreateAndResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartAndResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertTransitionObserved;
+import static android.server.wm.lifecycle.TransitionVerifier.transition;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -86,7 +93,7 @@
moveTaskToPrimarySplitScreenAndVerify(secondActivity, sideActivity);
// CLear logs so we can capture just the destroy sequence
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Start an activity in separate task (will be placed in secondary stack)
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
@@ -102,10 +109,10 @@
// Verify that the first activity was recreated to resume as it was created before
// windowing mode was switched
- LifecycleVerifier.assertRecreateAndResumeSequence(FirstActivity.class, getLifecycleLog());
+ assertRecreateAndResumeSequence(FirstActivity.class, getTransitionLog());
// Verify that the lifecycle state did not change for activity in non-focused stack
- LifecycleVerifier.assertLaunchSequence(ThirdActivity.class, getLifecycleLog());
+ assertLaunchSequence(ThirdActivity.class, getTransitionLog());
}
@Test
@@ -120,7 +127,7 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Launch third activity on top of second
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
new Launcher(ThirdActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
@@ -142,7 +149,7 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Launch translucent activity on top of second
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
new Launcher(TranslucentActivity.class)
@@ -184,13 +191,13 @@
moveTaskToPrimarySplitScreenAndVerify(secondActivity, sideActivity);
// Finish top activity and verify that activity below became focused.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondActivity.setResult(Activity.RESULT_OK);
secondActivity.finish();
// Check that activity was restarted and result was delivered
waitAndAssertActivityStates(state(callbackTrackingActivity, ON_RESUME));
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertSequence(CallbackTrackingActivity.class, getTransitionLog(),
Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_POST_CREATE,
ON_ACTIVITY_RESULT, ON_RESUME), "restart");
}
@@ -213,14 +220,14 @@
.launch();
// Launch second activity, first become stopped
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Activity secondActivity = launchActivityAndWait(SecondActivity.class);
// Wait for second activity to resume and first to stop
waitAndAssertActivityStates(state(newTaskActivity, ON_STOP));
// Finish top activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondActivity.finish();
waitAndAssertActivityStates(state(newTaskActivity, ON_RESUME));
@@ -228,8 +235,8 @@
// Verify that the first activity was restarted to resumed state as it was brought back
// after windowing mode was switched
- LifecycleVerifier.assertRestartAndResumeSequence(ThirdActivity.class, getLifecycleLog());
- LifecycleVerifier.assertResumeToDestroySequence(SecondActivity.class, getLifecycleLog());
+ assertRestartAndResumeSequence(ThirdActivity.class, getTransitionLog());
+ assertResumeToDestroySequence(SecondActivity.class, getTransitionLog());
}
@Test
@@ -252,17 +259,17 @@
sideActivity.getComponentName());
// Finish top activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
translucentActivity.finish();
waitAndAssertActivityStates(state(firstActivity, ON_RESUME));
waitAndAssertActivityStates(state(translucentActivity, ON_DESTROY));
// Verify that the first activity was resumed
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
+ assertSequence(FirstActivity.class, getTransitionLog(),
Arrays.asList(ON_RESUME), "resume");
- LifecycleVerifier.assertResumeToDestroySequence(TranslucentActivity.class,
- getLifecycleLog());
+ assertResumeToDestroySequence(TranslucentActivity.class,
+ getTransitionLog());
}
@Test
@@ -276,10 +283,10 @@
.launch();
// Wait for the activity to resume
- LifecycleVerifier.assertLaunchSequence(CallbackTrackingActivity.class, getLifecycleLog());
+ assertLaunchSequence(CallbackTrackingActivity.class, getTransitionLog());
// Enter split screen
- getLifecycleLog().clear();
+ getTransitionLog().clear();
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Wait for the activity to relaunch and receive multi-window mode change
@@ -288,12 +295,12 @@
ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED,
ON_TOP_POSITION_LOST, ON_PAUSE);
waitForActivityTransitions(CallbackTrackingActivity.class, expectedEnterSequence);
- LifecycleVerifier.assertOrder(getLifecycleLog(), CallbackTrackingActivity.class,
+ assertOrder(getTransitionLog(), CallbackTrackingActivity.class,
Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY, ON_CREATE,
ON_RESUME), "moveToSplitScreen");
// Exit split-screen
- getLifecycleLog().clear();
+ getTransitionLog().clear();
dismissSplitScreen(true /* primaryOnTop */);
// Wait for the activity to relaunch and receive multi-window mode change
@@ -301,7 +308,7 @@
Arrays.asList(ON_STOP, ON_DESTROY, ON_CREATE, ON_START,
ON_POST_CREATE, ON_RESUME, ON_PAUSE, ON_RESUME, ON_TOP_POSITION_GAINED);
waitForActivityTransitions(CallbackTrackingActivity.class, expectedExitSequence);
- LifecycleVerifier.assertOrder(getLifecycleLog(), CallbackTrackingActivity.class,
+ assertOrder(getTransitionLog(), CallbackTrackingActivity.class,
Arrays.asList(ON_DESTROY, ON_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED),
"moveFromSplitScreen");
}
@@ -325,7 +332,7 @@
// Wait for the activity to receive the change.
waitForActivityTransitions(LifecycleConfigChangeHandlingActivity.class,
Arrays.asList(ON_TOP_POSITION_LOST, ON_MULTI_WINDOW_MODE_CHANGED));
- LifecycleVerifier.assertOrder(getLifecycleLog(),
+ assertOrder(getTransitionLog(),
LifecycleConfigChangeHandlingActivity.class,
Arrays.asList(ON_MULTI_WINDOW_MODE_CHANGED, ON_TOP_POSITION_LOST),
"moveToSplitScreen");
@@ -333,13 +340,13 @@
// For non-fullscreen display mode, there won't be a multi-window callback.
waitForActivityTransitions(LifecycleConfigChangeHandlingActivity.class,
Arrays.asList(ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertTransitionObserved(getLifecycleLog(),
+ assertTransitionObserved(getTransitionLog(),
transition(LifecycleConfigChangeHandlingActivity.class, ON_TOP_POSITION_LOST),
"moveToSplitScreen");
}
// Exit split-screen
- getLifecycleLog().clear();
+ getTransitionLog().clear();
dismissSplitScreen(true /* primaryOnTop */);
// Wait for the activity to receive the change
@@ -348,11 +355,11 @@
waitForActivityTransitions(LifecycleConfigChangeHandlingActivity.class, expectedSequence);
if (displayWindowingMode == WINDOWING_MODE_FULLSCREEN) {
- LifecycleVerifier.assertTransitionObserved(getLifecycleLog(),
- transition(LifecycleConfigChangeHandlingActivity.class,
- ON_MULTI_WINDOW_MODE_CHANGED), "exitSplitScreen");
+ assertTransitionObserved(getTransitionLog(),
+ transition(LifecycleConfigChangeHandlingActivity.class,
+ ON_MULTI_WINDOW_MODE_CHANGED), "exitSplitScreen");
}
- LifecycleVerifier.assertTransitionObserved(getLifecycleLog(),
+ assertTransitionObserved(getTransitionLog(),
transition(LifecycleConfigChangeHandlingActivity.class, ON_TOP_POSITION_GAINED),
"exitSplitScreen");
}
@@ -368,12 +375,12 @@
extra -> extra.putBoolean(EXTRA_ACTIVITY_ON_USER_LEAVE_HINT, true))
.setTargetActivity(getComponentName(FirstActivity.class)));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
launchActivityAndWait(SecondActivity.class);
waitForIdle();
- LifecycleVerifier.assertOrder(getLifecycleLog(), FirstActivity.class,
+ assertOrder(getTransitionLog(), FirstActivity.class,
Arrays.asList(ON_USER_LEAVE_HINT, ON_PAUSE, ON_STOP),
"moveFromSplitScreen");
}
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 f0dd905..f895e4f 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
@@ -26,6 +26,12 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_RESUME;
import static android.server.wm.lifecycle.LifecycleConstants.ON_START;
import static android.server.wm.lifecycle.LifecycleConstants.ON_STOP;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEmptySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartAndResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequenceMatchesOneOf;
import static org.junit.Assume.assumeTrue;
@@ -38,6 +44,7 @@
import org.junit.Test;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -66,14 +73,14 @@
waitAndAssertActivityStates(state(firstActivity, ON_STOP));
// Move activity to Picture-In-Picture
- getLifecycleLog().clear();
+ getTransitionLog().clear();
pipActivity.enterPip();
// Wait and assert lifecycle
waitAndAssertActivityStates(state(firstActivity, ON_RESUME), state(pipActivity, ON_PAUSE));
- LifecycleVerifier.assertRestartAndResumeSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
- Arrays.asList(ON_PAUSE), "enterPip");
+ assertRestartAndResumeSequence(FirstActivity.class, getTransitionLog());
+ assertSequence(PipActivity.class, getTransitionLog(), Collections.singletonList(ON_PAUSE),
+ "enterPip");
}
@Test
@@ -82,7 +89,7 @@
final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
// Clear the log before launching to Pip
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Launch Pip-capable activity and enter Pip immediately
new Launcher(PipActivity.class)
@@ -97,10 +104,9 @@
Arrays.asList(ON_PAUSE, ON_RESUME);
final List<String> extraCycleSequence =
Arrays.asList(ON_PAUSE, ON_STOP, ON_RESTART, ON_START, ON_RESUME);
- LifecycleVerifier.assertSequenceMatchesOneOf(FirstActivity.class,
- getLifecycleLog(), Arrays.asList(expectedSequence, extraCycleSequence),
- "activityEnteringPipOnTop");
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
+ assertSequenceMatchesOneOf(FirstActivity.class, getTransitionLog(),
+ Arrays.asList(expectedSequence, extraCycleSequence), "activityEnteringPipOnTop");
+ assertSequence(PipActivity.class, getTransitionLog(),
Arrays.asList(ON_CREATE, ON_START, ON_RESUME, ON_PAUSE), "launchAndEnterPip");
}
@@ -110,7 +116,7 @@
final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
// Clear the log before launching to Pip
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Launch Pip-capable activity and enter Pip immediately
final Activity pipActivity = new Launcher(PipActivity.class)
@@ -122,12 +128,12 @@
waitAndAssertActivityStates(state(firstActivity, ON_RESUME));
// Exit PiP
- getLifecycleLog().clear();
+ getTransitionLog().clear();
pipActivity.finish();
waitAndAssertActivityStates(state(pipActivity, ON_DESTROY));
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(), "finishPip");
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
+ assertEmptySequence(FirstActivity.class, getTransitionLog(), "finishPip");
+ assertSequence(PipActivity.class, getTransitionLog(),
Arrays.asList(ON_STOP, ON_DESTROY), "finishPip");
}
@@ -140,14 +146,14 @@
.launch();
// Launch a regular activity below
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(FirstActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.launch();
// Wait and verify the sequence
- LifecycleVerifier.assertLaunchSequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertEmptySequence(PipActivity.class, getLifecycleLog(),
+ assertLaunchSequence(FirstActivity.class, getTransitionLog());
+ assertEmptySequence(PipActivity.class, getTransitionLog(),
"launchBelowPip");
}
@@ -160,7 +166,7 @@
.launch();
// Launch a regular activity into same task
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(FirstActivity.class)
.setExpectedState(ON_PAUSE)
// Skip launch time verification - it can be affected by PiP menu activity
@@ -177,11 +183,11 @@
//waitForActivityTransitions(FirstActivity.class, extraDestroySequence);
//final List<String> expectedSequence =
// Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE);
- //LifecycleVerifier.assertSequenceMatchesOneOf(FirstActivity.class, getLifecycleLog(),
+ //TransitionVerifier.assertSequenceMatchesOneOf(FirstActivity.class, getLifecycleLog(),
// Arrays.asList(extraDestroySequence, expectedSequence),
// "launchIntoPip");
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
+ assertSequence(PipActivity.class, getTransitionLog(),
Arrays.asList(ON_STOP), "launchIntoPip");
}
@@ -199,11 +205,11 @@
waitAndAssertActivityStates(state(firstActivity, ON_RESUME));
// Destroy the activity below
- getLifecycleLog().clear();
+ getTransitionLog().clear();
firstActivity.finish();
waitAndAssertActivityStates(state(firstActivity, ON_DESTROY));
- LifecycleVerifier.assertResumeToDestroySequence(FirstActivity.class, getLifecycleLog());
- LifecycleVerifier.assertEmptySequence(PipActivity.class, getLifecycleLog(),
+ assertResumeToDestroySequence(FirstActivity.class, getTransitionLog());
+ assertEmptySequence(PipActivity.class, getTransitionLog(),
"destroyBelowPip");
}
@@ -223,25 +229,25 @@
.launch();
// Launch first activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Activity firstActivity = new Launcher(FirstActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.launch();
- LifecycleVerifier.assertLaunchSequence(FirstActivity.class, getLifecycleLog());
+ assertLaunchSequence(FirstActivity.class, getTransitionLog());
// Enter split screen
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
- LifecycleVerifier.assertEmptySequence(PipActivity.class, getLifecycleLog(),
+ assertEmptySequence(PipActivity.class, getTransitionLog(),
"launchBelow");
// Launch second activity to side
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SecondActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.launch();
- LifecycleVerifier.assertLaunchSequence(SecondActivity.class, getLifecycleLog());
- LifecycleVerifier.assertEmptySequence(PipActivity.class, getLifecycleLog(),
+ assertLaunchSequence(SecondActivity.class, getTransitionLog());
+ assertEmptySequence(PipActivity.class, getTransitionLog(),
"launchBelow");
}
@@ -264,7 +270,7 @@
.launch();
// Launch Pip-capable activity and enter Pip immediately
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(PipActivity.class)
.setExpectedState(ON_PAUSE)
.setExtraFlags(EXTRA_ENTER_PIP)
@@ -272,18 +278,18 @@
// Wait for it to launch and pause. Other activities should not be affected.
waitAndAssertActivityStates(state(secondActivity, ON_RESUME));
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
+ assertSequence(PipActivity.class, getTransitionLog(),
Arrays.asList(ON_CREATE, ON_START, ON_RESUME, ON_PAUSE),
"launchAndEnterPip");
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(),
+ assertEmptySequence(FirstActivity.class, getTransitionLog(),
"launchPipOnTop");
final List<String> expectedSequence =
Arrays.asList(ON_PAUSE, ON_RESUME);
final List<String> extraCycleSequence =
Arrays.asList(ON_PAUSE, ON_STOP, ON_RESTART, ON_START, ON_RESUME);
// TODO(b/123013403): sometimes extra destroy is observed
- LifecycleVerifier.assertSequenceMatchesOneOf(SecondActivity.class,
- getLifecycleLog(), Arrays.asList(expectedSequence, extraCycleSequence),
+ assertSequenceMatchesOneOf(SecondActivity.class,
+ getTransitionLog(), Arrays.asList(expectedSequence, extraCycleSequence),
"activityEnteringPipOnTop");
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
index 0cf0dc3..e7b2909 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
@@ -53,7 +53,21 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_LOST;
import static android.server.wm.lifecycle.LifecycleConstants.ON_USER_LEAVE_HINT;
import static android.server.wm.lifecycle.LifecycleConstants.getComponentName;
-import static android.server.wm.lifecycle.LifecycleVerifier.transition;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEmptySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEntireSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchAndDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertOrder;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRelaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartAndResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRestartSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequenceMatchesOneOf;
+import static android.server.wm.lifecycle.TransitionVerifier.assertTransitionNotObserved;
+import static android.server.wm.lifecycle.TransitionVerifier.assertTransitionObserved;
+import static android.server.wm.lifecycle.TransitionVerifier.getLaunchAndDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.transition;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
@@ -77,6 +91,7 @@
import org.junit.Test;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -92,19 +107,19 @@
public void testSingleLaunch() throws Exception {
launchActivityAndWait(FirstActivity.class);
- LifecycleVerifier.assertLaunchSequence(FirstActivity.class, getLifecycleLog());
+ assertLaunchSequence(FirstActivity.class, getTransitionLog());
}
@Test
public void testLaunchOnTop() throws Exception {
final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
launchActivityAndWait(SecondActivity.class);
waitAndAssertActivityStates(state(firstActivity, ON_STOP));
- LifecycleVerifier.assertLaunchSequence(SecondActivity.class, FirstActivity.class,
- getLifecycleLog(), false /* launchIsTranslucent */);
+ assertLaunchSequence(SecondActivity.class, FirstActivity.class,
+ getTransitionLog(), false /* launchIsTranslucent */);
}
@Test
@@ -113,12 +128,12 @@
final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
// Launch translucent activity on top
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Activity translucentActivity = launchActivityAndWait(TranslucentActivity.class);
waitAndAssertActivityStates(occludedActivityState(firstActivity, translucentActivity));
- LifecycleVerifier.assertLaunchSequence(TranslucentActivity.class, FirstActivity.class,
- getLifecycleLog(), true /* launchIsTranslucent */);
+ assertLaunchSequence(TranslucentActivity.class, FirstActivity.class,
+ getTransitionLog(), true /* launchIsTranslucent */);
}
@Test
@@ -126,34 +141,33 @@
final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
// Launch translucent activity on top
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Activity translucentActivity = launchActivityAndWait(TranslucentActivity.class);
waitAndAssertActivityStates(occludedActivityState(firstActivity, translucentActivity));
- LifecycleVerifier.assertLaunchSequence(TranslucentActivity.class, FirstActivity.class,
- getLifecycleLog(), true /* launchIsTranslucent */);
+ assertLaunchSequence(TranslucentActivity.class, FirstActivity.class,
+ getTransitionLog(), true /* launchIsTranslucent */);
// Launch another translucent activity on top
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Activity secondTranslucentActivity =
launchActivityAndWait(SecondTranslucentActivity.class);
waitAndAssertActivityStates(
occludedActivityState(translucentActivity, secondTranslucentActivity));
- LifecycleVerifier.assertSequence(TranslucentActivity.class, getLifecycleLog(),
- Arrays.asList(ON_PAUSE), "launch");
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(), "launch");
+ assertSequence(TranslucentActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_PAUSE), "launch");
+ assertEmptySequence(FirstActivity.class, getTransitionLog(), "launch");
// Finish top translucent activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondTranslucentActivity.finish();
waitAndAssertActivityStates(state(translucentActivity, ON_RESUME));
waitAndAssertActivityStates(state(secondTranslucentActivity, ON_DESTROY));
- LifecycleVerifier.assertResumeToDestroySequence(SecondTranslucentActivity.class,
- getLifecycleLog());
- LifecycleVerifier.assertSequence(TranslucentActivity.class, getLifecycleLog(),
- Arrays.asList(ON_RESUME), "launch");
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(), "launch");
+ assertResumeToDestroySequence(SecondTranslucentActivity.class, getTransitionLog());
+ assertSequence(TranslucentActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_RESUME), "launch");
+ assertEmptySequence(FirstActivity.class, getTransitionLog(), "launch");
}
@Test
@@ -173,16 +187,15 @@
int firstActivityStack = mWmState.getRootTaskIdByActivity(firstActivityName);
// Move translucent activity into the stack with the first activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
moveActivityToRootTaskOrOnTop(getComponentName(TranslucentActivity.class), firstActivityStack);
// Wait for translucent activity to resume and first activity to pause
waitAndAssertActivityStates(state(translucentActivity, ON_RESUME),
state(firstActivity, ON_PAUSE));
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
- Arrays.asList(ON_PAUSE), "launchOnTop");
- LifecycleVerifier.assertRestartAndResumeSequence(TranslucentActivity.class,
- getLifecycleLog());
+ assertSequence(FirstActivity.class, getTransitionLog(), Collections.singletonList(ON_PAUSE),
+ "launchOnTop");
+ assertRestartAndResumeSequence(TranslucentActivity.class, getTransitionLog());
}
@Test
@@ -193,16 +206,16 @@
waitAndAssertActivityStates(occludedActivityState(firstActivity, translucentActivity));
// Finish translucent activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
translucentActivity.finish();
waitAndAssertActivityStates(state(firstActivity, ON_RESUME),
state(translucentActivity, ON_DESTROY));
// Verify destruction lifecycle
- LifecycleVerifier.assertResumeToDestroySequence(TranslucentActivity.class,
- getLifecycleLog());
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
+ assertResumeToDestroySequence(TranslucentActivity.class,
+ getTransitionLog());
+ assertSequence(FirstActivity.class, getTransitionLog(),
Arrays.asList(ON_RESUME), "resumeAfterTopDestroyed");
}
@@ -219,7 +232,7 @@
waitAndAssertActivityStates(state(translucentActivity, ON_STOP),
state(firstActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final boolean secondActivityIsTranslucent = ActivityInfo.isTranslucentOrFloating(
secondActivity.getWindow().getWindowStyle());
@@ -228,7 +241,7 @@
secondActivity.finish();
waitAndAssertActivityStates(state(secondActivity, ON_DESTROY));
- LifecycleVerifier.assertResumeToDestroySequence(SecondActivity.class, getLifecycleLog());
+ assertResumeToDestroySequence(SecondActivity.class, getTransitionLog());
if (secondActivityIsTranslucent) {
// In this case we don't expect the state of the firstActivity to change since it is
// already in the visible paused state. So, we just verify that translucentActivity
@@ -240,7 +253,7 @@
state(firstActivity, ON_START));
// Verify that the first activity was restarted
- LifecycleVerifier.assertRestartSequence(FirstActivity.class, getLifecycleLog());
+ assertRestartSequence(FirstActivity.class, getTransitionLog());
}
}
@@ -254,27 +267,26 @@
occludedActivityState(translucentActivity, secondTranslucentActivity));
// Finish top translucent activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondTranslucentActivity.finish();
waitAndAssertActivityStates(state(translucentActivity, ON_RESUME));
waitAndAssertActivityStates(state(secondTranslucentActivity, ON_DESTROY));
- LifecycleVerifier.assertResumeToDestroySequence(SecondTranslucentActivity.class,
- getLifecycleLog());
- LifecycleVerifier.assertSequence(TranslucentActivity.class, getLifecycleLog(),
- Arrays.asList(ON_RESUME), "destroy");
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(), "destroy");
+ assertResumeToDestroySequence(SecondTranslucentActivity.class,
+ getTransitionLog());
+ assertSequence(TranslucentActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_RESUME), "destroy");
+ assertEmptySequence(FirstActivity.class, getTransitionLog(), "destroy");
// Finish first translucent activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
translucentActivity.finish();
waitAndAssertActivityStates(state(firstActivity, ON_RESUME));
waitAndAssertActivityStates(state(translucentActivity, ON_DESTROY));
- LifecycleVerifier.assertResumeToDestroySequence(TranslucentActivity.class,
- getLifecycleLog());
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
- Arrays.asList(ON_RESUME), "secondDestroy");
+ assertResumeToDestroySequence(TranslucentActivity.class, getTransitionLog());
+ assertSequence(FirstActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_RESUME), "secondDestroy");
}
@Test
@@ -284,15 +296,15 @@
waitAndAssertActivityStates(state(bottomActivity, ON_STOP));
// Finish the activity on the bottom
- getLifecycleLog().clear();
+ getTransitionLog().clear();
bottomActivity.finish();
// Assert that activity on the bottom went directly to destroyed state, and activity on top
// did not get any lifecycle changes.
waitAndAssertActivityStates(state(bottomActivity, ON_DESTROY));
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
- Arrays.asList(ON_DESTROY), "destroyOnBottom");
- LifecycleVerifier.assertEmptySequence(SecondActivity.class, getLifecycleLog(),
+ assertSequence(FirstActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_DESTROY), "destroyOnBottom");
+ assertEmptySequence(SecondActivity.class, getTransitionLog(),
"destroyOnBottom");
}
@@ -321,7 +333,7 @@
waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED),
state(ResultActivity.class, ON_DESTROY));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
// Base launching activity starting.
transition(LaunchForResultActivity.class, ON_CREATE),
transition(LaunchForResultActivity.class, ON_START),
@@ -352,7 +364,7 @@
activity.finish();
waitAndAssertActivityStates(state(activity, ON_DESTROY));
- LifecycleVerifier.assertLaunchAndDestroySequence(FirstActivity.class, getLifecycleLog());
+ assertLaunchAndDestroySequence(FirstActivity.class, getTransitionLog());
}
@Test
@@ -385,7 +397,7 @@
launcher.launch();
waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(NoDisplayActivity.class, ON_CREATE),
transition(CallbackTrackingActivity.class, ON_CREATE),
transition(CallbackTrackingActivity.class, ON_START),
@@ -393,7 +405,7 @@
transition(CallbackTrackingActivity.class, ON_RESUME),
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED),
transition(NoDisplayActivity.class, ON_DESTROY)),
- getLifecycleLog(), "trampolineLaunch");
+ getTransitionLog(), "trampolineLaunch");
}
/** @see #testTrampolineWithAnotherProcess */
@@ -413,7 +425,7 @@
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
waitAndAssertActivityStates(
state(SecondProcessCallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
testTrampolineWithAnotherProcess();
}
@@ -444,11 +456,11 @@
public void testRelaunchResumed() throws Exception {
final Activity activity = launchActivityAndWait(FirstActivity.class);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(activity::recreate);
waitAndAssertActivityStates(state(activity, ON_RESUME));
- LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), ON_RESUME);
+ assertRelaunchSequence(FirstActivity.class, getTransitionLog(), ON_RESUME);
}
@Test
@@ -458,11 +470,11 @@
waitAndAssertActivityStates(occludedActivityState(pausedActivity, translucentActivity));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(pausedActivity::recreate);
waitAndAssertActivityStates(state(pausedActivity, ON_PAUSE));
- LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), ON_PAUSE);
+ assertRelaunchSequence(FirstActivity.class, getTransitionLog(), ON_PAUSE);
}
@Test
@@ -472,12 +484,11 @@
waitAndAssertActivityStates(state(stoppedActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(stoppedActivity::recreate);
waitAndAssertActivityStates(state(stoppedActivity, ON_STOP));
- LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(),
- ON_STOP);
+ assertRelaunchSequence(FirstActivity.class, getTransitionLog(), ON_STOP);
}
@Test
@@ -507,7 +518,7 @@
return;
}
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final int current = rotationSession.get();
// Set new rotation to cause a configuration change.
@@ -526,11 +537,10 @@
// Assert that the top activity was relaunched.
waitAndAssertActivityStates(state(topOpaqueActivity, ON_RESUME));
- LifecycleVerifier.assertRelaunchSequence(
- SecondActivity.class, getLifecycleLog(), ON_RESUME);
+ assertRelaunchSequence(SecondActivity.class, getTransitionLog(), ON_RESUME);
// Finish the top activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
topOpaqueActivity.finish();
// Assert that the translucent activity and the activity visible behind it were
@@ -538,13 +548,13 @@
waitAndAssertActivityStates(state(becomingVisibleActivity, ON_PAUSE),
state(translucentActivity, ON_RESUME));
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
- Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_RESUME,
- ON_PAUSE), "becomingVisiblePaused");
+ assertSequence(FirstActivity.class, getTransitionLog(),
+ Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE),
+ "becomingVisiblePaused");
final List<String> expectedSequence =
Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_RESUME);
- LifecycleVerifier.assertSequence(TranslucentActivity.class, getLifecycleLog(),
- expectedSequence, "becomingVisibleResumed");
+ assertSequence(TranslucentActivity.class, getTransitionLog(), expectedSequence,
+ "becomingVisibleResumed");
}
@Test
@@ -569,7 +579,7 @@
ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP,
ON_RESTART, ON_START, ON_ACTIVITY_RESULT, ON_RESUME,
ON_TOP_POSITION_GAINED);
- LifecycleVerifier.assertSequence(LaunchForwardResultActivity.class, getLifecycleLog(),
+ assertSequence(LaunchForwardResultActivity.class, getTransitionLog(),
expectedSequence, "becomingVisibleResumed");
}
@@ -591,8 +601,7 @@
final List<String> sequenceWithStop =
Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
ON_PAUSE, ON_STOP, ON_RESTART, ON_START, ON_ACTIVITY_RESULT, ON_RESUME);
- LifecycleVerifier.assertSequenceMatchesOneOf(LaunchForResultActivity.class,
- getLifecycleLog(),
+ assertSequenceMatchesOneOf(LaunchForResultActivity.class, getTransitionLog(),
Arrays.asList(expectedSequence, sequenceWithStop), "activityResult");
}
@@ -629,8 +638,8 @@
}
waitForActivityTransitions(LaunchForResultActivity.class, expectedSequences);
- LifecycleVerifier.assertSequence(LaunchForResultActivity.class,
- getLifecycleLog(), expectedSequences, "activityResult");
+ assertSequence(LaunchForResultActivity.class, getTransitionLog(), expectedSequences,
+ "activityResult");
}
@Test
@@ -638,12 +647,11 @@
final Activity trackingActivity = launchActivityAndWait(CallbackTrackingActivity.class);
// Call "recreate" and assert sequence
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(trackingActivity::recreate);
waitAndAssertActivityStates(state(trackingActivity, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class,
- getLifecycleLog(),
+ assertSequence(CallbackTrackingActivity.class, getTransitionLog(),
Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY,
ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED),
"recreate");
@@ -660,12 +668,11 @@
waitAndAssertActivityStates(occludedActivityState(trackingActivity, translucentActivity));
// Call "recreate" and assert sequence
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(trackingActivity::recreate);
waitAndAssertActivityStates(occludedActivityState(trackingActivity, translucentActivity));
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class,
- getLifecycleLog(),
+ assertSequence(CallbackTrackingActivity.class, getTransitionLog(),
Arrays.asList(ON_STOP, ON_DESTROY, ON_CREATE, ON_START,
ON_POST_CREATE, ON_RESUME, ON_PAUSE),
"recreate");
@@ -681,7 +688,7 @@
waitAndAssertActivityStates(state(trackingActivity, ON_STOP));
// Call "recreate" and assert sequence
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(trackingActivity::recreate);
waitAndAssertActivityStates(state(trackingActivity, ON_STOP));
@@ -694,8 +701,8 @@
ON_POST_CREATE, ON_RESUME, ON_PAUSE, ON_STOP);
}
- LifecycleVerifier.assertSequence(
- CallbackTrackingActivity.class, getLifecycleLog(), callbacks, "recreate");
+ assertSequence(
+ CallbackTrackingActivity.class, getTransitionLog(), callbacks, "recreate");
}
/**
@@ -754,7 +761,7 @@
waitAndAssertActivityStates(state(recreatingActivity, ON_STOP));
// Launch the activity again to recreate
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
.setExtraFlags(EXTRA_RECREATE)
@@ -774,8 +781,8 @@
}
waitForActivityTransitions(SingleTopActivity.class, expectedRelaunchSequence);
- LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
- expectedRelaunchSequence, "recreate");
+ assertSequence(SingleTopActivity.class, getTransitionLog(), expectedRelaunchSequence,
+ "recreate");
}
@Test
@@ -783,17 +790,17 @@
// Launch a singleTop activity
launchActivityAndWait(SingleTopActivity.class);
- LifecycleVerifier.assertLaunchSequence(SingleTopActivity.class, getLifecycleLog());
+ assertLaunchSequence(SingleTopActivity.class, getTransitionLog());
// Try to launch again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
.setNoInstance()
.launch();
// Verify that the first activity was paused, new intent was delivered and resumed again
- LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
+ assertSequence(SingleTopActivity.class, getTransitionLog(),
Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_NEW_INTENT, ON_RESUME,
ON_TOP_POSITION_GAINED), "newIntent");
}
@@ -802,7 +809,7 @@
public void testOnNewIntentFromHidden() throws Exception {
// Launch a singleTop activity
final Activity singleTopActivity = launchActivityAndWait(SingleTopActivity.class);
- LifecycleVerifier.assertLaunchSequence(SingleTopActivity.class, getLifecycleLog());
+ assertLaunchSequence(SingleTopActivity.class, getTransitionLog());
// Launch something on top
final Activity secondActivity = new Launcher(SecondActivity.class)
@@ -813,7 +820,7 @@
waitAndAssertActivityStates(state(singleTopActivity, ON_STOP));
// Try to launch again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
.setNoInstance()
@@ -827,15 +834,14 @@
expectedSequence = Arrays.asList(ON_RESTART, ON_START, ON_NEW_INTENT, ON_RESUME,
ON_TOP_POSITION_GAINED);
}
- LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
- expectedSequence, "newIntent");
+ assertSequence(SingleTopActivity.class, getTransitionLog(), expectedSequence, "newIntent");
}
@Test
public void testOnNewIntentFromPaused() throws Exception {
// Launch a singleTop activity
final Activity singleTopActivity = launchActivityAndWait(SingleTopActivity.class);
- LifecycleVerifier.assertLaunchSequence(SingleTopActivity.class, getLifecycleLog());
+ assertLaunchSequence(SingleTopActivity.class, getTransitionLog());
// Launch translucent activity, which will make the first one paused.
launchActivityAndWait(TranslucentActivity.class);
@@ -844,7 +850,7 @@
waitAndAssertActivityStates(state(singleTopActivity, ON_PAUSE));
// Try to launch again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP)
.setNoInstance()
@@ -855,8 +861,7 @@
final List<String> expectedSequence =
Arrays.asList(ON_NEW_INTENT, ON_RESUME, ON_TOP_POSITION_GAINED);
waitForActivityTransitions(SingleTopActivity.class, expectedSequence);
- LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
- expectedSequence, "newIntent");
+ assertSequence(SingleTopActivity.class, getTransitionLog(), expectedSequence, "newIntent");
}
@Test
@@ -955,8 +960,7 @@
// Launch an activity on top, which will make the first one paused or stopped.
launchActivityAndWait(launchOnTopClass);
- final List<String> expectedSequence =
- LifecycleVerifier.getLaunchAndDestroySequence(activityClass);
+ final List<String> expectedSequence = getLaunchAndDestroySequence(activityClass);
waitAndAssertActivityTransitions(activityClass, expectedSequence, "finish in " + stageName);
}
@@ -966,13 +970,13 @@
launchActivityAndWait(TranslucentCallbackTrackingActivity.class);
waitAndAssertActivityStates(state(bottomActivity, ON_PAUSE));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
waitForIdle();
bottomActivity.finish();
waitAndAssertActivityStates(state(bottomActivity, ON_DESTROY));
- LifecycleVerifier.assertEmptySequence(TranslucentCallbackTrackingActivity.class,
- getLifecycleLog(), "finishBelow");
+ assertEmptySequence(TranslucentCallbackTrackingActivity.class,
+ getTransitionLog(), "finishBelow");
}
@Test
@@ -981,13 +985,12 @@
launchActivityAndWait(FirstActivity.class);
waitAndAssertActivityStates(state(bottomActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
waitForIdle();
bottomActivity.finish();
waitAndAssertActivityStates(state(bottomActivity, ON_DESTROY));
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(),
- "finishBelow");
+ assertEmptySequence(FirstActivity.class, getTransitionLog(), "finishBelow");
}
@Test
@@ -1012,7 +1015,7 @@
waitAndAssertActivityStates(state(activity, ON_TOP_POSITION_GAINED));
// Verify the result have been sent back to original activity
- LifecycleVerifier.assertTransitionObserved(getLifecycleLog(),
+ assertTransitionObserved(getTransitionLog(),
transition(SingleTopActivity.class, ON_ACTIVITY_RESULT),"activityResult");
}
@@ -1022,11 +1025,11 @@
.setExtraFlags(EXTRA_ACTIVITY_ON_USER_LEAVE_HINT)
.launch();
- getLifecycleLog().clear();
+ getTransitionLog().clear();
launchActivityAndWait(SecondActivity.class);
waitAndAssertActivityStates(state(FirstActivity.class, ON_STOP));
- LifecycleVerifier.assertTransitionObserved(getLifecycleLog(),
+ assertTransitionObserved(getTransitionLog(),
transition(FirstActivity.class, ON_USER_LEAVE_HINT),"userLeaveHint");
}
@@ -1036,13 +1039,13 @@
.setExtraFlags(EXTRA_ACTIVITY_ON_USER_LEAVE_HINT)
.launch();
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SecondActivity.class)
.setFlags(FLAG_ACTIVITY_NO_USER_ACTION | FLAG_ACTIVITY_NEW_TASK)
.launch();
waitAndAssertActivityStates(state(FirstActivity.class, ON_STOP));
- LifecycleVerifier.assertTransitionNotObserved(getLifecycleLog(),
+ assertTransitionNotObserved(getTransitionLog(),
transition(FirstActivity.class, ON_USER_LEAVE_HINT),"userLeaveHint");
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
index fffce55..9d9fd6a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
@@ -39,7 +39,20 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_GAINED;
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_LOST;
import static android.server.wm.lifecycle.LifecycleConstants.getComponentName;
-import static android.server.wm.lifecycle.LifecycleVerifier.transition;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEmptySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEntireSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchAndStopSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertOrder;
+import static android.server.wm.lifecycle.TransitionVerifier.assertRelaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertResumeToStopSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertStopToResumeSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertStopToResumeSubSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.getLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.getRelaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.transition;
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -63,6 +76,7 @@
import org.junit.Test;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -85,31 +99,30 @@
public void testTopPositionAfterLaunch() throws Exception {
launchActivityAndWait(CallbackTrackingActivity.class);
- LifecycleVerifier.assertLaunchSequence(CallbackTrackingActivity.class, getLifecycleLog());
+ assertLaunchSequence(CallbackTrackingActivity.class, getTransitionLog());
}
@Test
public void testTopPositionLostOnFinish() throws Exception {
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
activity.finish();
mWmState.waitForActivityRemoved(getComponentName(CallbackTrackingActivity.class));
- LifecycleVerifier.assertResumeToDestroySequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertResumeToDestroySequence(CallbackTrackingActivity.class, getTransitionLog());
}
@Test
public void testTopPositionSwitchToActivityOnTop() throws Exception {
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
- final Activity topActivity = launchActivityAndWait(SingleTopActivity.class);
+ getTransitionLog().clear();
+ launchActivityAndWait(SingleTopActivity.class);
waitAndAssertActivityStates(state(activity, ON_STOP));
- LifecycleVerifier.assertLaunchSequence(SingleTopActivity.class,
- CallbackTrackingActivity.class, getLifecycleLog(),
+ assertLaunchSequence(SingleTopActivity.class,
+ CallbackTrackingActivity.class, getTransitionLog(),
false /* launchingIsTranslucent */);
}
@@ -125,7 +138,7 @@
waitAndAssertActivityStates(state(firstActivity, ON_TOP_POSITION_GAINED));
// Launch second activity on top
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Class<? extends Activity> secondActivityClass =
SecondProcessCallbackTrackingActivity.class;
launchActivity(new ComponentName(firstActivity, secondActivityClass));
@@ -133,7 +146,7 @@
// Wait and assert top position switch
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED),
state(firstActivity, ON_STOP));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(firstActivity.getClass(), ON_TOP_POSITION_LOST),
transition(secondActivityClass, ON_TOP_POSITION_GAINED)),
"launchOnTop");
@@ -152,7 +165,7 @@
final Class<? extends Activity> firstActivityClass = firstActivity.getClass();
// Launch second activity on top
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Class<? extends Activity> secondActivityClass =
SecondProcessCallbackTrackingActivity.class;
launchActivity(new ComponentName(firstActivity, secondActivityClass));
@@ -160,18 +173,18 @@
// Wait and assert top position switch,
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED),
state(firstActivity, ON_STOP));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_GAINED),
transition(firstActivityClass, ON_TOP_POSITION_LOST)),
"launchOnTop");
// Wait 5 seconds more to make sure that no new messages received after top resumed state
// released by the slow activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
Thread.sleep(5000);
- LifecycleVerifier.assertEmptySequence(firstActivityClass, getLifecycleLog(),
+ assertEmptySequence(firstActivityClass, getTransitionLog(),
"topStateLossTimeout");
- LifecycleVerifier.assertEmptySequence(secondActivityClass, getLifecycleLog(),
+ assertEmptySequence(secondActivityClass, getTransitionLog(),
"topStateLossTimeout");
}
@@ -179,13 +192,12 @@
public void testTopPositionSwitchToTranslucentActivityOnTop() throws Exception {
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
- final Activity topActivity = launchActivityAndWait(
- TranslucentCallbackTrackingActivity.class);
+ getTransitionLog().clear();
+ launchActivityAndWait(TranslucentCallbackTrackingActivity.class);
waitAndAssertActivityStates(state(activity, ON_PAUSE));
- LifecycleVerifier.assertLaunchSequence(TranslucentCallbackTrackingActivity.class,
- CallbackTrackingActivity.class, getLifecycleLog(),
+ assertLaunchSequence(TranslucentCallbackTrackingActivity.class,
+ CallbackTrackingActivity.class, getTransitionLog(),
true /* launchingIsTranslucent */);
}
@@ -193,7 +205,7 @@
public void testTopPositionSwitchOnDoubleLaunch() throws Exception {
final Activity baseActivity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(LaunchForResultActivity.class)
.setExpectedState(ON_STOP)
.setNoInstance()
@@ -206,7 +218,7 @@
waitForActivityTransitions(ResultActivity.class, expectedTopActivitySequence);
final List<Pair<String, String>> observedTransitions =
- getLifecycleLog().getLog();
+ getTransitionLog().getLog();
final List<Pair<String, String>> expectedTransitions = Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_PAUSE),
@@ -231,8 +243,8 @@
public void testTopPositionSwitchOnDoubleLaunchAndTopFinish() throws Exception {
final Activity baseActivity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
- final Activity launchForResultActivity = new Launcher(LaunchForResultActivity.class)
+ getTransitionLog().clear();
+ new Launcher(LaunchForResultActivity.class)
.customizeIntent(LaunchForResultActivity.forwardFlag(EXTRA_FINISH_IN_ON_RESUME,
EXTRA_SKIP_TOP_RESUMED_STATE))
// Start the TranslucentResultActivity to avoid activity below stopped sometimes
@@ -251,7 +263,7 @@
ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED);
waitForActivityTransitions(TranslucentResultActivity.class, expectedTopActivitySequence);
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_PAUSE),
transition(LaunchForResultActivity.class, ON_CREATE),
@@ -272,7 +284,7 @@
transition(TranslucentResultActivity.class, ON_STOP),
transition(TranslucentResultActivity.class, ON_DESTROY),
transition(CallbackTrackingActivity.class, ON_STOP)),
- getLifecycleLog(), "Double launch sequence must match");
+ getTransitionLog(), "Double launch sequence must match");
}
@Test
@@ -303,13 +315,13 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Launch second activity to side
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.launch();
// Second activity must be on top now
- LifecycleVerifier.assertLaunchSequence(SingleTopActivity.class, getLifecycleLog());
+ assertLaunchSequence(SingleTopActivity.class, getTransitionLog());
}
@Test
@@ -326,14 +338,14 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Launch second activity to side
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
final Activity secondActivity = new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.launch();
// Switch top between two activities
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getPrimarySplitTaskId());
new Launcher(CallbackTrackingActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
@@ -342,13 +354,13 @@
waitAndAssertActivityStates(state(firstActivity, ON_TOP_POSITION_GAINED),
state(secondActivity, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class, getLifecycleLog(),
- Arrays.asList(ON_TOP_POSITION_GAINED), "switchTop");
- LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
- Arrays.asList(ON_TOP_POSITION_LOST), "switchTop");
+ assertSequence(CallbackTrackingActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_TOP_POSITION_GAINED), "switchTop");
+ assertSequence(SingleTopActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_TOP_POSITION_LOST), "switchTop");
// Switch top again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
@@ -357,9 +369,9 @@
waitAndAssertActivityStates(state(firstActivity, ON_TOP_POSITION_LOST),
state(secondActivity, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class, getLifecycleLog(),
- Arrays.asList(ON_TOP_POSITION_LOST), "switchTop");
- LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
+ assertSequence(CallbackTrackingActivity.class, getTransitionLog(),
+ Collections.singletonList(ON_TOP_POSITION_LOST), "switchTop");
+ assertSequence(SingleTopActivity.class, getTransitionLog(),
Arrays.asList(ON_PAUSE, ON_NEW_INTENT, ON_RESUME, ON_TOP_POSITION_GAINED),
"switchTop");
}
@@ -370,7 +382,7 @@
launchActivityAndWait(SingleTopActivity.class);
// Launch the activity again to observe new intent
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
.setNoInstance()
@@ -392,7 +404,7 @@
waitAndAssertActivityStates(state(singleTopActivity, ON_STOP));
// Launch the single top activity again to observe new intent
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP)
.setNoInstance()
@@ -400,7 +412,7 @@
waitAndAssertActivityStates(state(topActivity, ON_DESTROY));
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_PAUSE),
transition(SingleTopActivity.class, ON_RESTART),
@@ -410,7 +422,7 @@
transition(SingleTopActivity.class, ON_TOP_POSITION_GAINED),
transition(CallbackTrackingActivity.class, ON_STOP),
transition(CallbackTrackingActivity.class, ON_DESTROY)),
- getLifecycleLog(), "Single top resolution sequence must match");
+ getTransitionLog(), "Single top resolution sequence must match");
}
@Test
@@ -424,7 +436,7 @@
waitAndAssertActivityStates(state(singleTopActivity, ON_PAUSE));
// Launch the single top activity again to observe new intent
- getLifecycleLog().clear();
+ getTransitionLog().clear();
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP)
.setNoInstance()
@@ -432,7 +444,7 @@
waitAndAssertActivityStates(state(topActivity, ON_DESTROY));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(TranslucentCallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(TranslucentCallbackTrackingActivity.class, ON_PAUSE),
transition(SingleTopActivity.class, ON_NEW_INTENT),
@@ -446,12 +458,11 @@
final Activity topActivity = launchActivityAndWait(CallbackTrackingActivity.class);
// Press HOME and verify the lifecycle
- getLifecycleLog().clear();
+ getTransitionLog().clear();
pressHomeButton();
waitAndAssertActivityStates(state(topActivity, ON_STOP));
- LifecycleVerifier.assertResumeToStopSequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertResumeToStopSequence(CallbackTrackingActivity.class, getTransitionLog());
}
@Test
@@ -468,37 +479,37 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Launch second activity to side
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
final Activity secondActivity = new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.launch();
// Tap on first activity to switch the focus
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task dockedTask = getRootTaskForLeafTaskId(firstActivity.getTaskId());
tapOnTaskCenter(dockedTask);
// Wait and assert focus switch
waitAndAssertActivityStates(state(firstActivity, ON_TOP_POSITION_GAINED),
state(secondActivity, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(SingleTopActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED)),
- getLifecycleLog(), "Single top resolution sequence must match");
+ getTransitionLog(), "Single top resolution sequence must match");
// Tap on second activity to switch the focus again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task sideTask = getRootTaskForLeafTaskId(secondActivity.getTaskId());
tapOnTaskCenter(sideTask);
// Wait and assert focus switch
waitAndAssertActivityStates(state(firstActivity, ON_TOP_POSITION_LOST),
state(secondActivity, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(SingleTopActivity.class, ON_TOP_POSITION_GAINED)),
- getLifecycleLog(), "Single top resolution sequence must match");
+ getTransitionLog(), "Single top resolution sequence must match");
}
@Test
@@ -521,7 +532,7 @@
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
// Launch second activity to side
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
final Class<? extends Activity> secondActivityClass =
SecondProcessCallbackTrackingActivity.class;
@@ -538,27 +549,27 @@
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED));
// Tap on first activity to switch the top resumed one
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task dockedTask = getRootTaskForLeafTaskId(firstActivity.getTaskId());
tapOnTaskCenter(dockedTask);
// Wait and assert top resumed position switch
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_LOST),
state(firstActivityClass, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_LOST),
transition(firstActivityClass, ON_TOP_POSITION_GAINED)),
"tapOnTask");
// Tap on second activity to switch the top resumed activity again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task sideTask = mWmState.getTaskByActivity(secondActivityComponent);
tapOnTaskCenter(sideTask);
// Wait and assert top resumed position switch
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED),
state(firstActivityClass, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(firstActivityClass, ON_TOP_POSITION_LOST),
transition(secondActivityClass, ON_TOP_POSITION_GAINED)),
"tapOnTask");
@@ -584,7 +595,7 @@
moveTaskToPrimarySplitScreenAndVerify(slowActivity, sideActivity);
// Launch second activity to side
- getLifecycleLog().clear();
+ getTransitionLog().clear();
mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
final Class<? extends Activity> secondActivityClass =
SecondProcessCallbackTrackingActivity.class;
@@ -601,20 +612,20 @@
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED));
// Tap on first activity to switch the top resumed one
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task dockedTask = getRootTaskForLeafTaskId(slowActivity.getTaskId());
tapOnTaskCenter(dockedTask);
// Wait and assert top resumed position switch.
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_LOST),
state(slowActivityClass, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_LOST),
transition(slowActivityClass, ON_TOP_POSITION_GAINED)),
"tapOnTask");
// Tap on second activity to switch the top resumed activity again
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task sideTask = mWmState
.getTaskByActivity(secondActivityComponent);
tapOnTaskCenter(sideTask);
@@ -623,18 +634,18 @@
// be reported to the first activity before second will finish handling it.
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED),
state(slowActivityClass, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_GAINED),
transition(slowActivityClass, ON_TOP_POSITION_LOST)),
"tapOnTask");
// Wait 5 seconds more to make sure that no new messages received after top resumed state
// released by the slow activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
Thread.sleep(5000);
- LifecycleVerifier.assertEmptySequence(slowActivityClass, getLifecycleLog(),
+ assertEmptySequence(slowActivityClass, getTransitionLog(),
"topStateLossTimeout");
- LifecycleVerifier.assertEmptySequence(secondActivityClass, getLifecycleLog(),
+ assertEmptySequence(secondActivityClass, getTransitionLog(),
"topStateLossTimeout");
}
@@ -642,11 +653,11 @@
public void testTopPositionPreservedOnLocalRelaunch() throws Exception {
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
getInstrumentation().runOnMainSync(activity::recreate);
waitAndAssertActivityStates(state(activity, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertRelaunchSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertRelaunchSequence(CallbackTrackingActivity.class, getTransitionLog(),
ON_TOP_POSITION_GAINED);
}
@@ -661,23 +672,21 @@
.setExpectedState(ON_STOP)
.setNoInstance()
.launch();
- LifecycleVerifier.assertLaunchAndStopSequence(CallbackTrackingActivity.class,
- getLifecycleLog(), true /* onTop */);
+ assertLaunchAndStopSequence(CallbackTrackingActivity.class, getTransitionLog(),
+ true /* onTop */);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
}
// Lock screen removed - activity should be on top now
if (isCar()) {
- LifecycleVerifier.assertStopToResumeSubSequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertStopToResumeSubSequence(CallbackTrackingActivity.class, getTransitionLog());
waitAndAssertActivityCurrentState(CallbackTrackingActivity.class,
ON_TOP_POSITION_GAINED);
} else {
waitAndAssertActivityStates(
state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertStopToResumeSequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertStopToResumeSequence(CallbackTrackingActivity.class, getTransitionLog());
}
}
@@ -687,26 +696,26 @@
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
- getLifecycleLog().clear();
+ getTransitionLog().clear();
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.setLockCredential().gotoKeyguard();
waitAndAssertActivityStates(state(activity, ON_STOP));
- LifecycleVerifier.assertResumeToStopSequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertResumeToStopSequence(CallbackTrackingActivity.class,
+ getTransitionLog());
- getLifecycleLog().clear();
+ getTransitionLog().clear();
}
// Lock screen removed - activity should be on top now
if (isCar()) {
- LifecycleVerifier.assertStopToResumeSubSequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertStopToResumeSubSequence(CallbackTrackingActivity.class,
+ getTransitionLog());
waitAndAssertActivityCurrentState(activity.getClass(), ON_TOP_POSITION_GAINED);
} else {
waitAndAssertActivityStates(state(activity, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertStopToResumeSequence(CallbackTrackingActivity.class,
- getLifecycleLog());
+ assertStopToResumeSequence(CallbackTrackingActivity.class,
+ getTransitionLog());
}
}
@@ -725,21 +734,21 @@
.launch();
// TODO(b/123432490): Fix extra pause/resume
- LifecycleVerifier.assertSequence(ShowWhenLockedCallbackTrackingActivity.class,
- getLifecycleLog(),
+ assertSequence(ShowWhenLockedCallbackTrackingActivity.class,
+ getTransitionLog(),
Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_RESUME,
ON_TOP_POSITION_GAINED),
"launchAboveKeyguard");
- getLifecycleLog().clear();
+ getTransitionLog().clear();
}
// When the lock screen is removed, the ShowWhenLocked activity will be dismissed using the
// back button, which should finish the activity.
waitAndAssertActivityStates(state(showWhenLockedActivity, ON_DESTROY));
- LifecycleVerifier.assertResumeToDestroySequence(
- ShowWhenLockedCallbackTrackingActivity.class, getLifecycleLog());
+ assertResumeToDestroySequence(
+ ShowWhenLockedCallbackTrackingActivity.class, getTransitionLog());
}
@Test
@@ -757,7 +766,7 @@
waitAndAssertTopResumedActivity(getComponentName(CallbackTrackingActivity.class),
DEFAULT_DISPLAY, "Activity launched on default display must be focused");
waitAndAssertActivityTransitions(CallbackTrackingActivity.class,
- LifecycleVerifier.getLaunchSequence(CallbackTrackingActivity.class), "launch");
+ getLaunchSequence(CallbackTrackingActivity.class), "launch");
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new simulated display
@@ -765,7 +774,7 @@
= virtualDisplaySession.setSimulateDisplay(true).createDisplay();
// Launch another activity on new secondary display.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
launchOptions.setLaunchDisplayId(newDisplay.mId);
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
@@ -775,20 +784,19 @@
newDisplay.mId, "Activity launched on secondary display must be focused");
waitAndAssertActivityTransitions(SingleTopActivity.class,
- LifecycleVerifier.getLaunchSequence(SingleTopActivity.class), "launch");
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ getLaunchSequence(SingleTopActivity.class), "launch");
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(SingleTopActivity.class, ON_TOP_POSITION_GAINED)),
"launchOnOtherDisplay");
- getLifecycleLog().clear();
+ getTransitionLog().clear();
}
// Secondary display was removed - activity will be moved to the default display
waitForActivityTransitions(SingleTopActivity.class,
- LifecycleVerifier.getRelaunchSequence(
- ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ getRelaunchSequence(ON_TOP_POSITION_GAINED));
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(SingleTopActivity.class, ON_TOP_POSITION_LOST),
transition(SingleTopActivity.class, ON_TOP_POSITION_GAINED)),
"hostingDisplayRemoved");
@@ -815,7 +823,7 @@
.createDisplay();
// Launch another activity on new secondary display.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
launchOptions.setLaunchDisplayId(newDisplay.mId);
new Launcher(SingleTopActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK)
@@ -824,7 +832,7 @@
waitAndAssertTopResumedActivity(getComponentName(SingleTopActivity.class),
newDisplay.mId, "Activity launched on secondary display must be focused");
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Tap on task center to switch the top activity.
final Task callbackTrackingTask = mWmState
@@ -836,12 +844,12 @@
Arrays.asList(ON_TOP_POSITION_LOST), "tapOnFocusSwitch");
waitAndAssertActivityTransitions(CallbackTrackingActivity.class,
Arrays.asList(ON_TOP_POSITION_GAINED), "tapOnFocusSwitch");
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(SingleTopActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED)),
- getLifecycleLog(), "Top activity must be switched on tap");
+ getTransitionLog(), "Top activity must be switched on tap");
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Tap on task center to switch the top activity.
final Task singleTopActivityTask = mWmState
@@ -854,10 +862,10 @@
Arrays.asList(ON_TOP_POSITION_LOST), "tapOnFocusSwitch");
waitAndAssertActivityTransitions(SingleTopActivity.class,
Arrays.asList(ON_TOP_POSITION_GAINED), "tapOnFocusSwitch");
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
+ assertEntireSequence(Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(SingleTopActivity.class, ON_TOP_POSITION_GAINED)),
- getLifecycleLog(), "Top activity must be switched on tap");
+ getTransitionLog(), "Top activity must be switched on tap");
}
@Test
@@ -883,7 +891,7 @@
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED));
// Launch activity on default display, which will be slow to release top position.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final ActivityOptions launchOptions = ActivityOptions.makeBasic();
launchOptions.setLaunchDisplayId(DEFAULT_DISPLAY);
final Class<? extends Activity> defaultActivityClass = SlowActivity.class;
@@ -899,13 +907,13 @@
// Wait and assert focus switch
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_LOST),
state(defaultActivityClass, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_LOST),
transition(defaultActivityClass, ON_TOP_POSITION_GAINED)),
"launchOnDifferentDisplay");
// Tap on task center to switch the top activity.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final Task secondActivityTask = mWmState
.getTaskByActivity(getComponentName(SecondProcessCallbackTrackingActivity.class));
tapOnTaskCenter(secondActivityTask);
@@ -913,12 +921,12 @@
// Wait and assert top resumed position switch.
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED),
state(defaultActivityClass, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(defaultActivityClass, ON_TOP_POSITION_LOST),
transition(secondActivityClass, ON_TOP_POSITION_GAINED)),
"tapOnDifferentDisplay");
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Tap on task center to switch the top activity.
final Task defaultActivityTask = mWmState
.getTaskByActivity(getComponentName(defaultActivityClass));
@@ -927,7 +935,7 @@
// Wait and assert top resumed position switch.
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_LOST),
state(defaultActivityClass, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_LOST),
transition(defaultActivityClass, ON_TOP_POSITION_GAINED)),
"tapOnDifferentDisplay");
@@ -956,7 +964,7 @@
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED));
// Launch activity on default display, which will be slow to release top position.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final ActivityOptions launchOptions = ActivityOptions.makeBasic();
launchOptions.setLaunchDisplayId(DEFAULT_DISPLAY);
final Class<? extends Activity> defaultActivityClass = SlowActivity.class;
@@ -972,31 +980,31 @@
// Wait and assert focus switch.
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_LOST),
state(defaultActivityClass, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_LOST),
transition(defaultActivityClass, ON_TOP_POSITION_GAINED)),
"launchOnDifferentDisplay");
// Tap on secondary display to switch the top activity.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
tapOnDisplayCenter(newDisplay.mId);
// Wait and assert top resumed position switch. Because of timeout top position gain
// will appear before top position loss handling is finished.
waitAndAssertActivityStates(state(secondActivityClass, ON_TOP_POSITION_GAINED),
state(defaultActivityClass, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(secondActivityClass, ON_TOP_POSITION_GAINED),
transition(defaultActivityClass, ON_TOP_POSITION_LOST)),
"tapOnDifferentDisplay");
// Wait 5 seconds more to make sure that no new messages received after top resumed state
// released by the slow activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
SystemClock.sleep(5000);
- LifecycleVerifier.assertEmptySequence(defaultActivityClass, getLifecycleLog(),
+ assertEmptySequence(defaultActivityClass, getTransitionLog(),
"topStateLossTimeout");
- LifecycleVerifier.assertEmptySequence(secondActivityClass, getLifecycleLog(),
+ assertEmptySequence(secondActivityClass, getTransitionLog(),
"topStateLossTimeout");
}
@@ -1021,7 +1029,7 @@
.createDisplay();
// Launch another activity on new secondary display.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final ActivityOptions launchOptions = ActivityOptions.makeBasic();
launchOptions.setLaunchDisplayId(newDisplay.mId);
new Launcher(SingleTopActivity.class)
@@ -1032,18 +1040,18 @@
newDisplay.mId, "Activity launched on secondary display must be focused");
// An activity is launched on the new display, so the activity on default display should
// lose the top state.
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertSequence(CallbackTrackingActivity.class, getTransitionLog(),
Arrays.asList(ON_TOP_POSITION_LOST), "launchFocusSwitch");
// Finish the activity on the default display.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
callbackTrackingActivity.finish();
// Verify that activity was actually destroyed.
waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_DESTROY));
// Verify that the original focused display is not affected by the finished activity on
// non-focused display.
- LifecycleVerifier.assertEmptySequence(SingleTopActivity.class, getLifecycleLog(),
+ assertEmptySequence(SingleTopActivity.class, getTransitionLog(),
"destructionOnDifferentDisplay");
}
@@ -1065,7 +1073,7 @@
.createDisplay();
// Launch another activity on new secondary display.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
final ActivityOptions launchOptions = ActivityOptions.makeBasic();
launchOptions.setLaunchDisplayId(newDisplay.mId);
new Launcher(SingleTopActivity.class)
@@ -1082,14 +1090,14 @@
waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
// Finish the focused activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
callbackTrackingActivity.finish();
// Verify that lifecycle of the activity on a different display did not change.
// Top resumed state will be given to home activity on that display.
waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_DESTROY),
state(SecondActivity.class, ON_RESUME));
- LifecycleVerifier.assertEmptySequence(SingleTopActivity.class, getLifecycleLog(),
+ assertEmptySequence(SingleTopActivity.class, getTransitionLog(),
"destructionOnDifferentDisplay");
}
@@ -1101,7 +1109,7 @@
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
// Clear the log before launching to Pip
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Launch Pip-capable activity and enter Pip immediately
final Activity pipActivity = new Launcher(PipActivity.class)
@@ -1123,21 +1131,21 @@
, "wait PipMenuActivity lost top focus");
waitAndAssertActivityStates(state(activity, ON_TOP_POSITION_GAINED));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_PAUSE),
transition(CallbackTrackingActivity.class, ON_RESUME),
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED)), "startPIP");
// Exit PiP
- getLifecycleLog().clear();
+ getTransitionLog().clear();
pipActivity.finish();
waitAndAssertActivityStates(state(pipActivity, ON_DESTROY));
- LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
+ assertSequence(PipActivity.class, getTransitionLog(),
Arrays.asList(
ON_STOP, ON_DESTROY), "finishPip");
- LifecycleVerifier.assertEmptySequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ assertEmptySequence(CallbackTrackingActivity.class, getTransitionLog(),
"finishPip");
}
@@ -1149,7 +1157,7 @@
final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
// Clear the log before launching to Pip
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Launch Pip-capable activity and enter Pip immediately
final Activity pipActivity = new Launcher(PipActivity.class)
@@ -1165,20 +1173,20 @@
launchActivityAndWait(AlwaysFocusablePipActivity.class);
waitAndAssertActivityStates(state(pipActivity, ON_STOP),
state(activity, ON_TOP_POSITION_LOST));
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
transition(AlwaysFocusablePipActivity.class, ON_TOP_POSITION_GAINED)),
"launchAlwaysFocusablePip");
// Finish always focusable activity - top position should go back to fullscreen activity
- getLifecycleLog().clear();
+ getTransitionLog().clear();
alwaysFocusableActivity.finish();
waitAndAssertActivityStates(state(alwaysFocusableActivity, ON_DESTROY),
state(activity, ON_TOP_POSITION_GAINED), state(pipActivity, ON_PAUSE));
- LifecycleVerifier.assertResumeToDestroySequence(AlwaysFocusablePipActivity.class,
- getLifecycleLog());
- LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
+ assertResumeToDestroySequence(AlwaysFocusablePipActivity.class,
+ getTransitionLog());
+ assertOrder(getTransitionLog(), Arrays.asList(
transition(AlwaysFocusablePipActivity.class, ON_TOP_POSITION_LOST),
transition(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED)),
"finishAlwaysFocusablePip");
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java
index 95c9c4a..7888595 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java
@@ -98,7 +98,7 @@
// Navigate home
launchHomeActivity();
waitAndAssertActivityStates(state(FirstActivity.class, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
// Start activity again with flags in question. Verify activity is resumed.
// A new instance of activity will be created, and the old one destroyed.
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
index 7f42519..5739935 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
@@ -27,7 +27,12 @@
import static android.server.wm.lifecycle.LifecycleConstants.ON_STOP;
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_GAINED;
import static android.server.wm.lifecycle.LifecycleConstants.ON_TOP_POSITION_LOST;
-import static android.server.wm.lifecycle.LifecycleVerifier.transition;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEmptySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertEntireSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchAndDestroySequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertLaunchSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.assertSequence;
+import static android.server.wm.lifecycle.TransitionVerifier.transition;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -40,6 +45,7 @@
import org.junit.Test;
import java.util.Arrays;
+import java.util.Collections;
/**
* Tests for {@link Activity} class APIs.
@@ -56,10 +62,9 @@
final Activity activity = launchActivityAndWait(FirstActivity.class);
waitAndAssertActivityStates(state(activity, ON_RESUME));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
assertFalse("Launched and visible activity must be released", activity.releaseInstance());
- LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(),
- "tryReleaseInstance");
+ assertEmptySequence(FirstActivity.class, getTransitionLog(), "tryReleaseInstance");
}
@Test
@@ -71,18 +76,18 @@
mWmState.waitForActivityState(firstActivity.getComponentName(), STATE_STOPPED);
// Release the instance of the non-visible activity below.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
assertTrue("It must be possible to release an instance of an invisible activity",
firstActivity.releaseInstance());
waitAndAssertActivityStates(state(firstActivity, ON_DESTROY));
- LifecycleVerifier.assertEmptySequence(SecondActivity.class, getLifecycleLog(),
+ assertEmptySequence(SecondActivity.class, getTransitionLog(),
"releaseInstance");
// Finish the top activity to navigate back to the first one and re-create it.
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondActivity.finish();
waitAndAssertActivityStates(state(secondActivity, ON_DESTROY));
- LifecycleVerifier.assertLaunchSequence(FirstActivity.class, getLifecycleLog());
+ assertLaunchSequence(FirstActivity.class, getTransitionLog());
}
/**
@@ -98,16 +103,16 @@
waitAndAssertActivityStates(state(rootActivity, ON_STOP),
state(topActivity, ON_TOP_POSITION_GAINED));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
rootActivity.finishAndRemoveTask();
waitAndAssertActivityStates(state(rootActivity, ON_DESTROY),
state(topActivity, ON_DESTROY));
// Cannot guarantee exact sequence among top and bottom activities, so verifying
// independently
- LifecycleVerifier.assertSequence(rootActivityClass, getLifecycleLog(),
- Arrays.asList(ON_DESTROY), "finishAndRemoveTask");
- LifecycleVerifier.assertSequence(topActivityClass, getLifecycleLog(),
+ assertSequence(rootActivityClass, getTransitionLog(),
+ Collections.singletonList(ON_DESTROY), "finishAndRemoveTask");
+ assertSequence(topActivityClass, getTransitionLog(),
Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY),
"finishAndRemoveTask");
}
@@ -126,16 +131,16 @@
waitAndAssertActivityStates(state(rootActivity, ON_PAUSE),
state(topActivity, ON_TOP_POSITION_GAINED));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
rootActivity.finishAndRemoveTask();
waitAndAssertActivityStates(state(rootActivity, ON_DESTROY),
state(topActivity, ON_DESTROY));
// Cannot guarantee exact sequence among top and bottom activities, so verifying
// independently
- LifecycleVerifier.assertSequence(rootActivityClass, getLifecycleLog(),
+ assertSequence(rootActivityClass, getTransitionLog(),
Arrays.asList(ON_STOP, ON_DESTROY), "finishAndRemoveTask");
- LifecycleVerifier.assertSequence(topActivityClass, getLifecycleLog(),
+ assertSequence(topActivityClass, getTransitionLog(),
Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY),
"finishAndRemoveTask");
}
@@ -155,13 +160,12 @@
waitAndAssertActivityStates(state(rootActivity, ON_STOP), state(midActivity, ON_STOP),
state(topActivity, ON_TOP_POSITION_GAINED));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
midActivity.finishAndRemoveTask();
waitAndAssertActivityStates(state(midActivity, ON_DESTROY));
- LifecycleVerifier.assertEntireSequence(Arrays.asList(
- transition(midActivityClass, ON_DESTROY)), getLifecycleLog(),
- "finishAndRemoveTask");
+ assertEntireSequence(Collections.singletonList(transition(midActivityClass, ON_DESTROY)),
+ getTransitionLog(), "finishAndRemoveTask");
}
/**
@@ -171,16 +175,15 @@
@Test
public void testFinishAfterTransition() throws Exception {
final TransitionSourceActivity rootActivity =
- (TransitionSourceActivity) launchActivityAndWait(TransitionSourceActivity.class);
+ launchActivityAndWait(TransitionSourceActivity.class);
waitAndAssertActivityStates(state(rootActivity, ON_RESUME));
// Launch activity with configured shared element transition. It will call
// finishAfterTransition() on its own after transition completes.
- rootActivity.runOnUiThread(() -> rootActivity.launchActivityWithTransition());
+ rootActivity.runOnUiThread(rootActivity::launchActivityWithTransition);
waitAndAssertActivityStates(state(TransitionDestinationActivity.class, ON_DESTROY),
state(rootActivity, ON_RESUME));
- LifecycleVerifier.assertLaunchAndDestroySequence(TransitionDestinationActivity.class,
- getLifecycleLog());
+ assertLaunchAndDestroySequence(TransitionDestinationActivity.class, getTransitionLog());
}
/**
@@ -192,10 +195,10 @@
final Activity activity = launchActivityAndWait(FirstActivity.class);
waitAndAssertActivityStates(state(activity, ON_RESUME));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
activity.finishAfterTransition();
waitAndAssertActivityStates(state(FirstActivity.class, ON_DESTROY));
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
+ assertSequence(FirstActivity.class, getTransitionLog(),
Arrays.asList(ON_PAUSE, ON_STOP, ON_DESTROY), "finishAfterTransition");
}
@@ -209,10 +212,10 @@
final Activity topActivity = launchActivityAndWait(SecondActivity.class);
waitAndAssertActivityStates(state(topActivity, ON_RESUME), state(rootActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
topActivity.finishAfterTransition();
waitAndAssertActivityStates(state(SecondActivity.class, ON_DESTROY));
- LifecycleVerifier.assertSequence(SecondActivity.class, getLifecycleLog(),
+ assertSequence(SecondActivity.class, getTransitionLog(),
Arrays.asList(ON_PAUSE, ON_STOP, ON_DESTROY), "finishAfterTransition");
}
@@ -228,12 +231,11 @@
waitAndAssertActivityStates(state(thirdActivity, ON_RESUME), state(secondActivity, ON_STOP),
state(firstActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondActivity.finishAffinity();
waitAndAssertActivityStates(state(FirstActivity.class, ON_DESTROY),
state(SecondActivity.class, ON_DESTROY));
- LifecycleVerifier.assertEmptySequence(ThirdActivity.class, getLifecycleLog(),
- "finishAffinityBelow");
+ assertEmptySequence(ThirdActivity.class, getTransitionLog(), "finishAffinityBelow");
}
/**
@@ -249,10 +251,10 @@
waitAndAssertActivityStates(state(differentAffinityActivity, ON_RESUME),
state(firstActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
differentAffinityActivity.finishAffinity();
waitAndAssertActivityStates(state(DifferentAffinityActivity.class, ON_DESTROY));
- LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
+ assertSequence(FirstActivity.class, getTransitionLog(),
Arrays.asList(ON_RESTART, ON_START, ON_RESUME), "finishAffinity");
}
@@ -271,7 +273,7 @@
waitAndAssertActivityStates(state(secondActivity, ON_RESUME),
state(firstActivity, ON_STOP));
- getLifecycleLog().clear();
+ getTransitionLog().clear();
secondActivity.finishAffinity();
waitAndAssertActivityStates(state(SecondActivity.class, ON_DESTROY),
state(firstActivity, ON_RESUME));
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 c0f376e..e3792ae 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
@@ -238,7 +238,7 @@
private static final int UI_MODE_TYPE_MASK = 0x0f;
private static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
- static final boolean ENABLE_SHELL_TRANSITIONS =
+ public static final boolean ENABLE_SHELL_TRANSITIONS =
SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
private static Boolean sHasHomeScreen = null;
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index 8585638..adf308d 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -1672,6 +1672,7 @@
public boolean translucent;
private WindowContainer mParent;
private boolean mEnableRecentsScreenshot;
+ private int mLastDropInputMode;
Activity(ActivityRecordProto proto, WindowContainer parent) {
super(proto.windowToken.windowContainer);
@@ -1687,6 +1688,7 @@
}
translucent = proto.translucent;
mEnableRecentsScreenshot = proto.enableRecentsScreenshot;
+ mLastDropInputMode = proto.lastDropInputMode;
mParent = parent;
}
@@ -1730,6 +1732,10 @@
return mEnableRecentsScreenshot;
}
+ public int getLastDropInputMode() {
+ return mLastDropInputMode;
+ }
+
@Override
public Rect getBounds() {
if (mBounds == null) {
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 c6d96f4..e957e94 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
@@ -735,7 +735,8 @@
final List<Task> tasks = getRootTasks();
for (Task task : tasks) {
task.forAllTasks((t) -> assertWithMessage("Empty task was found, id = " + t.mTaskId)
- .that(t.mTasks.size() + t.mActivities.size()).isGreaterThan(0));
+ .that(t.mTasks.size() + t.mTaskFragments.size() + t.mActivities.size())
+ .isGreaterThan(0));
if (task.isLeafTask()) {
continue;
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/CallbackTrackingActivity.java b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/CallbackTrackingActivity.java
index 8666b61..3316c81 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/CallbackTrackingActivity.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/CallbackTrackingActivity.java
@@ -36,32 +36,32 @@
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- mLifecycleLogClient.onActivityCallback(ON_ACTIVITY_RESULT);
+ mEventLogClient.onCallback(ON_ACTIVITY_RESULT);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
- mLifecycleLogClient.onActivityCallback(ON_POST_CREATE);
+ mEventLogClient.onCallback(ON_POST_CREATE);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
- mLifecycleLogClient.onActivityCallback(ON_NEW_INTENT);
+ mEventLogClient.onCallback(ON_NEW_INTENT);
setIntent(intent);
}
@Override
public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
if (!getIntent().getBooleanExtra(EXTRA_SKIP_TOP_RESUMED_STATE, false)) {
- mLifecycleLogClient.onActivityCallback(
+ mEventLogClient.onCallback(
isTopResumedActivity ? ON_TOP_POSITION_GAINED : ON_TOP_POSITION_LOST);
}
}
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
- mLifecycleLogClient.onActivityCallback(ON_MULTI_WINDOW_MODE_CHANGED);
+ mEventLogClient.onCallback(ON_MULTI_WINDOW_MODE_CHANGED);
}
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleLog.java b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/EventLog.java
similarity index 76%
rename from tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleLog.java
rename to tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/EventLog.java
index 9b8dd43..a9e680b 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleLog.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/EventLog.java
@@ -33,17 +33,17 @@
import java.util.List;
/**
- * Used as a shared log storage of activity lifecycle transitions. Methods must be synchronized to
- * prevent concurrent modification of the log store.
+ * Used as a shared log storage of events such as activity lifecycle. Methods must be
+ * synchronized to prevent concurrent modification of the log store.
*/
-public class LifecycleLog extends ContentProvider {
+public class EventLog extends ContentProvider {
- interface LifecycleTrackerCallback {
- void onActivityLifecycleChanged();
+ interface EventTrackerCallback {
+ void onEventObserved();
}
/** Identifies the activity to which the event corresponds. */
- private static final String EXTRA_KEY_ACTIVITY = "key_activity";
+ private static final String EXTRA_KEY_TAG = "key_activity";
/** Puts a lifecycle or callback into the container. */
private static final String METHOD_ADD_CALLBACK = "add_callback";
/** Content provider URI for cross-process lifecycle transitions collecting. */
@@ -56,9 +56,9 @@
private static final List<Pair<String, String>> sLog = new ArrayList<>();
/**
- * Lifecycle tracker interface that waits for correct states or sequences.
+ * Event tracker interface that waits for correct states or sequences.
*/
- private static LifecycleTrackerCallback sLifecycleTracker;
+ private static EventTrackerCallback sEventTracker;
/** Clear the entire transition log. */
public void clear() {
@@ -67,8 +67,10 @@
}
}
- public void setLifecycleTracker(LifecycleTrackerCallback lifecycleTracker) {
- sLifecycleTracker = lifecycleTracker;
+ public void setEventTracker(EventTrackerCallback eventTracker) {
+ synchronized (sLog) {
+ sEventTracker = eventTracker;
+ }
}
/** Add activity callback to the log. */
@@ -78,8 +80,8 @@
}
log("Activity " + activityCanonicalName + " receiver callback " + callback);
// Trigger check for valid state in the tracker
- if (sLifecycleTracker != null) {
- sLifecycleTracker.onActivityLifecycleChanged();
+ if (sEventTracker != null) {
+ sEventTracker.onEventObserved();
}
}
@@ -109,28 +111,28 @@
// ContentProvider implementation for cross-process tracking
- public static class LifecycleLogClient implements AutoCloseable {
+ public static class EventLogClient implements AutoCloseable {
private static final String EMPTY_ARG = "";
private final ContentProviderClient mClient;
- private final String mOwner;
+ private final String mTag;
- public LifecycleLogClient(ContentProviderClient client, String owner) {
+ public EventLogClient(ContentProviderClient client, String tag) {
mClient = client;
- mOwner = owner;
+ mTag = tag;
}
- public void onActivityCallback(String callback) {
- onActivityCallback(callback, mOwner);
+ public void onCallback(String callback) {
+ onCallback(callback, mTag);
}
- public void onActivityCallback(String callback, Activity owner) {
- onActivityCallback(callback, owner.getClass().getCanonicalName());
+ public void onCallback(String callback, Activity activity) {
+ onCallback(callback, activity.getClass().getCanonicalName());
}
- public void onActivityCallback(String callback, String owner) {
+ public void onCallback(String callback, String tag) {
final Bundle extras = new Bundle();
extras.putString(METHOD_ADD_CALLBACK, callback);
- extras.putString(EXTRA_KEY_ACTIVITY, owner);
+ extras.putString(EXTRA_KEY_TAG, tag);
try {
mClient.call(METHOD_ADD_CALLBACK, EMPTY_ARG, extras);
} catch (RemoteException e) {
@@ -143,13 +145,13 @@
mClient.close();
}
- public static LifecycleLogClient create(String owner, Context context) {
+ public static EventLogClient create(String owner, Context context) {
final ContentProviderClient client = context.getContentResolver()
.acquireContentProviderClient(URI);
if (client == null) {
throw new RuntimeException("Unable to acquire " + URI);
}
- return new LifecycleLogClient(client, owner);
+ return new EventLogClient(client, owner);
}
}
@@ -158,7 +160,7 @@
if (!METHOD_ADD_CALLBACK.equals(method)) {
throw new UnsupportedOperationException();
}
- onActivityCallback(extras.getString(EXTRA_KEY_ACTIVITY), extras.getString(method));
+ onActivityCallback(extras.getString(EXTRA_KEY_TAG), extras.getString(method));
return null;
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTracker.java b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/EventTracker.java
similarity index 86%
rename from tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTracker.java
rename to tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/EventTracker.java
index 31bb9ae..fae5657 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTracker.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/EventTracker.java
@@ -29,13 +29,13 @@
* Gets notified about activity lifecycle updates and provides blocking mechanism to wait until
* expected activity states are reached.
*/
-public class LifecycleTracker implements LifecycleLog.LifecycleTrackerCallback {
+public class EventTracker implements EventLog.EventTrackerCallback {
private static final int TIMEOUT = 5 * 1000;
- private LifecycleLog mLifecycleLog;
+ private EventLog mEventLog;
- public LifecycleTracker(LifecycleLog lifecycleLog) {
- mLifecycleLog = lifecycleLog;
- mLifecycleLog.setLifecycleTracker(this);
+ public EventTracker(EventLog eventLog) {
+ mEventLog = eventLog;
+ mEventLog.setEventTracker(this);
}
void waitAndAssertActivityStates(
@@ -51,14 +51,14 @@
void waitAndAssertActivityCurrentState(Class<? extends Activity> activityClass,
String expectedState) {
final boolean waitResult = waitForConditionWithTimeout(() -> {
- List<String> activityLog = mLifecycleLog.getActivityLog(activityClass);
+ List<String> activityLog = mEventLog.getActivityLog(activityClass);
String currentState = activityLog.get(activityLog.size() - 1);
return expectedState.equals(currentState);
});
if (!waitResult) {
fail("Lifecycle state did not settle with the expected current state of "
- + expectedState + " : " + mLifecycleLog.getActivityLog(activityClass));
+ + expectedState + " : " + mEventLog.getActivityLog(activityClass));
}
}
@@ -71,11 +71,11 @@
public void waitForActivityTransitions(Class<? extends Activity> activityClass,
List<String> expectedTransitions) {
waitForConditionWithTimeout(
- () -> mLifecycleLog.getActivityLog(activityClass).equals(expectedTransitions));
+ () -> mEventLog.getActivityLog(activityClass).equals(expectedTransitions));
}
@Override
- public synchronized void onActivityLifecycleChanged() {
+ public synchronized void onEventObserved() {
notify();
}
@@ -88,7 +88,7 @@
for (Pair<Class<? extends Activity>, String> callbackPair : activityCallbacks) {
final Class<? extends Activity> activityClass = callbackPair.first;
final List<String> transitionList =
- mLifecycleLog.getActivityLog(activityClass);
+ mEventLog.getActivityLog(activityClass);
if (transitionList.isEmpty()
|| !transitionList.get(transitionList.size() - 1).equals(callbackPair.second)) {
// The activity either hasn't got any state transitions yet or the current state is
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTrackingActivity.java b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTrackingActivity.java
index f3ce34f..5c64485 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTrackingActivity.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleTrackingActivity.java
@@ -40,14 +40,14 @@
/** Base activity that only tracks fundamental activity lifecycle states. */
public class LifecycleTrackingActivity extends Activity {
- LifecycleLog.LifecycleLogClient mLifecycleLogClient;
+ EventLog.EventLogClient mEventLogClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mLifecycleLogClient = LifecycleLog.LifecycleLogClient.create(
+ mEventLogClient = EventLog.EventLogClient.create(
this.getClass().getCanonicalName(), this);
- mLifecycleLogClient.onActivityCallback(ON_CREATE);
+ mEventLogClient.onCallback(ON_CREATE);
final Intent intent = getIntent();
final Intent startOnCreate =
@@ -72,7 +72,7 @@
@Override
protected void onStart() {
super.onStart();
- mLifecycleLogClient.onActivityCallback(ON_START);
+ mEventLogClient.onCallback(ON_START);
if (getIntent().getBooleanExtra(EXTRA_FINISH_IN_ON_START, false)) {
finish();
@@ -82,7 +82,7 @@
@Override
protected void onResume() {
super.onResume();
- mLifecycleLogClient.onActivityCallback(ON_RESUME);
+ mEventLogClient.onCallback(ON_RESUME);
final Intent intent = getIntent();
if (intent.getBooleanExtra(EXTRA_FINISH_IN_ON_RESUME, false)) {
@@ -93,7 +93,7 @@
@Override
protected void onPause() {
super.onPause();
- mLifecycleLogClient.onActivityCallback(ON_PAUSE);
+ mEventLogClient.onCallback(ON_PAUSE);
if (getIntent().getBooleanExtra(EXTRA_FINISH_IN_ON_PAUSE, false)) {
finish();
@@ -103,7 +103,7 @@
@Override
protected void onStop() {
super.onStop();
- mLifecycleLogClient.onActivityCallback(ON_STOP);
+ mEventLogClient.onCallback(ON_STOP);
if (getIntent().getBooleanExtra(EXTRA_FINISH_IN_ON_STOP, false)) {
finish();
@@ -113,14 +113,14 @@
@Override
protected void onDestroy() {
super.onDestroy();
- mLifecycleLogClient.onActivityCallback(ON_DESTROY);
- mLifecycleLogClient.close();
+ mEventLogClient.onCallback(ON_DESTROY);
+ mEventLogClient.close();
}
@Override
protected void onRestart() {
super.onRestart();
- mLifecycleLogClient.onActivityCallback(ON_RESTART);
+ mEventLogClient.onCallback(ON_RESTART);
}
@Override
@@ -128,7 +128,7 @@
super.onUserLeaveHint();
if (getIntent().getBooleanExtra(EXTRA_ACTIVITY_ON_USER_LEAVE_HINT, false)) {
- mLifecycleLogClient.onActivityCallback(ON_USER_LEAVE_HINT);
+ mEventLogClient.onCallback(ON_USER_LEAVE_HINT);
}
}
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleVerifier.java b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/TransitionVerifier.java
similarity index 85%
rename from tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleVerifier.java
rename to tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/TransitionVerifier.java
index b9a6b66..db6a243 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/LifecycleVerifier.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/lifecycle/TransitionVerifier.java
@@ -41,17 +41,17 @@
import java.util.Arrays;
import java.util.List;
-/** Util class that verifies correct activity state transition sequences. */
-public class LifecycleVerifier {
+/** Util class that verifies correct event and state transition sequences. */
+public class TransitionVerifier {
private static final Class CALLBACK_TRACKING_CLASS = CallbackTrackingActivity.class;
private static final Class CONFIG_CHANGE_HANDLING_CLASS =
LifecycleConfigChangeHandlingActivity.class;
static void assertLaunchSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog, String... expectedSubsequentEvents) {
+ EventLog eventLog, String... expectedSubsequentEvents) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "launch");
@@ -81,7 +81,7 @@
}
static void assertLaunchSequence(Class<? extends Activity> launchingActivity,
- Class<? extends Activity> existingActivity, LifecycleLog lifecycleLog,
+ Class<? extends Activity> existingActivity, EventLog eventLog,
boolean launchingIsTranslucent) {
final boolean includingCallbacks;
if (CALLBACK_TRACKING_CLASS.isAssignableFrom(launchingActivity)
@@ -97,7 +97,7 @@
}
- final List<Pair<String, String>> observedTransitions = lifecycleLog.getLog();
+ final List<Pair<String, String>> observedTransitions = eventLog.getLog();
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(launchingActivity, "launch");
@@ -125,15 +125,15 @@
}
static void assertLaunchAndStopSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
- assertLaunchAndStopSequence(activityClass, lifecycleLog,
+ EventLog eventLog) {
+ assertLaunchAndStopSequence(activityClass, eventLog,
false /* onTop */);
}
static void assertLaunchAndStopSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog, boolean onTop) {
+ EventLog eventLog, boolean onTop) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "launch and stop");
@@ -153,9 +153,9 @@
}
static void assertLaunchAndPauseSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "launch and pause");
@@ -165,9 +165,9 @@
}
static void assertRestartSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "restart");
@@ -177,9 +177,9 @@
}
static void assertRestartAndResumeSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "restart and pause");
@@ -194,22 +194,22 @@
* state is resolved.
*/
static void assertRestartAndResumeSubSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final List<Pair<String, String>> expectedTransitions =
Arrays.asList(transition(activityClass, ON_RESTART),
transition(activityClass, ON_START), transition(activityClass, ON_RESUME));
- assertOrder(lifecycleLog, expectedTransitions, "restart and resume");
+ assertOrder(eventLog, expectedTransitions, "restart and resume");
}
static void assertRecreateAndResumeSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "recreateA and pause");
@@ -219,9 +219,9 @@
}
static void assertLaunchAndDestroySequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "launch and destroy");
@@ -231,9 +231,9 @@
}
static void assertResumeToDestroySequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "launch and destroy");
@@ -250,9 +250,9 @@
}
static void assertResumeToStopSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "resumed to stopped");
final boolean includeCallbacks = CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass);
@@ -268,9 +268,9 @@
}
static void assertStopToResumeSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, "stopped to resumed");
final boolean includeCallbacks = CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass);
@@ -290,9 +290,9 @@
* state is resolved.
*/
static void assertStopToResumeSubSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog) {
+ EventLog eventLog) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final boolean includeCallbacks = CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass);
@@ -303,13 +303,13 @@
expectedTransitions.add(transition(activityClass, ON_TOP_POSITION_GAINED));
}
- assertOrder(lifecycleLog, expectedTransitions, "stop and resume");
+ assertOrder(eventLog, expectedTransitions, "stop and resume");
}
static void assertRelaunchSequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog, String startState) {
+ EventLog eventLog, String startState) {
final List<String> expectedTransitions = getRelaunchSequence(startState);
- assertSequence(activityClass, lifecycleLog, expectedTransitions, "relaunch");
+ assertSequence(activityClass, eventLog, expectedTransitions, "relaunch");
}
static List<String> getRelaunchSequence(String startState) {
@@ -361,10 +361,10 @@
return newTransitions;
}
- static void assertSequence(Class<? extends Activity> activityClass, LifecycleLog lifecycleLog,
+ static void assertSequence(Class<? extends Activity> activityClass, EventLog eventLog,
List<String> expectedTransitions, String transition) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, transition);
@@ -378,13 +378,13 @@
* Use this method when there is no need to verify the entire sequence, only that some
* transitions happened after another.
*/
- static void assertOrder(LifecycleLog lifecycleLog, Class<? extends Activity> activityClass,
+ static void assertOrder(EventLog eventLog, Class<? extends Activity> activityClass,
List<String> expectedTransitionsOrder, String transition) {
List<Pair<String, String>> expectedTransitions = new ArrayList<>();
for (String callback : expectedTransitionsOrder) {
expectedTransitions.add(transition(activityClass, callback));
}
- assertOrder(lifecycleLog, expectedTransitions, transition);
+ assertOrder(eventLog, expectedTransitions, transition);
}
/**
@@ -394,10 +394,10 @@
* Use this method when there is no need to verify the entire sequence, only that some
* transitions happened after another.
*/
- public static void assertOrder(LifecycleLog lifecycleLog,
+ public static void assertOrder(EventLog eventLog,
List<Pair<String, String>> expectedTransitionsOrder,
String transition) {
- String result = checkOrderAndReturnError(lifecycleLog, expectedTransitionsOrder,
+ String result = checkOrderAndReturnError(eventLog, expectedTransitionsOrder,
transition);
if (result != null) {
fail(result);
@@ -405,12 +405,12 @@
}
/**
- * Same as {@link #assertOrder(LifecycleLog, List, String)}, but returns the String with error
+ * Same as {@link #assertOrder(EventLog, List, String)}, but returns the String with error
* if it occurs. Otherwise returns {@code null}
*/
- public static String checkOrderAndReturnError(LifecycleLog lifecycleLog,
+ public static String checkOrderAndReturnError(EventLog eventLog,
List<Pair<String, String>> expectedTransitionsOrder, String transition) {
- final List<Pair<String, String>> observedTransitions = lifecycleLog.getLog();
+ final List<Pair<String, String>> observedTransitions = eventLog.getLog();
int nextObservedPosition = 0;
for (Pair<String, String> expectedTransition
: expectedTransitionsOrder) {
@@ -429,42 +429,42 @@
/**
* Assert that a transition was observer, no particular order.
*/
- public static void assertTransitionObserved(LifecycleLog lifecycleLog,
+ public static void assertTransitionObserved(EventLog eventLog,
Pair<String, String> expectedTransition, String transition) {
assertTrue("Transition " + expectedTransition + " must be observed during " + transition,
- lifecycleLog.getLog().contains(expectedTransition));
+ eventLog.getLog().contains(expectedTransition));
}
/**
- * Same as {@link #checkOrderAndReturnError(LifecycleLog, List, String)}, but returns
+ * Same as {@link #checkOrderAndReturnError(EventLog, List, String)}, but returns
* {@code false} if the order does not match. Otherwise returns {@code true}
*/
- public static boolean checkOrder(LifecycleLog lifecycleLog,
+ public static boolean checkOrder(EventLog eventLog,
List<Pair<String, String>> expectedTransitionsOrder) {
- String result = checkOrderAndReturnError(lifecycleLog, expectedTransitionsOrder, null);
+ String result = checkOrderAndReturnError(eventLog, expectedTransitionsOrder, null);
return result == null;
}
/**
* Assert that a transition was not observer, no particular order.
*/
- static void assertTransitionNotObserved(LifecycleLog lifecycleLog,
+ static void assertTransitionNotObserved(EventLog eventLog,
Pair<String, String> expectedTransition, String transition) {
assertFalse("Transition " + expectedTransition + " must not be observed during "
- + transition, lifecycleLog.getLog().contains(expectedTransition));
+ + transition, eventLog.getLog().contains(expectedTransition));
}
static void assertEmptySequence(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog, String transition) {
- assertSequence(activityClass, lifecycleLog, new ArrayList<>(), transition);
+ EventLog eventLog, String transition) {
+ assertSequence(activityClass, eventLog, new ArrayList<>(), transition);
}
/** Assert that a lifecycle sequence matches one of the possible variants. */
static void assertSequenceMatchesOneOf(Class<? extends Activity> activityClass,
- LifecycleLog lifecycleLog, List<List<String>> expectedTransitions,
+ EventLog eventLog, List<List<String>> expectedTransitions,
String transition) {
final List<String> observedTransitions =
- lifecycleLog.getActivityLog(activityClass);
+ eventLog.getActivityLog(activityClass);
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(activityClass, transition);
@@ -483,8 +483,8 @@
/** Assert the entire sequence for all involved activities. */
static void assertEntireSequence(
List<Pair<String, String>> expectedTransitions,
- LifecycleLog lifecycleLog, String message) {
- final List<Pair<String, String>> observedTransitions = lifecycleLog.getLog();
+ EventLog eventLog, String message) {
+ final List<Pair<String, String>> observedTransitions = eventLog.getLog();
assertEquals(message, expectedTransitions, observedTransitions);
}
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
new file mode 100644
index 0000000..e1260e7
--- /dev/null
+++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediapc.cts;
+
+import static android.mediapc.cts.CodecTestBase.SELECT_ALL;
+import static android.mediapc.cts.CodecTestBase.SELECT_AUDIO;
+import static android.mediapc.cts.CodecTestBase.SELECT_HARDWARE;
+import static android.mediapc.cts.CodecTestBase.SELECT_VIDEO;
+import static android.mediapc.cts.CodecTestBase.getMimesOfAvailableCodecs;
+import static android.mediapc.cts.CodecTestBase.selectCodecs;
+import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.media.MediaRecorder;
+import android.mediapc.cts.common.Utils;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Surface;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+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.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The following test class validates the codec initialization latency (time for codec create +
+ * configure) for the audio codecs and hardware video codecs available in the device, under the
+ * load condition (Transcode + MediaRecorder session Audio(Microphone) and 1080p Video(Camera)).
+ */
+@RunWith(Parameterized.class)
+public class CodecInitializationLatencyTest {
+ private static final String LOG_TAG = CodecInitializationLatencyTest.class.getSimpleName();
+ private static final boolean[] boolStates = {false, true};
+ private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS = 50;
+ private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS = 65;
+ private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS = 40;
+ private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS = 50;
+ private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS = 30;
+ private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS = 40;
+ private static final int MAX_AUDIODEC_INITIALIZATION_LATENCY_PC_T_MS = 30;
+ private static final int MAX_VIDEODEC_INITIALIZATION_LATENCY_PC_T_MS = 40;
+
+ private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_MS;
+ private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
+ private static final int MAX_AUDIODEC_INITIALIZATION_LATENCY_MS;
+ private static final int MAX_VIDEODEC_INITIALIZATION_LATENCY_MS;
+ private static final String AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private static final String HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
+ private static final String AVC_TRANSCODE_FILE = "bbb_1280x720_3mbps_30fps_avc.mp4";
+ private static String AVC_DECODER_NAME;
+ private static String AVC_ENCODER_NAME;
+ private static final Map<String, String> mTestFiles = new HashMap<>();
+
+ static {
+ if (Utils.isRPerfClass()) {
+ MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS;
+ MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS;
+ } else if (Utils.isSPerfClass()) {
+ MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS;
+ MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS;
+ } else {
+ // Performance class Build.VERSION_CODES.TIRAMISU and beyond
+ MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS;
+ MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS;
+ }
+ if (Utils.isTPerfClass()) {
+ MAX_AUDIODEC_INITIALIZATION_LATENCY_MS = MAX_AUDIODEC_INITIALIZATION_LATENCY_PC_T_MS;
+ MAX_VIDEODEC_INITIALIZATION_LATENCY_MS = MAX_VIDEODEC_INITIALIZATION_LATENCY_PC_T_MS;
+ } else {
+ // no requirement below performance class Build.VERSION_CODES.TIRAMISU
+ MAX_AUDIODEC_INITIALIZATION_LATENCY_MS = Integer.MAX_VALUE;
+ MAX_VIDEODEC_INITIALIZATION_LATENCY_MS = Integer.MAX_VALUE;
+ }
+ // TODO(b/222006626): Add tests vectors for remaining media types
+ // Audio media types
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_stereo_48kHz_128kbps_aac.mp4");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_mono_8kHz_12.2kbps_amrnb.3gp");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_23kbps_amrwb.3gp");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_1ch_12kHz_lvl4_flac.mka");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_2ch_8kHz_alaw.wav");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_2ch_8kHz_mulaw.wav");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_2ch_48kHz_opus.mka");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_1ch_8kHz.wav");
+ mTestFiles.put(MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_stereo_48kHz_128kbps_vorbis.ogg");
+
+ // Video media types
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1920x1080_4mbps_30fps_av1.mp4");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1920x1080_6mbps_30fps_avc.mp4");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_H263, "bbb_cif_768kbps_30fps_h263.mp4");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1920x1080_4mbps_30fps_hevc.mp4");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_1920x1080_mpeg2_main_high.mp4");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_cif_768kbps_30fps_mpeg4.mkv");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_1920x1080_6mbps_30fps_vp8.webm");
+ mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1920x1080_4mbps_30fps_vp9.webm");
+ }
+
+ private final String mMime;
+ private final String mCodecName;
+
+ private LoadStatus mTranscodeLoadStatus = null;
+ private Thread mTranscodeLoadThread = null;
+ private MediaRecorder mMediaRecorderLoad = null;
+ private File mTempRecordedFile = null;
+ private Surface mSurface = null;
+ private Exception mException = null;
+
+ @Before
+ public void setUp() throws Exception {
+ Utils.assumeDeviceMeetsPerformanceClassPreconditions();
+
+ ArrayList<String> listOfAvcHwDecoders = selectHardwareCodecs(AVC, null, null, false);
+ assumeFalse("Test requires h/w avc decoder", listOfAvcHwDecoders.isEmpty());
+ AVC_DECODER_NAME = listOfAvcHwDecoders.get(0);
+
+ ArrayList<String> listOfAvcHwEncoders = selectHardwareCodecs(AVC, null, null, true);
+ assumeFalse("Test requires h/w avc encoder", listOfAvcHwEncoders.isEmpty());
+ AVC_ENCODER_NAME = listOfAvcHwEncoders.get(0);
+
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ Context context = instrumentation.getTargetContext();
+ PackageManager packageManager = context.getPackageManager();
+ assertNotNull(packageManager.getSystemAvailableFeatures());
+ assumeTrue("The device doesn't have a camera",
+ packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));
+ assumeTrue("The device doesn't have a microphone",
+ packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE));
+ createSurface();
+ startLoad();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ stopLoad();
+ releaseSurface();
+ }
+
+ public CodecInitializationLatencyTest(String mimeType, String codecName) {
+ mMime = mimeType;
+ mCodecName = codecName;
+ }
+
+ @Rule
+ public ActivityTestRule<TestActivity> mActivityRule =
+ new ActivityTestRule<>(TestActivity.class);
+
+ /**
+ * Returns the list of parameters with mimetype and their codecs(for audio - all codecs,
+ * video - hardware codecs).
+ *
+ * @return Collection of Parameters {0}_{1} -- MIME_CodecName
+ */
+ @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.
+ final List<Object[]> argsList = new ArrayList<>();
+ Set<String> mimeSet = getMimesOfAvailableCodecs(SELECT_VIDEO, SELECT_HARDWARE);
+ mimeSet.addAll(getMimesOfAvailableCodecs(SELECT_AUDIO, SELECT_ALL));
+ for (String mime : mimeSet) {
+ ArrayList<String> listOfCodecs;
+ if (mime.startsWith("audio/")) {
+ listOfCodecs = selectCodecs(mime, null, null, true);
+ listOfCodecs.addAll(selectCodecs(mime, null, null, false));
+ } else {
+ listOfCodecs = selectHardwareCodecs(mime, null, null, true);
+ listOfCodecs.addAll(selectHardwareCodecs(mime, null, null, false));
+ }
+ for (String codec : listOfCodecs) {
+ argsList.add(new Object[]{mime, codec});
+ }
+ }
+ return argsList;
+ }
+
+ private MediaRecorder createMediaRecorderLoad(Surface surface) throws Exception {
+ MediaRecorder mediaRecorder = new MediaRecorder(InstrumentationRegistry.getInstrumentation()
+ .getContext());
+ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+ mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+ mediaRecorder.setVideoEncoder(mMime.equalsIgnoreCase(HEVC) ?
+ MediaRecorder.VideoEncoder.HEVC : MediaRecorder.VideoEncoder.H264);
+ mediaRecorder.setOutputFile(mTempRecordedFile);
+ mediaRecorder.setVideoSize(1920, 1080);
+ mediaRecorder.setOrientationHint(0);
+ mediaRecorder.setPreviewDisplay(surface);
+ mediaRecorder.prepare();
+ return mediaRecorder;
+ }
+
+ private void startLoad() throws Exception {
+ // TODO: b/183671436
+ // Create Transcode load (AVC Decoder(720p) + AVC Encoder(720p))
+ mTranscodeLoadStatus = new LoadStatus();
+ mTranscodeLoadThread = new Thread(() -> {
+ try {
+ TranscodeLoad transcodeLoad = new TranscodeLoad(AVC, AVC_TRANSCODE_FILE,
+ AVC_DECODER_NAME, AVC_ENCODER_NAME, mTranscodeLoadStatus);
+ transcodeLoad.doTranscode();
+ } catch (Exception e) {
+ mException = e;
+ }
+ });
+ // Create MediaRecorder Session - Audio (Microphone) + 1080p Video (Camera)
+ // Create a temp file to dump the MediaRecorder output. Later it will be deleted.
+ mTempRecordedFile = new File(WorkDir.getMediaDirString() + "tempOut.mp4");
+ mTempRecordedFile.createNewFile();
+ mMediaRecorderLoad = createMediaRecorderLoad(mSurface);
+ // Start the Loads
+ mTranscodeLoadThread.start();
+ mMediaRecorderLoad.start();
+ }
+
+ private void stopLoad() throws Exception {
+ if (mTranscodeLoadStatus != null) {
+ mTranscodeLoadStatus.setLoadFinished();
+ mTranscodeLoadStatus = null;
+ }
+ if (mTranscodeLoadThread != null) {
+ mTranscodeLoadThread.join();
+ mTranscodeLoadThread = null;
+ }
+ if (mMediaRecorderLoad != null) {
+ // Note that a RuntimeException is intentionally thrown to the application, if no valid
+ // audio/video data has been received when stop() is called. This happens if stop() is
+ // called immediately after start(). So sleep for 1000ms inorder to make sure some
+ // data has been received between start() and stop().
+ Thread.sleep(1000);
+ mMediaRecorderLoad.stop();
+ mMediaRecorderLoad.release();
+ mMediaRecorderLoad = null;
+ if (mTempRecordedFile != null && mTempRecordedFile.exists()) {
+ mTempRecordedFile.delete();
+ mTempRecordedFile = null;
+ }
+ }
+ if (mException != null) throw mException;
+ }
+
+ private void createSurface() throws InterruptedException {
+ mActivityRule.getActivity().waitTillSurfaceIsCreated();
+ mSurface = mActivityRule.getActivity().getSurface();
+ assertNotNull("Surface created is null.", mSurface);
+ assertTrue("Surface created is invalid.", mSurface.isValid());
+ mActivityRule.getActivity().setScreenParams(1920, 1080, true);
+ }
+
+ private void releaseSurface() {
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
+ }
+ }
+
+ /**
+ * This test validates the initialization latency (time for codec create + configure) for
+ * audio and hw video codecs.
+ *
+ * <p>Measurements are taken 5 * 2(sync/async) * [1 or 2]
+ * (surface/non-surface for video) times. This also logs the stats: min, max, avg of the codec
+ * initialization latencies.
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ @CddTest(requirements = {
+ "2.2.7.1/5.1/H-1-7",
+ "2.2.7.1/5.1/H-1-8",})
+ public void testInitializationLatency() throws Exception {
+ MediaCodec codec = MediaCodec.createByCodecName(mCodecName);
+ boolean isEncoder = codec.getCodecInfo().isEncoder();
+ boolean isAudio = mMime.startsWith("audio/");
+ codec.release();
+ final int NUM_MEASUREMENTS = 5;
+ // Test gathers initialization latency for a number of iterations and
+ // percentile is a variable used to control how many of these iterations
+ // need to meet the pass criteria. For eg. if NUM_MEASUREMENTS = 5, audio, sync and Async
+ // modes which is a total of 10 iterations, this translates to index 7.
+ final int percentile = 70;
+ long expectedMaxCodecInitializationLatencyMs = isAudio ?
+ isEncoder ? MAX_AUDIOENC_INITIALIZATION_LATENCY_MS :
+ MAX_AUDIODEC_INITIALIZATION_LATENCY_MS :
+ isEncoder ? MAX_VIDEOENC_INITIALIZATION_LATENCY_MS :
+ MAX_VIDEODEC_INITIALIZATION_LATENCY_MS;
+ long sumOfCodecInitializationLatencyMs = 0;
+ int count = 0;
+ int numOfActualMeasurements =
+ NUM_MEASUREMENTS * boolStates.length * ((!isEncoder && !isAudio) ? 2 : 1);
+ long[] codecInitializationLatencyMs = new long[numOfActualMeasurements];
+ for (int i = 0; i < NUM_MEASUREMENTS; i++) {
+ for (boolean isAsync : boolStates) {
+ long latency;
+ if (isEncoder) {
+ EncoderInitializationLatency encoderInitializationLatency =
+ new EncoderInitializationLatency(mMime, mCodecName, isAsync);
+ latency = encoderInitializationLatency.calculateInitLatency();
+ codecInitializationLatencyMs[count] = latency;
+ sumOfCodecInitializationLatencyMs += latency;
+ count++;
+ } else {
+ String testFile = mTestFiles.get(mMime);
+ assumeTrue("Add test vector for media type: " + mMime, testFile != null);
+ if (isAudio) {
+ DecoderInitializationLatency decoderInitializationLatency =
+ new DecoderInitializationLatency(mMime, mCodecName, testFile,
+ isAsync, false);
+ latency = decoderInitializationLatency.calculateInitLatency();
+ codecInitializationLatencyMs[count] = latency;
+ sumOfCodecInitializationLatencyMs += latency;
+ count++;
+ } else {
+ for (boolean surfaceMode : boolStates) {
+ DecoderInitializationLatency decoderInitializationLatency =
+ new DecoderInitializationLatency(mMime, mCodecName,
+ testFile,
+ isAsync, surfaceMode);
+ latency = decoderInitializationLatency.calculateInitLatency();
+ codecInitializationLatencyMs[count] = latency;
+ sumOfCodecInitializationLatencyMs += latency;
+ count++;
+ }
+ }
+ }
+ }
+ }
+ Arrays.sort(codecInitializationLatencyMs);
+
+ String statsLog = String.format("CodecInitialization latency for mime: %s, " +
+ "Codec: %s, in Ms :: ", mMime, mCodecName);
+ Log.i(LOG_TAG, "Min " + statsLog + codecInitializationLatencyMs[0]);
+ Log.i(LOG_TAG, "Max " + statsLog + codecInitializationLatencyMs[count - 1]);
+ Log.i(LOG_TAG, "Avg " + statsLog + (sumOfCodecInitializationLatencyMs / count));
+ long initializationLatency = codecInitializationLatencyMs[percentile * count / 100];
+ if (Utils.isPerfClass()) {
+ String errorLog = String.format(
+ "CodecInitialization latency for mime: %s, Codec: %s is not as expected."
+ + "act/exp in Ms :: %d/%d", mMime, mCodecName, initializationLatency,
+ expectedMaxCodecInitializationLatencyMs);
+ assertTrue(errorLog, initializationLatency <= expectedMaxCodecInitializationLatencyMs);
+ } else {
+ int pc;
+ if (mMime.startsWith("audio/")) {
+ pc = initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS ?
+ Build.VERSION_CODES.TIRAMISU :
+ initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS ?
+ Build.VERSION_CODES.S : initializationLatency <
+ MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS ?
+ Build.VERSION_CODES.R : 0;
+ } else {
+ pc = initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS ?
+ Build.VERSION_CODES.TIRAMISU :
+ initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS ?
+ Build.VERSION_CODES.S : initializationLatency <
+ MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS ?
+ Build.VERSION_CODES.R : 0;
+ }
+ DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs",
+ "InitializationLatency_" + mCodecName);
+ log.addValue("codec", mCodecName, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("initialization_latency", initializationLatency, ResultType.LOWER_BETTER,
+ ResultUnit.NONE);
+ log.setSummary("CDD 2.2.7.1/5.1/H-1-7,H-1-8 performance_class", pc, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
+ /**
+ * The following class calculates the encoder initialization latency (time for codec create +
+ * configure).
+ *
+ * <p>And also logs the time taken by the encoder for:
+ * (create + configure + start),
+ * (create + configure + start + first frame to enqueue),
+ * (create + configure + start + first frame to dequeue).
+ */
+ static class EncoderInitializationLatency extends CodecEncoderTestBase {
+ private static final String LOG_TAG = EncoderInitializationLatency.class.getSimpleName();
+
+ private final String mEncoderName;
+ private final boolean mIsAsync;
+
+ EncoderInitializationLatency(String mime, String encoderName, boolean isAsync) {
+ super(mime);
+ mEncoderName = encoderName;
+ mIsAsync = isAsync;
+ mSampleRate = 8000;
+ mFrameRate = 60;
+ }
+
+ private MediaFormat setUpFormat() throws IOException {
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, mMime);
+ if (mIsAudio) {
+ if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+ format.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, 10000);
+ } else {
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
+ }
+ format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate);
+ format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+ } else {
+ MediaCodec codec = MediaCodec.createByCodecName(mEncoderName);
+ MediaCodecInfo.CodecCapabilities codecCapabilities =
+ codec.getCodecInfo().getCapabilitiesForType(mMime);
+ if (codecCapabilities.getVideoCapabilities().isSizeSupported(1920, 1080)) {
+ format.setInteger(MediaFormat.KEY_WIDTH, 1920);
+ format.setInteger(MediaFormat.KEY_HEIGHT, 1080);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 8000000);
+ } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(1280, 720)) {
+ format.setInteger(MediaFormat.KEY_WIDTH, 1280);
+ format.setInteger(MediaFormat.KEY_HEIGHT, 720);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 5000000);
+ } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(640, 480)) {
+ format.setInteger(MediaFormat.KEY_WIDTH, 640);
+ format.setInteger(MediaFormat.KEY_HEIGHT, 480);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
+ } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(352, 288)) {
+ format.setInteger(MediaFormat.KEY_WIDTH, 352);
+ format.setInteger(MediaFormat.KEY_HEIGHT, 288);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 512000);
+ } else {
+ format.setInteger(MediaFormat.KEY_WIDTH, 176);
+ format.setInteger(MediaFormat.KEY_HEIGHT, 144);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
+ }
+ codec.release();
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
+ format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+ MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
+ }
+ return format;
+ }
+
+ public long calculateInitLatency() throws Exception {
+ MediaFormat format = setUpFormat();
+ if (mIsAudio) {
+ mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ mChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ } else {
+ mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
+ mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+ }
+ setUpSource(mInputFile);
+ MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
+ long enqueueTimeStamp = 0;
+ long dequeueTimeStamp = 0;
+ long baseTimeStamp = System.nanoTime();
+ mCodec = MediaCodec.createByCodecName(mEncoderName);
+ resetContext(mIsAsync, false);
+ mAsyncHandle.setCallBack(mCodec, mIsAsync);
+ mCodec.configure(format, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
+ long configureTimeStamp = System.nanoTime();
+ mCodec.start();
+ long startTimeStamp = System.nanoTime();
+ if (mIsAsync) {
+ // We will keep on feeding the input to encoder until we see the first dequeued
+ // frame.
+ while (!mAsyncHandle.hasSeenError() && !mSawInputEOS) {
+ Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
+ if (element != null) {
+ int bufferID = element.first;
+ MediaCodec.BufferInfo info = element.second;
+ if (info != null) {
+ dequeueTimeStamp = System.nanoTime();
+ dequeueOutput(bufferID, info);
+ break;
+ } else {
+ if (enqueueTimeStamp == 0) {
+ enqueueTimeStamp = System.nanoTime();
+ }
+ enqueueInput(bufferID);
+ }
+ }
+ }
+ } else {
+ while (!mSawOutputEOS) {
+ if (!mSawInputEOS) {
+ int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
+ if (inputBufferId > 0) {
+ if (enqueueTimeStamp == 0) {
+ enqueueTimeStamp = System.nanoTime();
+ }
+ enqueueInput(inputBufferId);
+ }
+ }
+ int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
+ if (outputBufferId >= 0) {
+ dequeueTimeStamp = System.nanoTime();
+ dequeueOutput(outputBufferId, outInfo);
+ break;
+ }
+ }
+ }
+ queueEOS();
+ waitForAllOutputs();
+ mCodec.stop();
+ mCodec.release();
+ Log.d(LOG_TAG, "Encode Mime: " + mMime + " Encoder: " + mEncoderName +
+ " Time for (create + configure) in ns: " +
+ (configureTimeStamp - baseTimeStamp));
+ Log.d(LOG_TAG, "Encode Mime: " + mMime + " Encoder: " + mEncoderName +
+ " Time for (create + configure + start) in ns: " +
+ (startTimeStamp - baseTimeStamp));
+ Log.d(LOG_TAG, "Encode Mime: " + mMime + " Encoder: " + mEncoderName +
+ " Time for (create + configure + start + first frame to enqueue) in ns: " +
+ (enqueueTimeStamp - baseTimeStamp));
+ Log.d(LOG_TAG, "Encode Mime: " + mMime + " Encoder: " + mEncoderName +
+ " Time for (create + configure + start + first frame to dequeue) in ns: " +
+ (dequeueTimeStamp - baseTimeStamp));
+ long timeToConfigureMs = (configureTimeStamp - baseTimeStamp) / 1000000;
+ return timeToConfigureMs;
+ }
+ }
+
+ /**
+ * The following class calculates the decoder initialization latency (time for codec create +
+ * configure).
+ * And also logs the time taken by the decoder for:
+ * (create + configure + start),
+ * (create + configure + start + first frame to enqueue),
+ * (create + configure + start + first frame to dequeue).
+ */
+ static class DecoderInitializationLatency extends CodecDecoderTestBase {
+ private static final String LOG_TAG = DecoderInitializationLatency.class.getSimpleName();
+
+ private final String mDecoderName;
+ private final boolean mIsAsync;
+
+ DecoderInitializationLatency(String mediaType, String decoderName, String testFile,
+ boolean isAsync, boolean surfaceMode) {
+ super(mediaType, testFile);
+ mDecoderName = decoderName;
+ mIsAsync = isAsync;
+ mSurface = mIsAudio ? null :
+ surfaceMode ? MediaCodec.createPersistentInputSurface() : null;
+ }
+
+ public long calculateInitLatency() throws Exception {
+ MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
+ MediaFormat format = setUpSource(mTestFile);
+ long enqueueTimeStamp = 0;
+ long dequeueTimeStamp = 0;
+ long baseTimeStamp = System.nanoTime();
+ mCodec = MediaCodec.createByCodecName(mDecoderName);
+ resetContext(mIsAsync, false);
+ mAsyncHandle.setCallBack(mCodec, mIsAsync);
+ mCodec.configure(format, mSurface, 0, null);
+ long configureTimeStamp = System.nanoTime();
+ mCodec.start();
+ long startTimeStamp = System.nanoTime();
+ if (mIsAsync) {
+ // We will keep on feeding the input to decoder until we see the first dequeued
+ // frame.
+ while (!mAsyncHandle.hasSeenError() && !mSawInputEOS) {
+ Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
+ if (element != null) {
+ int bufferID = element.first;
+ MediaCodec.BufferInfo info = element.second;
+ if (info != null) {
+ dequeueTimeStamp = System.nanoTime();
+ dequeueOutput(bufferID, info);
+ break;
+ } else {
+ if (enqueueTimeStamp == 0) {
+ enqueueTimeStamp = System.nanoTime();
+ }
+ enqueueInput(bufferID);
+ }
+ }
+ }
+ } else {
+ while (!mSawOutputEOS) {
+ if (!mSawInputEOS) {
+ int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
+ if (inputBufferId >= 0) {
+ if (enqueueTimeStamp == 0) {
+ enqueueTimeStamp = System.nanoTime();
+ }
+ enqueueInput(inputBufferId);
+ }
+ }
+ int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
+ if (outputBufferId >= 0) {
+ dequeueTimeStamp = System.nanoTime();
+ dequeueOutput(outputBufferId, outInfo);
+ break;
+ }
+ }
+ }
+ queueEOS();
+ waitForAllOutputs();
+ mCodec.stop();
+ mCodec.release();
+ if (mSurface != null) {
+ mSurface.release();
+ }
+ Log.d(LOG_TAG, "Decode Mime: " + mMime + " Decoder: " + mDecoderName +
+ " Time for (create + configure) in ns: " +
+ (configureTimeStamp - baseTimeStamp));
+ Log.d(LOG_TAG, "Decode Mime: " + mMime + " Decoder: " + mDecoderName +
+ " Time for (create + configure + start) in ns: " +
+ (startTimeStamp - baseTimeStamp));
+ Log.d(LOG_TAG, "Decode Mime: " + mMime + " Decoder: " + mDecoderName +
+ " Time for (create + configure + start + first frame to enqueue) in ns: " +
+ (enqueueTimeStamp - baseTimeStamp));
+ Log.d(LOG_TAG, "Decode Mime: " + mMime + " Decoder: " + mDecoderName +
+ " Time for (create + configure + start + first frame to dequeue) in ns: " +
+ (dequeueTimeStamp - baseTimeStamp));
+ long timeToConfigureMs = (configureTimeStamp - baseTimeStamp) / 1000000;
+ return timeToConfigureMs;
+ }
+ }
+}
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
index c6a0c60..c75fffb 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
@@ -42,7 +42,9 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.LinkedList;
+import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@@ -178,6 +180,8 @@
static final int SELECT_ALL = 0; // Select all codecs
static final int SELECT_HARDWARE = 1; // Select Hardware codecs only
static final int SELECT_SOFTWARE = 2; // Select Software codecs only
+ static final int SELECT_AUDIO = 3; // Select Audio codecs only
+ static final int SELECT_VIDEO = 4; // Select Video codecs only
// Maintain Timeouts in sync with their counterpart in NativeMediaCommon.h
static final long Q_DEQ_TIMEOUT_US = 5000; // block at most 5ms while looking for io buffers
static final int RETRY_LIMIT = 100; // max poll counter before test aborts and returns error
@@ -339,12 +343,23 @@
static ArrayList<String> selectHardwareCodecs(String mime, ArrayList<MediaFormat> formats,
String[] features, boolean isEncoder) {
- return selectCodecs(mime, formats, features, isEncoder, SELECT_HARDWARE);
+ return selectHardwareCodecs(mime, formats, features, isEncoder, false);
+ }
+
+ static ArrayList<String> selectHardwareCodecs(String mime, ArrayList<MediaFormat> formats,
+ String[] features, boolean isEncoder, boolean allCodecs) {
+ return selectCodecs(mime, formats, features, isEncoder, SELECT_HARDWARE, allCodecs);
}
static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
String[] features, boolean isEncoder, int selectCodecOption) {
- MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ return selectCodecs(mime, formats, features, isEncoder, selectCodecOption, false);
+ }
+
+ static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
+ String[] features, boolean isEncoder, int selectCodecOption, boolean allCodecs) {
+ int kind = allCodecs ? MediaCodecList.ALL_CODECS : MediaCodecList.REGULAR_CODECS;
+ MediaCodecList codecList = new MediaCodecList(kind);
MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
ArrayList<String> listOfCodecs = new ArrayList<>();
for (MediaCodecInfo codecInfo : codecInfos) {
@@ -382,6 +397,31 @@
}
return listOfCodecs;
}
+
+ static Set<String> getMimesOfAvailableCodecs(int codecAV, int codecType) {
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+ Set<String> listOfMimes = new HashSet<>();
+ for (MediaCodecInfo codecInfo : codecInfos) {
+ if (codecType == SELECT_HARDWARE && !codecInfo.isHardwareAccelerated()) {
+ continue;
+ }
+ if (codecType == SELECT_SOFTWARE && !codecInfo.isSoftwareOnly()) {
+ continue;
+ }
+ String[] types = codecInfo.getSupportedTypes();
+ for (String type : types) {
+ if (codecAV == SELECT_AUDIO && !type.startsWith("audio/")) {
+ continue;
+ }
+ if (codecAV == SELECT_VIDEO && !type.startsWith("video/")) {
+ continue;
+ }
+ listOfMimes.add(type);
+ }
+ }
+ return listOfMimes;
+ }
}
class CodecDecoderTestBase extends CodecTestBase {
diff --git a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
deleted file mode 100644
index ae09b14..0000000
--- a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.mediapc.cts;
-
-import static android.mediapc.cts.CodecTestBase.selectCodecs;
-import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
-import android.media.MediaFormat;
-import android.media.MediaRecorder;
-import android.mediapc.cts.common.Utils;
-import android.os.Build;
-import android.util.Log;
-import android.util.Pair;
-import android.view.Surface;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.ActivityTestRule;
-
-import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.DeviceReportLog;
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-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.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * The following test class validates the codec initialization latency (time for codec create +
- * configure) for the audio encoders and hardware video encoders available in the device, under the
- * load condition (Transcode + MediaRecorder session Audio(Microphone) and 1080p Video(Camera)).
- */
-@RunWith(Parameterized.class)
-public class EncoderInitializationLatencyTest {
- private static final String LOG_TAG = EncoderInitializationLatencyTest.class.getSimpleName();
- private static final boolean[] boolStates = {false, true};
- private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS = 50;
- private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS = 65;
- private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS = 40;
- private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS = 50;
- private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS = 30;
- private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS = 40;
-
- private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_MS;
- private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
- private static final String AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final String HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
- private static final String AVC_TRANSCODE_FILE = "bbb_1280x720_3mbps_30fps_avc.mp4";
- private static String AVC_DECODER_NAME;
- private static String AVC_ENCODER_NAME;
-
- static {
- if (Utils.isRPerfClass()) {
- MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS;
- MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS;
- } else if (Utils.isSPerfClass()) {
- MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS;
- MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS;
- } else {
- // Performance class Build.VERSION_CODES.TIRAMISU and beyond
- MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS;
- MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS;
- }
- }
-
- private final String mMime;
- private final String mEncoderName;
-
- private LoadStatus mTranscodeLoadStatus = null;
- private Thread mTranscodeLoadThread = null;
- private MediaRecorder mMediaRecorderLoad = null;
- private File mTempRecordedFile = null;
- private Surface mSurface = null;
- private Exception mException = null;
-
- @Before
- public void setUp() throws Exception {
- Utils.assumeDeviceMeetsPerformanceClassPreconditions();
-
- ArrayList<String> listOfAvcHwDecoders = selectHardwareCodecs(AVC, null, null, false);
- assumeFalse("Test requires h/w avc decoder", listOfAvcHwDecoders.isEmpty());
- AVC_DECODER_NAME = listOfAvcHwDecoders.get(0);
-
- ArrayList<String> listOfAvcHwEncoders = selectHardwareCodecs(AVC, null, null, true);
- assumeFalse("Test requires h/w avc encoder", listOfAvcHwEncoders.isEmpty());
- AVC_ENCODER_NAME = listOfAvcHwEncoders.get(0);
-
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- Context context = instrumentation.getTargetContext();
- PackageManager packageManager = context.getPackageManager();
- assertNotNull(packageManager.getSystemAvailableFeatures());
- assumeTrue("The device doesn't have a camera",
- packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));
- assumeTrue("The device doesn't have a microphone",
- packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE));
- createSurface();
- startLoad();
- }
-
- @After
- public void tearDown() throws Exception {
- stopLoad();
- releaseSurface();
- }
-
- public EncoderInitializationLatencyTest(String mimeType, String encoderName) {
- mMime = mimeType;
- mEncoderName = encoderName;
- }
-
- @Rule
- public ActivityTestRule<TestActivity> mActivityRule =
- new ActivityTestRule<>(TestActivity.class);
-
- // Returns the list of all available hardware video encoders in the device.
- static ArrayList<String> getMimesOfAvailableHardwareVideoEncoders() {
- MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
- ArrayList<String> listOfMimes = new ArrayList<>();
- for (MediaCodecInfo codecInfo : codecInfos) {
- if (!codecInfo.isEncoder() || !codecInfo.isHardwareAccelerated()) continue;
- String[] types = codecInfo.getSupportedTypes();
- for (String type : types) {
- if (type.startsWith("video/") && !listOfMimes.contains(type)) {
- listOfMimes.add(type);
- }
- }
- }
- return listOfMimes;
- }
-
- // Returns the list of all available audio encoders in the device.
- static ArrayList<String> getMimesOfAvailableAudioEncoders() {
- MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
- ArrayList<String> listOfMimes = new ArrayList<>();
- for (MediaCodecInfo codecInfo : codecInfos) {
- if (!codecInfo.isEncoder()) continue;
- String[] types = codecInfo.getSupportedTypes();
- for (String type : types) {
- if (type.startsWith("audio/") && !listOfMimes.contains(type)) {
- listOfMimes.add(type);
- }
- }
- }
- return listOfMimes;
- }
-
- // Returns the list of parameters with mimetype and their encoder(for audio - all encoders,
- // video - hardware encoders).
- // Parameters {0}_{1} -- Mime_EncoderName
- @Parameterized.Parameters(name = "{index}({0}_{1})")
- public static Collection<Object[]> inputParams() {
- // Prepares the params list with the required Hardware video encoders and all available
- // audio encoders present in the device.
- final List<Object[]> argsList = new ArrayList<>();
- ArrayList<String> mimesList = getMimesOfAvailableHardwareVideoEncoders();
- mimesList.addAll(getMimesOfAvailableAudioEncoders());
- for (String mime : mimesList) {
- ArrayList<String> listOfEncoders;
- if (mime.startsWith("audio/")) {
- listOfEncoders = selectCodecs(mime, null, null, true);
- } else {
- listOfEncoders = selectHardwareCodecs(mime, null, null, true);
- }
- for (String encoder : listOfEncoders) {
- argsList.add(new Object[]{mime, encoder});
- }
- }
- return argsList;
- }
-
- private MediaRecorder createMediaRecorderLoad(Surface surface) throws Exception {
- MediaRecorder mediaRecorder = new MediaRecorder(InstrumentationRegistry.getInstrumentation()
- .getContext());
- mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
- mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
- mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mediaRecorder.setVideoEncoder(mMime.equalsIgnoreCase(HEVC) ?
- MediaRecorder.VideoEncoder.HEVC : MediaRecorder.VideoEncoder.H264);
- mediaRecorder.setOutputFile(mTempRecordedFile);
- mediaRecorder.setVideoSize(1920, 1080);
- mediaRecorder.setOrientationHint(0);
- mediaRecorder.setPreviewDisplay(surface);
- mediaRecorder.prepare();
- return mediaRecorder;
- }
-
- private void startLoad() throws Exception {
- // TODO: b/183671436
- // Create Transcode load (AVC Decoder(720p) + AVC Encoder(720p))
- mTranscodeLoadStatus = new LoadStatus();
- mTranscodeLoadThread = new Thread(() -> {
- try {
- TranscodeLoad transcodeLoad = new TranscodeLoad(AVC, AVC_TRANSCODE_FILE,
- AVC_DECODER_NAME, AVC_ENCODER_NAME, mTranscodeLoadStatus);
- transcodeLoad.doTranscode();
- } catch (Exception e) {
- mException = e;
- }
- });
- // Create MediaRecorder Session - Audio (Microphone) + 1080p Video (Camera)
- // Create a temp file to dump the MediaRecorder output. Later it will be deleted.
- mTempRecordedFile = new File(WorkDir.getMediaDirString() + "tempOut.mp4");
- mTempRecordedFile.createNewFile();
- mMediaRecorderLoad = createMediaRecorderLoad(mSurface);
- // Start the Loads
- mTranscodeLoadThread.start();
- mMediaRecorderLoad.start();
- }
-
- private void stopLoad() throws Exception {
- if (mTranscodeLoadStatus != null) {
- mTranscodeLoadStatus.setLoadFinished();
- mTranscodeLoadStatus = null;
- }
- if (mTranscodeLoadThread != null) {
- mTranscodeLoadThread.join();
- mTranscodeLoadThread = null;
- }
- if (mMediaRecorderLoad != null) {
- // Note that a RuntimeException is intentionally thrown to the application, if no valid
- // audio/video data has been received when stop() is called. This happens if stop() is
- // called immediately after start(). So sleep for 1000ms inorder to make sure some
- // data has been received between start() and stop().
- Thread.sleep(1000);
- mMediaRecorderLoad.stop();
- mMediaRecorderLoad.release();
- mMediaRecorderLoad = null;
- if (mTempRecordedFile != null && mTempRecordedFile.exists()) {
- mTempRecordedFile.delete();
- mTempRecordedFile = null;
- }
- }
- if (mException != null) throw mException;
- }
-
- private void createSurface() throws InterruptedException {
- mActivityRule.getActivity().waitTillSurfaceIsCreated();
- mSurface = mActivityRule.getActivity().getSurface();
- assertTrue("Surface created is null.", mSurface != null);
- assertTrue("Surface created is invalid.", mSurface.isValid());
- mActivityRule.getActivity().setScreenParams(1920, 1080, true);
- }
-
- private void releaseSurface() {
- if (mSurface != null) {
- mSurface.release();
- mSurface = null;
- }
- }
-
- /**
- * This test validates that the initialization latency(time for codec create + configure)
- * for the audio encoders <= 30ms and for video encoders <= 40ms measuring 10 times in
- * succession(5 times alternating sync and async modes). This also logs the stats min, max, avg
- * of the encoder initialization latencies.
- */
- @LargeTest
- @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
- @CddTest(requirement = "2.2.7.1/5.1/H-1-7,H-1-8")
- public void testInitializationLatency() throws Exception {
- final int NUM_MEASUREMENTS = 5;
- // Test gathers initialization latency for a number of iterations and
- // percentile is a variable used to control how many of these iterations
- // need to meet the pass criteria. For NUM_MEASUREMENTS at 5, sync and Async
- // modes which is a total of 10 iterations, this translates to index 7.
- final int percentile = 70;
- long expectedMaxCodecInitializationLatencyMs = mMime.startsWith("audio/") ?
- MAX_AUDIOENC_INITIALIZATION_LATENCY_MS : MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
- long sumOfEncoderInitializationLatencyMs = 0;
- int count = 0;
- long[] encoderInitializationLatencyMs = new long[NUM_MEASUREMENTS * boolStates.length];
- for (int i = 0; i < NUM_MEASUREMENTS; i++) {
- for (boolean isAsync : boolStates) {
- EncoderInitializationLatency encoderInitializationLatency =
- new EncoderInitializationLatency(mMime, mEncoderName, isAsync);
- long latency = encoderInitializationLatency.calculateEncoderInitializationLatency();
- encoderInitializationLatencyMs[count] = latency;
- sumOfEncoderInitializationLatencyMs += latency;
- count++;
- }
- }
- Arrays.sort(encoderInitializationLatencyMs);
-
- String statsLog = String.format("CodecInitialization latency for mime: %s, " +
- "Encoder: %s, in Ms :: ", mMime, mEncoderName);
- Log.i(LOG_TAG, "Min " + statsLog + encoderInitializationLatencyMs[0]);
- Log.i(LOG_TAG, "Max " + statsLog + encoderInitializationLatencyMs[count - 1]);
- Log.i(LOG_TAG, "Avg " + statsLog + (sumOfEncoderInitializationLatencyMs / count));
- long initializationLatency = encoderInitializationLatencyMs[percentile * count / 100];
- if (Utils.isPerfClass()) {
- String errorLog = String.format(
- "CodecInitialization latency for mime: %s, Encoder: %s is not as expected. "
- + "act/exp in Ms :: %d/%d", mMime, mEncoderName, initializationLatency,
- expectedMaxCodecInitializationLatencyMs);
- assertTrue(errorLog, initializationLatency <= expectedMaxCodecInitializationLatencyMs);
- } else {
- int pc;
- if (mMime.startsWith("audio/")) {
- pc = initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS ?
- Build.VERSION_CODES.TIRAMISU :
- initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS ?
- Build.VERSION_CODES.S : initializationLatency <
- MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS ?
- Build.VERSION_CODES.R : 0;
- } else {
- pc = initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS ?
- Build.VERSION_CODES.TIRAMISU :
- initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS ?
- Build.VERSION_CODES.S : initializationLatency <
- MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS ?
- Build.VERSION_CODES.R : 0;
- }
- DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs",
- "InitializationLatency_" + mEncoderName);
- log.addValue("encoder", mEncoderName, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue("initialization_latency", initializationLatency, ResultType.LOWER_BETTER,
- ResultUnit.NONE);
- log.setSummary("CDD 2.2.7.1/5.1/H-1-7,H-1-8 performance_class", pc, ResultType.NEUTRAL,
- ResultUnit.NONE);
- log.submit(InstrumentationRegistry.getInstrumentation());
- }
- }
-}
-
-/**
- * The following class calculates the encoder initialization latency (time for codec create +
- * configure). And also logs the time taken by the encoder for:
- * (create + configure + start),
- * (create + configure + start + first frame to enqueue),
- * (create + configure + start + first frame to dequeue).
- */
-class EncoderInitializationLatency extends CodecEncoderTestBase {
- private static final String LOG_TAG = EncoderInitializationLatency.class.getSimpleName();
-
- private final String mEncoderName;
- private final boolean mIsAsync;
-
- EncoderInitializationLatency(String mime, String encoderName, boolean isAsync) {
- super(mime);
- mEncoderName = encoderName;
- mIsAsync = isAsync;
- mSampleRate = 8000;
- mFrameRate = 60;
- }
-
- private MediaFormat setUpFormat() throws IOException {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, mMime);
- if (mIsAudio) {
- if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
- format.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, 10000);
- } else {
- format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
- }
- format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate);
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
- } else {
- MediaCodec codec = MediaCodec.createByCodecName(mEncoderName);
- MediaCodecInfo.CodecCapabilities codecCapabilities =
- codec.getCodecInfo().getCapabilitiesForType(mMime);
- if (codecCapabilities.getVideoCapabilities().isSizeSupported(1920, 1080)) {
- format.setInteger(MediaFormat.KEY_WIDTH, 1920);
- format.setInteger(MediaFormat.KEY_HEIGHT, 1080);
- format.setInteger(MediaFormat.KEY_BIT_RATE, 8000000);
- } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(1280, 720)) {
- format.setInteger(MediaFormat.KEY_WIDTH, 1280);
- format.setInteger(MediaFormat.KEY_HEIGHT, 720);
- format.setInteger(MediaFormat.KEY_BIT_RATE, 5000000);
- } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(640, 480)) {
- format.setInteger(MediaFormat.KEY_WIDTH, 640);
- format.setInteger(MediaFormat.KEY_HEIGHT, 480);
- format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
- } else if (codecCapabilities.getVideoCapabilities().isSizeSupported(352, 288)) {
- format.setInteger(MediaFormat.KEY_WIDTH, 352);
- format.setInteger(MediaFormat.KEY_HEIGHT, 288);
- format.setInteger(MediaFormat.KEY_BIT_RATE, 512000);
- } else {
- format.setInteger(MediaFormat.KEY_WIDTH, 176);
- format.setInteger(MediaFormat.KEY_HEIGHT, 144);
- format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
- }
- codec.release();
- format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
- format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
- MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
- }
- return format;
- }
-
- public long calculateEncoderInitializationLatency() throws Exception {
- MediaFormat format = setUpFormat();
- if (mIsAudio) {
- mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
- mChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
- } else {
- mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
- mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
- }
- setUpSource(mInputFile);
- MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
- long enqueueTimeStamp = 0;
- long dequeueTimeStamp = 0;
- long baseTimeStamp = System.nanoTime();
- mCodec = MediaCodec.createByCodecName(mEncoderName);
- resetContext(mIsAsync, false);
- mAsyncHandle.setCallBack(mCodec, mIsAsync);
- mCodec.configure(format, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
- long configureTimeStamp = System.nanoTime();
- mCodec.start();
- long startTimeStamp = System.nanoTime();
- if (mIsAsync) {
- // We will keep on feeding the input to encoder until we see the first dequeued frame.
- while (!mAsyncHandle.hasSeenError() && !mSawInputEOS) {
- Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
- if (element != null) {
- int bufferID = element.first;
- MediaCodec.BufferInfo info = element.second;
- if (info != null) {
- dequeueTimeStamp = System.nanoTime();
- dequeueOutput(bufferID, info);
- break;
- } else {
- if (enqueueTimeStamp == 0) {
- enqueueTimeStamp = System.nanoTime();
- }
- enqueueInput(bufferID);
- }
- }
- }
- } else {
- while (!mSawOutputEOS) {
- if (!mSawInputEOS) {
- int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
- if (inputBufferId > 0) {
- if (enqueueTimeStamp == 0) {
- enqueueTimeStamp = System.nanoTime();
- }
- enqueueInput(inputBufferId);
- }
- }
- int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
- if (outputBufferId >= 0) {
- dequeueTimeStamp = System.nanoTime();
- dequeueOutput(outputBufferId, outInfo);
- break;
- }
- }
- }
- queueEOS();
- waitForAllOutputs();
- mCodec.stop();
- mCodec.release();
- Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
- " Time for (create + configure) in ns: " + (configureTimeStamp - baseTimeStamp));
- Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
- " Time for (create + configure + start) in ns: " +
- (startTimeStamp - baseTimeStamp));
- Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
- " Time for (create + configure + start + first frame to enqueue) in ns: " +
- (enqueueTimeStamp - baseTimeStamp));
- Log.d(LOG_TAG, "Encode mMime: " + mMime + " Encoder: " + mEncoderName +
- " Time for (create + configure + start + first frame to dequeue) in ns: " +
- (dequeueTimeStamp - baseTimeStamp));
- long timeToConfigureMs = (configureTimeStamp - baseTimeStamp) / 1000000;
- return timeToConfigureMs;
- }
-}
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index ec27bf9..4e82515 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -16,6 +16,7 @@
package android.mediapc.cts;
+import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback;
import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
import static org.junit.Assert.assertTrue;
@@ -25,9 +26,11 @@
import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
import android.media.MediaFormat;
import android.mediapc.cts.common.Utils;
+import android.os.Build;
import android.util.Log;
import android.util.Pair;
+import org.junit.Assume;
import org.junit.Before;
import java.io.IOException;
@@ -49,6 +52,7 @@
static ArrayList<String> mMimeList = new ArrayList<>();
static Map<String, String> mTestFiles = new HashMap<>();
static Map<String, String> m720pTestFiles = new HashMap<>();
+ static Map<String, String> m1080pTestFiles = new HashMap<>();
static {
mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
@@ -57,14 +61,18 @@
m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4");
m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4");
- // Test VP9 and AV1 as well for Build.VERSION_CODES.S
- if (Utils.isSPerfClass()) {
+ // Test VP9 and AV1 as well for Build.VERSION_CODES.S and beyond
+ if (Utils.getPerfClass() >= Build.VERSION_CODES.S) {
mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP9);
mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm");
m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4");
}
+ m1080pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1920x1080_6mbps_30fps_avc.mp4");
+ m1080pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1920x1080_4mbps_30fps_hevc.mp4");
+ m1080pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1920x1080_4mbps_30fps_vp9.webm");
+ m1080pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1920x1080_4mbps_30fps_av1.mp4");
}
String mMime;
@@ -86,6 +94,11 @@
// Returns the list of hardware codecs for given mime
public static ArrayList<String> getHardwareCodecsForMime(String mime, boolean isEncoder) {
+ return getHardwareCodecsForMime(mime, isEncoder, false);
+ }
+
+ public static ArrayList<String> getHardwareCodecsForMime(String mime, boolean isEncoder,
+ boolean allCodecs) {
// All the multi-instance tests are limited to codecs that support at least 1280x720 @ 30fps
// This will exclude hevc constant quality encoders that are limited to max resolution of
// 512x512
@@ -93,7 +106,7 @@
fmt.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
ArrayList<MediaFormat> formatsList = new ArrayList<>();
formatsList.add(fmt);
- return selectHardwareCodecs(mime, formatsList, null, isEncoder);
+ return selectHardwareCodecs(mime, formatsList, null, isEncoder, allCodecs);
}
// Returns the max number of 30 fps instances that the given list of mimeCodecPairs
@@ -160,4 +173,30 @@
}
return REQUIRED_MIN_CONCURRENT_INSTANCES;
}
+
+ boolean isSecureSupportedCodec(String codecName, String mime) throws IOException {
+ boolean isSecureSupported;
+ MediaCodec codec = MediaCodec.createByCodecName(codecName);
+ isSecureSupported = codec.getCodecInfo().getCapabilitiesForType(mime).isFeatureSupported(
+ FEATURE_SecurePlayback);
+ codec.release();
+ return isSecureSupported;
+ }
+
+ boolean codecSupportsPP(String codecName, String mime, PerformancePoint reqPP)
+ throws IOException {
+ MediaCodec codec = MediaCodec.createByCodecName(codecName);
+ List<PerformancePoint> suppPPs =
+ codec.getCodecInfo().getCapabilitiesForType(mime).getVideoCapabilities()
+ .getSupportedPerformancePoints();
+ assertTrue("Performance point not published by codec: " + codecName, suppPPs != null);
+ boolean codecSupportsReqPP = false;
+ for (PerformancePoint pp : suppPPs) {
+ if (pp.covers(reqPP)) {
+ codecSupportsReqPP = true;
+ }
+ }
+ codec.release();
+ return codecSupportsReqPP;
+ }
}
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index 31c069f..832f9d0 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertTrue;
+import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.mediapc.cts.common.Utils;
import android.os.Build;
@@ -55,6 +56,7 @@
@RunWith(Parameterized.class)
public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase {
private static final String LOG_TAG = MultiDecoderPairPerfTest.class.getSimpleName();
+ private static final int REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE = 3;
private final Pair<String, String> mFirstPair;
private final Pair<String, String> mSecondPair;
@@ -74,7 +76,7 @@
final List<Object[]> argsList = new ArrayList<>();
ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
for (String mime : mMimeList) {
- ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false);
+ ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false, true);
for (String decoder : listOfDecoders) {
mimeTypeDecoderPairs.add(Pair.create(mime, decoder));
}
@@ -102,6 +104,9 @@
@CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2")
public void test720p() throws Exception {
Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
+ Assume.assumeFalse("Skipping regular performance tests for secure codecs",
+ isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) ||
+ isSecureSupportedCodec(mSecondPair.second, mSecondPair.first));
boolean hasVP9 = mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9) ||
mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
@@ -109,6 +114,69 @@
testCodec(m720pTestFiles, 720, 1280, requiredMinInstances);
}
+ /**
+ * This test calculates the number of 1080p 30 fps decoder instances that the given two
+ * (mime - decoder) pairs can support. Assigns the same number of instances to the two pairs
+ * (if max instances are even), or one more to one pair (if odd) and ensures that all the
+ * concurrent sessions succeed in decoding with meeting the expected frame rate.
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ @CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2")
+ public void test1080p() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ Assume.assumeFalse("Skipping regular performance tests for secure codecs",
+ isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) ||
+ isSecureSupportedCodec(mSecondPair.second, mSecondPair.first));
+ testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES);
+ }
+
+ /**
+ * Validates if hardware decoder pairs where one or both supports secure decode and required
+ * perf are present
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ // TODO(b/218771970) Add @CddTest annotation
+ public void testReqSecureDecodeSupport() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ Assume.assumeTrue("Skipping secure decode support tests if both are non-secure codecs",
+ isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) ||
+ isSecureSupportedCodec(mSecondPair.second, mSecondPair.first));
+
+ MediaCodecInfo.VideoCapabilities.PerformancePoint reqSecurePP =
+ new MediaCodecInfo.VideoCapabilities.PerformancePoint(1920, 1080, 30);
+
+ MediaCodecInfo.VideoCapabilities.PerformancePoint reqNonSecurePP =
+ new MediaCodecInfo.VideoCapabilities.PerformancePoint(1920, 1080,
+ 30 * REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE);
+
+ boolean codecSupportsReqPP = codecSupportsPP(mFirstPair.second, mFirstPair.first,
+ isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) ? reqSecurePP :
+ reqNonSecurePP);
+
+ codecSupportsReqPP &= codecSupportsPP(mSecondPair.second, mSecondPair.first,
+ isSecureSupportedCodec(mSecondPair.second, mSecondPair.first) ? reqSecurePP :
+ reqNonSecurePP);
+
+
+ if (Utils.isTPerfClass()) {
+ assertTrue(
+ "Required Secure Decode Support required for MPC >= Android T, unsupported " +
+ "codec pair: " + mFirstPair.second + "," + mSecondPair.second,
+ codecSupportsReqPP);
+ } else {
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "SecureDecodeSupport");
+ log.addValue("Req Secure Decode Support pair: " + mFirstPair.second + "," +
+ mSecondPair.second, codecSupportsReqPP, ResultType.NEUTRAL, ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary("MPC 13: Secure Decode requirements", 0, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
private void testCodec(Map<String, String> testFiles, int height, int width,
int requiredMinInstances) throws Exception {
mTestFiles = testFiles;
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index 1c1aeea..803ec62 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertTrue;
+import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
import android.media.MediaFormat;
import android.mediapc.cts.common.Utils;
import android.os.Build;
@@ -53,6 +54,7 @@
@RunWith(Parameterized.class)
public class MultiDecoderPerfTest extends MultiCodecPerfTestBase {
private static final String LOG_TAG = MultiDecoderPerfTest.class.getSimpleName();
+ private static final int REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES = 2;
private final String mDecoderName;
@@ -68,7 +70,7 @@
public static Collection<Object[]> inputParams() {
final List<Object[]> argsList = new ArrayList<>();
for (String mime : mMimeList) {
- ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false);
+ ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false, true);
for (String decoder : listOfDecoders) {
for (boolean isAsync : boolStates) {
argsList.add(new Object[]{mime, decoder, isAsync});
@@ -88,12 +90,60 @@
@CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2")
public void test720p() throws Exception {
Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
-
+ Assume.assumeFalse("Skipping regular performance tests for secure codecs",
+ isSecureSupportedCodec(mDecoderName, mMime));
boolean hasVP9 = mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9);
testCodec(m720pTestFiles, 720, 1280, requiredMinInstances);
}
+ /**
+ * This test validates that the decoder can support at least 6 concurrent 1080p 30fps
+ * decoder instances. Also ensures that all the concurrent sessions succeed in decoding
+ * with meeting the expected frame rate.
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ @CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2")
+ public void test1080p() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ Assume.assumeFalse("Skipping regular performance tests for secure codecs",
+ isSecureSupportedCodec(mDecoderName, mMime));
+ testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES);
+ }
+
+ /**
+ * Validates if hardware decoder that supports required secure decode perf is present
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ // TODO(b/218771970) Add @CddTest annotation
+ public void testReqSecureDecodeSupport() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ Assume.assumeTrue("Skipping secure decode support tests for non-secure codecs",
+ isSecureSupportedCodec(mDecoderName, mMime));
+
+ PerformancePoint reqPP =
+ new PerformancePoint(1920, 1080, 30 * REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES);
+
+ boolean codecSupportsReqPP = codecSupportsPP(mDecoderName, mMime, reqPP);
+
+ if (Utils.isTPerfClass()) {
+ assertTrue(
+ "Required Secure Decode Support required for MPC >= Android T, unsupported " +
+ "codec: " + mDecoderName, codecSupportsReqPP);
+ } else {
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "SecureDecodeSupport");
+ log.addValue("Req Secure Decode Support: " + mDecoderName, codecSupportsReqPP,
+ ResultType.NEUTRAL, ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary("MPC 13: Secure Decode requirements", 0, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
private void testCodec(Map<String, String> testFiles, int height, int width,
int requiredMinInstances) throws Exception {
mTestFile = testFiles.get(mMime);
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
index edc2d6c..01e68d3 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
@@ -109,6 +109,20 @@
testCodec(720, 1280, 4000000, requiredMinInstances);
}
+ /**
+ * This test calculates the number of 1080p 30 fps encoder instances that the given two
+ * (mime - encoder) pairs can support. Assigns the same number of instances to the two pairs
+ * (if max instances are even), or one more to one pair (if odd) and ensures that all the
+ * concurrent sessions succeed in encoding.
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ @CddTest(requirement = "2.2.7.1/5.1/H-1-3,H-1-4")
+ public void test1080p() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ testCodec(1080, 1920, 10000000, REQUIRED_MIN_CONCURRENT_INSTANCES);
+ }
+
private void testCodec(int height, int width, int bitrate, int requiredMinInstances)
throws Exception {
ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>();
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index 3a2f1d9..28c7fbd 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -94,6 +94,18 @@
testCodec(720, 1280, 4000000, requiredMinInstances);
}
+ /**
+ * This test validates that the encoder can support at least 6 concurrent 1080p 30fps
+ * encoder instances. Also ensures that all the concurrent sessions succeed in encoding.
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ @CddTest(requirement = "2.2.7.1/5.1/H-1-3,H-1-4")
+ public void test1080p() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ testCodec(1080, 1920, 10000000, REQUIRED_MIN_CONCURRENT_INSTANCES);
+ }
+
private void testCodec(int height, int width, int bitrate, int requiredMinInstances)
throws Exception {
ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>();
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index d7d8445..9312637 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -119,6 +119,21 @@
testCodec(m720pTestFiles, 720, 1280, requiredMinInstances);
}
+ /**
+ * This test calculates the validates number of concurrent 1080p Transcode sessions that
+ * it can support by the (mime, decoder - mime, encoder) pairs. Creates maxInstances / 2
+ * Transcode sessions. If maximum instances is odd, creates one additional decoder which decodes
+ * to surface and render. And ensures that all the supported sessions succeed in
+ * transcoding/decoding with meeting the expected frame rate.
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ @CddTest(requirement = "2.2.7.1/5.1/H-1-5,H-1-6")
+ public void test1080p() throws Exception {
+ Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass());
+ testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES / 2);
+ }
+
private void testCodec(Map<String, String> testFiles, int height, int width,
int requiredMinInstances) throws Exception {
mTestFiles = testFiles;
diff --git a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
new file mode 100644
index 0000000..0afc209
--- /dev/null
+++ b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.mediapc.cts;
+
+import static android.media.MediaFormat.MIMETYPE_VIDEO_AV1;
+import static android.mediapc.cts.CodecTestBase.SELECT_HARDWARE;
+import static android.mediapc.cts.CodecTestBase.SELECT_VIDEO;
+import static android.mediapc.cts.CodecTestBase.getMimesOfAvailableCodecs;
+import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+import static org.junit.Assert.assertTrue;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
+import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class VideoCodecRequirementsTest {
+ 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 Set<String> get4k60HwCodecSet(boolean isEncoder) throws IOException {
+ Set<String> codecSet = new HashSet<>();
+ Set<String> codecMediaTypes = getMimesOfAvailableCodecs(SELECT_VIDEO, SELECT_HARDWARE);
+ PerformancePoint PP4k60 = new PerformancePoint(3840, 2160, 60);
+ for (String codecMediaType : codecMediaTypes) {
+ ArrayList<String> hwVideoCodecs =
+ selectHardwareCodecs(codecMediaType, null, null, isEncoder);
+ for (String hwVideoCodec : hwVideoCodecs) {
+ MediaCodec codec = MediaCodec.createByCodecName(hwVideoCodec);
+ CodecCapabilities capabilities =
+ codec.getCodecInfo().getCapabilitiesForType(codecMediaType);
+ List<PerformancePoint> pps =
+ capabilities.getVideoCapabilities().getSupportedPerformancePoints();
+ for (PerformancePoint pp : pps) {
+ if (pp.covers(PP4k60)) {
+ codecSet.add(hwVideoCodec);
+ Log.d(LOG_TAG,
+ "Performance point 4k60 supported by codec: " + hwVideoCodec);
+ break;
+ }
+ }
+ codec.release();
+ }
+ }
+ return codecSet;
+ }
+
+ /**
+ * Validates AV1 hardware decoder is present and supports: Main 10, Level 4.1, Film Grain
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ // TODO(b/218771970) Add @CddTest annotation
+ public void testAV1HwDecoderRequirements() throws Exception {
+ MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AV1, 1920, 1080);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, 60);
+ ArrayList<MediaFormat> formats = new ArrayList<>();
+ formats.add(format);
+ ArrayList<String> av1HwDecoders =
+ selectHardwareCodecs(MIMETYPE_VIDEO_AV1, formats, null, false);
+ boolean oneCodecDecoding = false;
+ for (String codec : av1HwDecoders) {
+ Decode decode = new Decode(MIMETYPE_VIDEO_AV1, FILE_AV1_REQ_SUPPORT, codec, true);
+ double achievedRate = decode.doDecode();
+ if (achievedRate > 0) {
+ oneCodecDecoding = true;
+ }
+ }
+ if (Utils.isTPerfClass()) {
+ assertTrue("One AV1 HW decoder with supported features required for MPC >= Android T",
+ oneCodecDecoding);
+ } else {
+ int pc = oneCodecDecoding ? Build.VERSION_CODES.TIRAMISU : 0;
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "VideoCodecRequirements");
+ log.addValue("AV1DecoderFeatureSupport", oneCodecDecoding, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary(
+ "Video Codec Requirements: AV1 HW decoder: Main 10, Level 4.1, Film Grain", pc,
+ ResultType.HIGHER_BETTER, ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
+ /**
+ * Validates if a hardware decoder that supports 4k60 is present
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ // TODO(b/218771970) Add @CddTest annotation
+ public void test4k60Decoder() throws IOException {
+ Set<String> decoderSet = get4k60HwCodecSet(false);
+ boolean oneCodecSupportsRequiredPerformance = !decoderSet.isEmpty();
+
+ if (Utils.isTPerfClass()) {
+ assertTrue("At least one 4k60 HW decoder required for MPC >= Android T",
+ oneCodecSupportsRequiredPerformance);
+ } else {
+ int pc = oneCodecSupportsRequiredPerformance ? Build.VERSION_CODES.TIRAMISU : 0;
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "VideoCodecRequirements");
+ log.addValue("4k60DecodeHW", oneCodecSupportsRequiredPerformance, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary("Video Codec Requirements: 1 HW video decoder supporting 4K60", pc,
+ ResultType.HIGHER_BETTER, ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
+ /**
+ * Validates if a hardware encoder that supports 4k60 is present
+ */
+ @LargeTest
+ @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
+ // TODO(b/218771970) Add @CddTest annotation
+ public void test4k60Encoder() throws IOException {
+ Set<String> encoderSet = get4k60HwCodecSet(true);
+ boolean oneCodecSupportsRequiredPerformance = !encoderSet.isEmpty();
+
+ if (Utils.isTPerfClass()) {
+ assertTrue("At least one 4k60 HW encoder required for MPC >= Android T",
+ oneCodecSupportsRequiredPerformance);
+ } else {
+ int pc = oneCodecSupportsRequiredPerformance ? Build.VERSION_CODES.TIRAMISU : 0;
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "VideoCodecRequirements");
+ log.addValue("4k60EncodeHW", oneCodecSupportsRequiredPerformance, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary("Video Codec Requirements: 1 HW video encoder supporting 4K60", pc,
+ ResultType.HIGHER_BETTER, ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+}
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt b/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
index 4d09333..7ca994b 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
@@ -59,6 +59,7 @@
override fun onDeviceAppeared(associationInfo: AssociationInfo) {
Log.d(TAG, "$this.onDevice_Appeared(), association=$associationInfo")
_connectedDevices[associationInfo.id] = associationInfo
+
super.onDeviceAppeared(associationInfo)
}
@@ -86,6 +87,10 @@
instanceHolder.instance = null
super.onDestroy()
}
+
+ fun removeConnectedDevice(associationId: Int) {
+ _connectedDevices.remove(associationId)
+ }
}
sealed class InstanceHolder<T : CompanionService<T>> {
@@ -127,6 +132,13 @@
}
if (!gone) throw AssertionError("""Association with $associationId hasn't "disappeared"""")
}
+
+ // This is a useful function to use to conveniently "forget" that a device is currently present.
+ // Use to bypass the "unbinding while there are connected devices" for simulated devices.
+ // (Don't worry! they would have removed themselves after 1 minute anyways!)
+ fun forgetDevicePresence(associationId: Int) {
+ instance?.removeConnectedDevice(associationId)
+ }
}
class PrimaryCompanionService : CompanionService<PrimaryCompanionService>(Companion) {
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
index 2525769..8c03abd 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
@@ -36,11 +36,14 @@
import org.junit.AssumptionViolatedException
import org.junit.Before
import java.io.IOException
+import kotlin.test.assertContains
+import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertIs
import kotlin.test.assertTrue
import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
/**
@@ -156,6 +159,89 @@
expected = expected)
/**
+ * Assert that CDM binds valid CompanionDeviceServices, both primary and secondary.
+ * Use when services are expected to switch its state to "bound".
+ */
+fun assertValidCompanionDeviceServicesBind() =
+ assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should bind") {
+ waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
+ PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
+ }
+ }
+
+/**
+ * Assert both primary and secondary CompanionDeviceServices stay bound.
+ * Use when services are expected to be in "bound" state already.
+ */
+fun assertValidCompanionDeviceServicesRemainBound() =
+ assertFalse("Both valid CompanionDeviceServices should stay bound") {
+ waitFor(timeout = 3.seconds, interval = 100.milliseconds) {
+ !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
+ }
+ }
+
+/**
+ * Assert that CDM unbinds valid CompanionDeviceServices, both primary and secondary.
+ * Use when services are expected to switch its state to "unbound".
+ */
+fun assertValidCompanionDeviceServicesUnbind() =
+ assertTrue("CompanionDeviceServices should not bind") {
+ waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
+ !PrimaryCompanionService.isBound && !SecondaryCompanionService.isBound
+ }
+ }
+
+/**
+ * Assert that neither primary nor secondary CompanionDeviceService is bound.
+ * Use when services are expected to be in "unbound" state already.
+ */
+fun assertValidCompanionDeviceServicesRemainUnbound() =
+ assertFalse("CompanionDeviceServices should not be bound") {
+ waitFor(timeout = 3.seconds, interval = 100.milliseconds) {
+ PrimaryCompanionService.isBound || SecondaryCompanionService.isBound
+ }
+ }
+
+/**
+ * Assert that CDM did not bind invalid CompanionDeviceServices
+ * (i.e. missing permission or intent-filter).
+ */
+fun assertInvalidCompanionDeviceServicesNotBound() =
+ assertFalse("CompanionDeviceServices that do not require " +
+ "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
+ "\"android.companion.CompanionDeviceService\" action should not be bound") {
+ MissingPermissionCompanionService.isBound ||
+ MissingIntentFilterActionCompanionService.isBound
+ }
+
+/**
+ * Assert that device (dis)appearance detection callback is only triggered for the primary
+ * CompanionDeviceService and not on any of the non-primary or invalid CompanionDeviceServices.
+ */
+fun assertOnlyPrimaryCompanionDeviceServiceNotified(associationId: Int, appeared: Boolean) {
+ val snapshotSecondary = HashSet(SecondaryCompanionService.connectedDevices)
+ val snapshotUnauthorized = HashSet(MissingPermissionCompanionService.connectedDevices)
+ val snapshotInvalid = HashSet(MissingIntentFilterActionCompanionService.connectedDevices)
+
+ // Check that the primary CompanionDeviceService received onDevice(Dis)Appeared() callback
+ if (appeared) {
+ PrimaryCompanionService.waitAssociationToAppear(associationId)
+ assertContains(PrimaryCompanionService.associationIdsForConnectedDevices, associationId)
+ } else {
+ PrimaryCompanionService.waitAssociationToDisappear(associationId)
+ assertFalse(PrimaryCompanionService.associationIdsForConnectedDevices
+ .contains(associationId))
+ }
+
+ // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
+ // have NOT. (Give it 1 more second.)
+ sleepFor(1.seconds)
+ assertContentEquals(snapshotSecondary, SecondaryCompanionService.connectedDevices)
+ assertContentEquals(snapshotUnauthorized, MissingPermissionCompanionService.connectedDevices)
+ assertContentEquals(snapshotInvalid, MissingIntentFilterActionCompanionService.connectedDevices)
+}
+
+/**
* @return whether the condition was met before time ran out.
*/
fun waitFor(
diff --git a/tests/tests/companion/core/src/android/companion/cts/core/ObservingDevicePresenceTest.kt b/tests/tests/companion/core/src/android/companion/cts/core/ObservingDevicePresenceTest.kt
index 9bc5c53..4c0d4bf 100644
--- a/tests/tests/companion/core/src/android/companion/cts/core/ObservingDevicePresenceTest.kt
+++ b/tests/tests/companion/core/src/android/companion/cts/core/ObservingDevicePresenceTest.kt
@@ -1,25 +1,40 @@
+/*
+ * 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.companion.cts.core
import android.Manifest
import android.companion.cts.common.MAC_ADDRESS_A
-import android.companion.cts.common.MissingIntentFilterActionCompanionService
-import android.companion.cts.common.MissingPermissionCompanionService
+import android.companion.cts.common.MAC_ADDRESS_B
import android.companion.cts.common.PrimaryCompanionService
import android.companion.cts.common.SecondaryCompanionService
+import android.companion.cts.common.assertValidCompanionDeviceServicesBind
+import android.companion.cts.common.assertValidCompanionDeviceServicesRemainBound
+import android.companion.cts.common.assertValidCompanionDeviceServicesRemainUnbound
+import android.companion.cts.common.assertValidCompanionDeviceServicesUnbind
import android.companion.cts.common.assertEmpty
-import android.companion.cts.common.sleepFor
+import android.companion.cts.common.assertInvalidCompanionDeviceServicesNotBound
+import android.companion.cts.common.assertOnlyPrimaryCompanionDeviceServiceNotified
import android.companion.cts.common.toUpperCaseString
-import android.companion.cts.common.waitFor
import android.platform.test.annotations.AppModeFull
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertContentEquals
import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-import kotlin.time.Duration.Companion.milliseconds
-import kotlin.time.Duration.Companion.seconds
/**
* Test CDM APIs for observing device presence.
@@ -41,13 +56,9 @@
simulateDeviceAppeared(associationId)
- // Make sure CDM does not bind CompanionDeviceServices
- assertFalse("CompanionDeviceServices should not be bound when observing device presence " +
- "is off") {
- waitFor(timeout = 3.seconds, interval = 100.milliseconds) {
- PrimaryCompanionService.isBound || SecondaryCompanionService.isBound
- }
- }
+ // Make sure CDM does not bind application
+ assertValidCompanionDeviceServicesRemainUnbound()
+
// ... and does not trigger onDeviceAppeared ()
assertEmpty(PrimaryCompanionService.connectedDevices)
assertEmpty(SecondaryCompanionService.connectedDevices)
@@ -87,53 +98,26 @@
// Simulate device appeared.
simulateDeviceAppeared(associationId)
- // Make sure CDM binds valid CompanionDeviceServices...
- assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
- "now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
- }
- }
- // ... and does not bind incorrectly defined CompanionDeviceServices.
- assertFalse("CompanionDeviceServices that do not require " +
- "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
- "\"android.companion.CompanionDeviceService\" action should not be bound") {
- MissingPermissionCompanionService.isBound ||
- MissingIntentFilterActionCompanionService.isBound
- }
+ // Make sure valid CompanionDeviceServices are bound
+ assertValidCompanionDeviceServicesBind()
+
+ // ... and incorrectly defined CompanionDeviceServices are not
+ assertInvalidCompanionDeviceServicesNotBound()
// Check that only the primary CompanionDeviceService has received the onDeviceAppeared()
// callback...
- PrimaryCompanionService.waitAssociationToAppear(associationId)
- assertContentEquals(
- actual = PrimaryCompanionService.associationIdsForConnectedDevices,
- expected = setOf(associationId)
- )
- // ... while the non-primary and incorrectly defined CompanionDeviceServices - have NOT.
- // (Give it 1 more second.)
- sleepFor(1.seconds)
- assertEmpty(SecondaryCompanionService.connectedDevices)
- assertEmpty(MissingPermissionCompanionService.connectedDevices)
- assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
+ assertOnlyPrimaryCompanionDeviceServiceNotified(associationId, appeared = true)
- assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
- "bound ") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
- }
- }
+ // Make sure that both primary and secondary CompanionDeviceServices still bind.
+ assertValidCompanionDeviceServicesRemainBound()
simulateDeviceDisappeared(associationId)
// Check that only the primary services has received the onDeviceDisappeared() callback.
- PrimaryCompanionService.waitAssociationToDisappear(associationId)
- assertEmpty(PrimaryCompanionService.connectedDevices)
+ assertOnlyPrimaryCompanionDeviceServiceNotified(associationId, appeared = false)
- assertTrue("Both Services - Primary and Secondary - should be unbound now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound && !SecondaryCompanionService.isBound
- }
- }
+ // Both primary and secondary CompanionDeviceServices should unbind now.
+ assertValidCompanionDeviceServicesUnbind()
}
@Test
@@ -148,16 +132,12 @@
cdm.stopObservingDevicePresence(MAC_ADDRESS_A.toUpperCaseString())
}
- // Simulate device disappeared.
+ // Simulate device appeared.
simulateDeviceAppeared(associationId)
- // Make sure CDM does not bind CompanionDeviceServices
- assertFalse("CompanionDeviceServices should not be bound when observing device presence " +
- "is off") {
- waitFor(timeout = 3.seconds, interval = 100.milliseconds) {
- PrimaryCompanionService.isBound || SecondaryCompanionService.isBound
- }
- }
+ // Make sure CDM does not bind application
+ assertValidCompanionDeviceServicesRemainUnbound()
+
// ... and does not trigger onDeviceAppeared ()
assertEmpty(PrimaryCompanionService.connectedDevices)
assertEmpty(SecondaryCompanionService.connectedDevices)
@@ -166,6 +146,130 @@
simulateDeviceDisappeared(associationId)
}
+ @Test
+ fun test_startObservingDevicePresence_alreadyPresent() {
+ // Create a regular (not self-managed) association.
+ targetApp.associate(MAC_ADDRESS_A)
+ val associationId = cdm.myAssociations[0].id
+
+ // Simulate device appearing before observing it
+ simulateDeviceAppeared(associationId)
+
+ // Make sure CDM doesn't bind application yet
+ assertValidCompanionDeviceServicesRemainUnbound()
+
+ // Start observing presence of an already present device.
+ withShellPermissionIdentity(Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) {
+ cdm.startObservingDevicePresence(MAC_ADDRESS_A.toUpperCaseString())
+ }
+
+ // Make sure valid CompanionDeviceServices are bound
+ assertValidCompanionDeviceServicesBind()
+ assertInvalidCompanionDeviceServicesNotBound()
+
+ // Clean-up
+ simulateDeviceDisappeared(associationId)
+ }
+
+ @Test
+ fun test_startObservingDevicePresence_multipleDevices() {
+ // Create two regular (not self-managed) associations.
+ targetApp.associate(MAC_ADDRESS_A)
+ targetApp.associate(MAC_ADDRESS_B)
+ val idA = cdm.myAssociations[0].id
+ val idB = cdm.myAssociations[1].id
+
+ // Start observing presence of both devices.
+ withShellPermissionIdentity(Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) {
+ cdm.startObservingDevicePresence(MAC_ADDRESS_A.toUpperCaseString())
+ cdm.startObservingDevicePresence(MAC_ADDRESS_B.toUpperCaseString())
+ }
+
+ simulateDeviceAppeared(idA)
+
+ // Assert only the valid CompanionDeviceServices (primary + secondary) bind
+ assertValidCompanionDeviceServicesBind()
+ assertInvalidCompanionDeviceServicesNotBound()
+
+ // Assert only the primary CompanionDeviceService is notified of device A's appearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idA, appeared = true)
+ assertContentEquals(
+ actual = PrimaryCompanionService.associationIdsForConnectedDevices,
+ expected = setOf(idA)
+ )
+
+ simulateDeviceAppeared(idB)
+
+ // Assert only the primary CompanionDeviceService is notified of device B's appearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idB, appeared = true)
+ assertContentEquals(
+ actual = PrimaryCompanionService.associationIdsForConnectedDevices,
+ expected = setOf(idA, idB)
+ )
+
+ // Make sure both valid services stay bound.
+ assertValidCompanionDeviceServicesRemainBound()
+
+ // "Disconnect" first device (A).
+ simulateDeviceDisappeared(idA)
+
+ // Assert only the primary CompanionDeviceService is notified of device A's disappearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idA, appeared = false)
+
+ // Both valid services should stay bound for as long as there is at least one connected
+ // device - device B in this case.
+ assertValidCompanionDeviceServicesRemainBound()
+
+ // "Disconnect" second (and last remaining) device (B).
+ simulateDeviceDisappeared(idB)
+
+ // Assert only the primary CompanionDeviceService is notified of device B's disappearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idB, appeared = false)
+
+ // Both valid services should unbind now.
+ assertValidCompanionDeviceServicesUnbind()
+ }
+
+ @Test
+ fun test_stopObservingDevicePresence_unbindsApplication() {
+ // Create two regular (not self-managed) association.s
+ targetApp.associate(MAC_ADDRESS_A)
+ targetApp.associate(MAC_ADDRESS_B)
+ val idA = cdm.myAssociations[0].id
+ val idB = cdm.myAssociations[1].id
+
+ // Start observing presence of both devices.
+ withShellPermissionIdentity(Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) {
+ cdm.startObservingDevicePresence(MAC_ADDRESS_A.toUpperCaseString())
+ cdm.startObservingDevicePresence(MAC_ADDRESS_B.toUpperCaseString())
+ }
+
+ simulateDeviceAppeared(idA)
+ simulateDeviceAppeared(idB)
+
+ // Assert only the valid CompanionDeviceServices (primary + secondary) bind
+ assertValidCompanionDeviceServicesBind()
+ assertInvalidCompanionDeviceServicesNotBound()
+
+ // Stop observing presence of device A.
+ PrimaryCompanionService.forgetDevicePresence(idA)
+ withShellPermissionIdentity(Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) {
+ cdm.stopObservingDevicePresence(MAC_ADDRESS_A.toUpperCaseString())
+ }
+
+ // Make sure both valid services stay bound.
+ assertValidCompanionDeviceServicesRemainBound()
+
+ // Stop observing presence of device B.
+ PrimaryCompanionService.forgetDevicePresence(idB)
+ withShellPermissionIdentity(Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) {
+ cdm.stopObservingDevicePresence(MAC_ADDRESS_B.toUpperCaseString())
+ }
+
+ // Both valid services should unbind now.
+ assertValidCompanionDeviceServicesUnbind()
+ }
+
private fun simulateDeviceAppeared(associationId: Int) = runShellCommand(
"cmd companiondevice simulate-device-appeared $associationId")
diff --git a/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt b/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
index f34e828..0305da7 100644
--- a/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
+++ b/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
@@ -20,15 +20,14 @@
import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
import android.companion.cts.common.DEVICE_DISPLAY_NAME_B
import android.companion.cts.common.MAC_ADDRESS_A
-import android.companion.cts.common.MissingIntentFilterActionCompanionService
-import android.companion.cts.common.MissingPermissionCompanionService
import android.companion.cts.common.PrimaryCompanionService
import android.companion.cts.common.Repeat
import android.companion.cts.common.RepeatRule
-import android.companion.cts.common.SecondaryCompanionService
-import android.companion.cts.common.assertEmpty
-import android.companion.cts.common.waitFor
-import android.os.SystemClock.sleep
+import android.companion.cts.common.assertValidCompanionDeviceServicesBind
+import android.companion.cts.common.assertValidCompanionDeviceServicesRemainBound
+import android.companion.cts.common.assertValidCompanionDeviceServicesUnbind
+import android.companion.cts.common.assertInvalidCompanionDeviceServicesNotBound
+import android.companion.cts.common.assertOnlyPrimaryCompanionDeviceServiceNotified
import android.platform.test.annotations.AppModeFull
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
@@ -36,10 +35,6 @@
import org.junit.runner.RunWith
import kotlin.test.assertContentEquals
import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-import kotlin.time.Duration.Companion.milliseconds
-import kotlin.time.Duration.Companion.seconds
/**
* Tests CDM APIs for notifying the presence of status of the companion devices for self-managed
@@ -65,51 +60,23 @@
cdm.notifyDeviceAppeared(associationId)
- assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
- "now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
- }
- }
- assertFalse("CompanionDeviceServices that do not require " +
- "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
- "\"android.companion.CompanionDeviceService\" action should not be bound") {
- MissingPermissionCompanionService.isBound ||
- MissingIntentFilterActionCompanionService.isBound
- }
+ // Assert only the valid CompanionDeviceServices (primary + secondary) are bound
+ assertValidCompanionDeviceServicesBind()
+ assertInvalidCompanionDeviceServicesNotBound()
- // Check that only the primary CompanionDeviceService has received the onDeviceAppeared()
- // callback...
- PrimaryCompanionService.waitAssociationToAppear(associationId)
- assertContentEquals(
- actual = PrimaryCompanionService.associationIdsForConnectedDevices,
- expected = setOf(associationId)
- )
- // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
- // have NOT. (Give it 1 more second.)
- sleep(1000)
- assertEmpty(SecondaryCompanionService.connectedDevices)
- assertEmpty(MissingPermissionCompanionService.connectedDevices)
- assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
+ // Assert only the primary CompanionDeviceService is notified of device appearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(associationId, appeared = true)
- assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
- "bound ") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
- }
- }
+ // Assert both valid CompanionDeviceServices stay bound
+ assertValidCompanionDeviceServicesRemainBound()
cdm.notifyDeviceDisappeared(associationId)
- // Check that only the primary services has received the onDeviceDisappeared() callback.
- PrimaryCompanionService.waitAssociationToDisappear(associationId)
- assertEmpty(PrimaryCompanionService.connectedDevices)
+ // Assert only the primary CompanionDeviceService is notified of device disappearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(associationId, appeared = false)
- assertTrue("Both Services - Primary and Secondary - should be unbound now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound && !SecondaryCompanionService.isBound
- }
- }
+ // Assert both services are unbound now
+ assertValidCompanionDeviceServicesUnbind()
}
@Test
@@ -119,71 +86,47 @@
cdm.notifyDeviceAppeared(idA)
- assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
- "now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
- }
- }
- assertFalse("CompanionDeviceServices that do not require " +
- "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
- "\"android.companion.CompanionDeviceService\" action should not be bound") {
- MissingPermissionCompanionService.isBound ||
- MissingIntentFilterActionCompanionService.isBound
- }
+ // Assert only the valid CompanionDeviceServices (primary + secondary) are bound
+ assertValidCompanionDeviceServicesBind()
+ assertInvalidCompanionDeviceServicesNotBound()
- // Check that only the primary services has received the onDeviceAppeared() callback...
- PrimaryCompanionService.waitAssociationToAppear(idA)
+ // Assert only the primary CompanionDeviceService is notified of device A's appearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idA, appeared = true)
assertContentEquals(
- actual = PrimaryCompanionService.associationIdsForConnectedDevices,
- expected = setOf(idA)
+ actual = PrimaryCompanionService.associationIdsForConnectedDevices,
+ expected = setOf(idA)
)
- // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
- // have NOT. (Give it 1 more second.)
- sleep(1000)
- assertEmpty(SecondaryCompanionService.connectedDevices)
- assertEmpty(MissingPermissionCompanionService.connectedDevices)
- assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
cdm.notifyDeviceAppeared(idB)
- // Check that only the primary services has received the onDeviceAppeared() callback.
- PrimaryCompanionService.waitAssociationToAppear(idB)
+ // Assert only the primary CompanionDeviceService is notified of device B's appearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idB, appeared = true)
assertContentEquals(
actual = PrimaryCompanionService.associationIdsForConnectedDevices,
expected = setOf(idA, idB)
)
// Make sure both valid services stay bound.
- assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
- "bound ") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
- }
- }
+ assertValidCompanionDeviceServicesRemainBound()
// "Disconnect" first device (A).
cdm.notifyDeviceDisappeared(idA)
- PrimaryCompanionService.waitAssociationToDisappear(idA)
+ // Assert only the primary CompanionDeviceService is notified of device A's disappearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idA, appeared = false)
+
// Both valid services should stay bound for as long as there is at least one connected
// device - device B in this case.
- assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
- "bound ") {
- waitFor(timeout = 3.seconds, interval = 1.milliseconds) {
- !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
- }
- }
+ assertValidCompanionDeviceServicesRemainBound()
- // "Disconnect" second device (B).
+ // "Disconnect" second (and last remaining) device (B).
cdm.notifyDeviceDisappeared(idB)
- PrimaryCompanionService.waitAssociationToDisappear(idB)
- assertTrue("Both Services - Primary and Secondary - should be unbound now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound && !SecondaryCompanionService.isBound
- }
- }
+ // Assert only the primary CompanionDeviceService is notified of device B's disappearance
+ assertOnlyPrimaryCompanionDeviceServiceNotified(idB, appeared = false)
+
+ // Both valid services should unbind now.
+ assertValidCompanionDeviceServicesUnbind()
}
@Test
@@ -220,21 +163,12 @@
}
// Make sure CDM binds both CompanionDeviceServices.
- assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
- "now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
- }
- }
+ assertValidCompanionDeviceServicesBind()
// Notify CDM that devices has disconnected.
cdm.notifyDeviceDisappeared(associationId)
// Make sure CDM unbinds both CompanionDeviceServices.
- assertTrue("Both Services - Primary and Secondary - should be unbound now") {
- waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
- !PrimaryCompanionService.isBound && !SecondaryCompanionService.isBound
- }
- }
+ assertValidCompanionDeviceServicesUnbind()
}
}
\ No newline at end of file
diff --git a/tests/tests/cronet/Android.bp b/tests/tests/cronet/Android.bp
deleted file mode 100644
index fc8ec7f..0000000
--- a/tests/tests/cronet/Android.bp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-// TODO: Move this target to cts/tests/tests/net/cronet
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test {
- name: "CtsCronetTestCases",
- defaults: ["cts_defaults"],
-
- // Include both the 32 and 64 bit versions
- compile_multilib: "both",
-
- static_libs: [
- "CronetApiCommonTests",
- "ctstestrunner-axt",
- ],
-
- // Tag this module as a cts test artifact
- test_suites: [
- "cts",
- "general-tests",
- "mts-cronet",
- ],
-
-}
diff --git a/tests/tests/cronet/AndroidManifest.xml b/tests/tests/cronet/AndroidManifest.xml
deleted file mode 100644
index b7ae844..0000000
--- a/tests/tests/cronet/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open 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.cronet.cts" >
-
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.INTERNET" />
-
- <application android:usesCleartextTraffic="true">
- <uses-library android:name="android.test.runner" />
- <uses-library android:name="org.chromium.net.cronet" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.cronet.cts"
- android:label="CTS tests of android.cronet">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
diff --git a/tests/tests/cronet/AndroidTest.xml b/tests/tests/cronet/AndroidTest.xml
deleted file mode 100644
index 79c37f7..0000000
--- a/tests/tests/cronet/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Config for CTS Cronet test cases">
- <option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="networking" />
- <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
- <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="CtsCronetTestCases.apk" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.cronet.cts" />
- <option name="runtime-hint" value="10s" />
- </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/tests/cronet/OWNERS b/tests/tests/cronet/OWNERS
deleted file mode 100644
index 9b1555e..0000000
--- a/tests/tests/cronet/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 31808
-set noparent
-include platform/packages/modules/Connectivity:/tests/cts/OWNERS
diff --git a/tests/tests/cronet/TEST_MAPPING b/tests/tests/cronet/TEST_MAPPING
deleted file mode 100644
index b1f3088..0000000
--- a/tests/tests/cronet/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit": [
- {
- "name": "CtsCronetTestCases"
- }
- ]
-}
diff --git a/tests/tests/dreams/src/android/service/dreams/cts/DreamOverlayTest.java b/tests/tests/dreams/src/android/service/dreams/cts/DreamOverlayTest.java
index fed0c91..8c836fa 100644
--- a/tests/tests/dreams/src/android/service/dreams/cts/DreamOverlayTest.java
+++ b/tests/tests/dreams/src/android/service/dreams/cts/DreamOverlayTest.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.server.wm.ActivityManagerTestBase;
import android.server.wm.DreamCoordinator;
import android.view.Display;
@@ -31,6 +32,7 @@
import static com.google.common.truth.Truth.assertThat;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -84,6 +86,9 @@
@Test
public void testDreamOverlayAppearance() throws InterruptedException {
+ Assume.assumeFalse(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+
// Listen for the overlay to be shown
final CountDownLatch countDownLatch = new CountDownLatch(1);
mContext.registerReceiver(
diff --git a/tests/tests/graphics/res/xml/valid_themes.xml b/tests/tests/graphics/res/xml/valid_themes.xml
index 64437f9..ad8b953 100644
--- a/tests/tests/graphics/res/xml/valid_themes.xml
+++ b/tests/tests/graphics/res/xml/valid_themes.xml
@@ -19,48 +19,48 @@
<theme color="ffb9567a">
<spritz>ffffff,fffbfa,ffecf1,f9dbe2,dcc0c6,c0a4ab,a48a91,877076,6f595e,564147,3e2b31,27171c,000000,ffffff,fffbfa,ffecf1,f2dee2,d5c2c6,b9a6aa,9e8c90,827276,6a5a5e,514347,392d30,23191b,000000,ffffff,fffbfa,ffecf1,ffd9e2,e2bdc6,c5a2ab,a98891,8d6e76,74565f,5b3f47,422a31,2b151c,000000,ffffff,fffbfa,f6efef,e8e1e1,cbc5c5,b0aaaa,958f90,7a7575,625d5e,4a4646,333030,1e1b1b,000000,ffffff,fffbfa,f6efef,e8e1e1,cbc5c5,b0aaaa,958f90,7a7575,625d5e,4a4646,333030,1e1b1b,000000</spritz>
<tonal_spot>ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,e495ad,c57b93,a76078,8c4a60,703349,541d32,39071d,000000,ffffff,fffbfa,ffecf1,ffd9e2,e2bdc6,c5a2ab,a98891,8d6e76,74565f,5b3f47,422a31,2b151c,000000,ffffff,fffbfa,ffeddf,ffdcbf,efbc94,d1a27a,b48762,976d4a,7c5635,623f20,48290b,2f1500,000000,ffffff,fffbfa,faeeef,ebe0e1,cfc4c5,b3a8aa,988f90,7d7475,655c5e,4c4546,352f30,201a1c,000000,ffffff,fffbfa,ffecf1,f2dee2,d5c2c6,b9a6aa,9e8c90,827276,6a5a5e,514347,392d30,23191b,000000</tonal_spot>
- <vibrant>ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,f889ae,d86f94,b85579,9b3e61,7d2649,600d33,3e001c,000000,ffffff,fffbfa,ffecf1,ffd9e4,efb7c7,d29dac,b58392,986977,7e525f,633b48,4a2531,31101d,000000,ffffff,fffbfa,ffecf1,ffd9e4,fcb2c8,de98ad,c07e92,a26378,874c60,6b3648,511f32,370b1d,000000,ffffff,fffbfa,ffecf1,f6dce2,d9c0c6,bca5ab,a18b91,857175,6c5a5e,534247,3c2c31,25181c,000000,ffffff,fffbfa,ffecf1,f9dbe2,dcc0c6,c0a4ab,a48a91,877076,6f595e,564147,3e2b31,27171c,000000</vibrant>
- <expressive>ffffff,fafcff,e4f2ff,c7e7ff,8bcefd,6eb3e0,5297c4,337da7,0b648e,004c6f,00344e,001e2f,000000,ffffff,fffbfa,ffecf1,ffd9e4,efb7c7,d29dac,b58392,986977,7e525f,633b48,4a2531,31101d,000000,ffffff,fffbfa,ffecf1,ffd9e4,fcb2c8,de98ad,c07e92,a26378,874c60,6b3648,511f32,370b1d,000000,ffffff,fffbfa,ffeded,f4ddde,d7c1c2,bba7a7,9f8c8d,837272,6b5b5b,534344,3b2d2d,241919,000000,ffffff,fffbfa,ffeced,fcdbdb,debfc0,c2a4a5,a68a8b,8a6f70,715859,574142,402b2c,281718,000000</expressive>
+ <vibrant>ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,f889ae,d86f94,b85579,9b3e61,7d2649,600d33,3e001c,000000,ffffff,fffbfa,ffeceb,ffdad9,f5b7b7,d79c9c,b98382,9c6869,815152,663a3b,4c2525,331012,000000,ffffff,fffbfa,ffede7,ffdacf,ffb49d,e49882,c57f6a,a66551,8b4e3c,6e3727,532213,380d03,000000,ffffff,fffbfa,ffecf1,f9dbe2,dcc0c6,c0a4ab,a48a91,877076,6f595e,564147,3e2b31,27171c,000000,ffffff,fffbfa,ffecf1,fcdae2,dfbec6,c3a3ab,a78991,8a6f76,71575f,584047,402a31,29161c,000000</vibrant>
+ <expressive>ffffff,fafcff,e4f2ff,c7e7ff,8bcefd,6eb3e0,5297c4,337da7,0b648e,004c6f,00344e,001e2f,000000,ffffff,fffbfa,ffede4,ffdbc9,f4ba9e,d69f84,b9856c,9b6b53,80543d,653d28,4a2714,311303,000000,ffffff,fcffd6,ecf8ad,dee9a0,c1cd86,a6b16e,8c9656,717b3e,5a6328,424b12,2b3400,181e00,000000,ffffff,fffbfa,ffeded,f4ddde,d7c1c2,bba7a7,9f8c8d,837272,6b5b5b,534344,3b2d2d,241919,000000,ffffff,fffbfa,ffeced,fcdbdb,debfc0,c2a4a5,a68a8b,8a6f70,715859,574142,402b2c,281718,000000</expressive>
<rainbow>ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,f48aae,d57294,b55779,984061,7b2849,5e1033,3e001c,000000,ffffff,fffbfa,ffecf1,ffd9e2,e2bdc6,c5a2ab,a98891,8d6e76,74565f,5b3f47,422a31,2b151c,000000,ffffff,fffbfa,ffeddf,ffdcbf,efbc94,d1a27a,b48762,976d4a,7c5635,623f20,48290b,2f1500,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
<fruit_salad>ffffff,fffbfb,faecff,f1dbff,deb8ff,c499f1,a97ed4,8c64b7,734c9d,5b3383,431a6b,2b0053,000000,ffffff,fffbfb,faecff,f1dbff,dabaf9,be9edc,a384c0,866aa4,6e538b,553b71,3d2458,270d42,000000,ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,e495ad,c57b93,a76078,8c4a60,703349,541d32,39071d,000000,ffffff,fffbfa,ffecf1,f6dce2,d9c0c6,bca5ab,a18b91,857175,6c5a5e,534247,3c2c31,25181c,000000,ffffff,fffbfa,ffecf1,ffd9e2,e2bdc6,c5a2ab,a98891,8d6e76,74565f,5b3f47,422a31,2b151c,000000</fruit_salad>
</theme>
<theme color="ffb16307">
<spritz>ffffff,fffbfa,ffeddf,faddc9,dcc2ae,c0a794,a48c7a,887261,6f5b4a,564334,3e2d1f,27180c,000000,ffffff,fffbfa,ffede0,f3dfd1,d5c3b6,baa89c,9e8e82,837368,6a5b51,51443b,3a2e26,231a12,000000,ffffff,fffbfa,ffeddf,ffdcc1,e2c0a5,c5a58b,aa8b72,8d705a,745943,5a422d,412c19,2a1707,000000,ffffff,fffbfa,f7efec,e8e1de,ccc5c2,b0aaa7,958f8d,7a7572,625e5b,4a4643,33302d,1d1b19,000000,ffffff,fffbfa,f7efec,e8e1de,ccc5c2,b0aaa7,958f8d,7a7572,625e5b,4a4643,33302d,1d1b19,000000</spritz>
<tonal_spot>ffffff,fffbfa,ffeddf,ffdcbf,ffb879,e19d61,c28349,a46932,88521c,6b3b05,4d2700,2f1500,000000,ffffff,fffbfa,ffeddf,ffdcc1,e2c0a5,c5a58b,aa8b72,8d705a,745943,5a422d,412c19,2a1707,000000,ffffff,fdffd7,eef5be,e0e8b1,c4cb97,a8af7e,8e9565,727a4d,5b6238,444a22,2d330e,191e00,000000,ffffff,fffbfa,faeee8,ece0da,cfc4be,b3a9a3,988f89,7d746f,655d58,4c4641,362f2b,201a16,000000,ffffff,fffbfa,ffede0,f3dfd1,d5c3b6,baa89c,9e8e82,837368,6a5b51,51443b,3a2e26,231a12,000000</tonal_spot>
- <vibrant>ffffff,fffbfa,ffeddf,ffdcbf,ffb776,f1963f,d17c26,b06306,8f4e00,6d3900,4d2700,2f1500,000000,ffffff,fffbfa,ffecf0,ffd9e3,f0b8c6,d29dab,b68391,986976,7e525e,643b47,4a2531,31111c,000000,ffffff,fffbfa,ffecf0,ffd9e3,fcb2c7,de97ac,c17d91,a26377,874d5f,6c3547,512031,370b1c,000000,ffffff,fffbfa,ffeddf,f6decd,d9c2b2,bda798,a18d7e,857264,6c5b4e,534437,3c2d22,26190f,000000,ffffff,fffbfa,ffeddf,faddc9,dcc2ae,c0a794,a48c7a,887261,6f5b4a,564334,3e2d1f,27180c,000000</vibrant>
- <expressive>ffffff,fffbfd,f7edff,eadcff,d1bcff,b5a0e8,9a85cc,7e6baf,665395,4e3c7c,372464,220b4e,000000,ffffff,fffbfa,ffedea,ffdad7,f5b8b4,d79c99,ba8380,9c6966,81524f,663b39,4d2524,321110,000000,ffffff,fffbfa,ffedea,ffdad6,ffb3b0,e49794,c67d7a,a76461,8b4c4a,6f3634,542020,380c0c,000000,ffffff,fffbf9,feeedd,efe0cf,d3c4b5,b7a99a,9b8f80,807467,675d50,4f4539,382f24,221a10,000000,ffffff,fffbf9,ffeed9,f5dfc6,d8c4ab,bca891,a08e77,84745e,6b5c48,534432,3b2e1d,241a0a,000000</expressive>
+ <vibrant>ffffff,fffbfa,ffeddf,ffdcbf,ffb776,f1963f,d17c26,b06306,8f4e00,6d3900,4d2700,2f1500,000000,ffffff,fffbf9,ffeedb,ffddb3,e9c08e,cba475,af8a5e,917045,785830,5d411b,442b07,2a1700,000000,ffffff,fffbf8,ffefd2,ffde9c,e7c277,caa75f,ad8c48,907230,775a1a,5c4301,412d00,261900,000000,ffffff,fffbfa,ffeddf,faddc9,dcc2ae,c0a794,a48c7a,887261,6f5b4a,564334,3e2d1f,27180c,000000,ffffff,fffbfa,ffeddf,fddcc4,dfc1a9,c3a58f,a78b76,8a715d,715a47,584331,402c1c,281809,000000</vibrant>
+ <expressive>ffffff,fffbfd,f7edff,eadcff,d1bcff,b5a0e8,9a85cc,7e6baf,665395,4e3c7c,372464,220b4e,000000,ffffff,fffbf7,fbf2b7,ece4a9,d0c88f,b4ad77,99925e,7e7747,656031,4d481c,363107,1f1c00,000000,ffffff,f0fffa,b9ffec,abf0de,8fd4c2,74b8a7,599d8d,3d8173,22695b,005143,00382e,002019,000000,ffffff,fffbf9,feeedd,efe0cf,d3c4b5,b7a99a,9b8f80,807467,675d50,4f4539,382f24,221a10,000000,ffffff,fffbf9,ffeed9,f5dfc6,d8c4ab,bca891,a08e77,84745e,6b5c48,534432,3b2e1d,241a0a,000000</expressive>
<rainbow>ffffff,fffbfa,ffeddf,ffdcbf,ffb776,ee9744,cf7d2c,af6311,8f4d00,6d3900,4d2700,2f1500,000000,ffffff,fffbfa,ffeddf,ffdcc1,e2c0a5,c5a58b,aa8b72,8d705a,745943,5a422d,412c19,2a1707,000000,ffffff,fdffd7,eef5be,e0e8b1,c4cb97,a8af7e,8e9565,727a4d,5b6238,444a22,2d330e,191e00,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
<fruit_salad>ffffff,fffbfa,ffedef,ffdadf,ffb2be,f98b9c,d97082,b85769,9c4052,7d293b,5f1126,400012,000000,ffffff,fffbfa,ffedef,ffdadf,ffb2be,e894a0,c97a86,aa606c,8e4a55,72333e,561c28,3b0714,000000,ffffff,fffbfa,ffeddf,ffdcbf,ffb879,e19d61,c28349,a46932,88521c,6b3b05,4d2700,2f1500,000000,ffffff,fffbfa,ffeddf,f6decd,d9c2b2,bda798,a18d7e,857264,6c5b4e,534437,3c2d22,26190f,000000,ffffff,fffbfa,ffeddf,ffdcc1,e2c0a5,c5a58b,aa8b72,8d705a,745943,5a422d,412c19,2a1707,000000</fruit_salad>
</theme>
<theme color="ff6e7e0f">
<spritz>ffffff,fdfee4,f1f2d8,e3e4cb,c7c8b0,abad96,90927c,757862,5e604c,464835,2f3220,1a1d0d,000000,ffffff,fefdec,f2f2e0,e4e4d3,c7c7b7,acac9d,919283,767769,5e6052,46483b,303126,1b1c12,000000,ffffff,fcffdc,f0f3d0,e2e5c2,c6c9a8,aaae8e,909375,74795b,5c6145,454930,2f321b,1a1d08,000000,ffffff,fffbf7,f4f0ec,e5e2dd,c9c6c2,adaba7,92918d,777672,605e5b,474744,31302e,1c1b19,000000,ffffff,fffbf7,f4f0ec,e5e2dd,c9c6c2,adaba7,92918d,777672,605e5b,474744,31302e,1c1b19,000000</spritz>
<tonal_spot>ffffff,fcffd5,ebf8a4,ddea96,c1cd7d,a5b264,8b974d,707c35,596320,414b08,2b3400,181e00,000000,ffffff,fcffdc,f0f3d0,e2e5c2,c6c9a8,aaae8e,909375,74795b,5c6145,454930,2f321b,1a1d08,000000,ffffff,f0fffa,cbfbed,bdeddf,a1d0c3,87b4a8,6d9a8e,527e73,3b665c,224e45,05372f,002019,000000,ffffff,fffcf4,f3f1e8,e5e3da,c8c7bf,adaba4,929189,777670,5f5f58,474741,30312b,1c1c17,000000,ffffff,fefdec,f2f2e0,e4e4d3,c7c7b7,acac9d,919283,767769,5e6052,46483b,303126,1b1c12,000000</tonal_spot>
- <vibrant>ffffff,fdffd7,eaf99a,d9ed76,bdd05d,a2b444,87992c,6e7d0e,566500,404c00,2b3400,181e00,000000,ffffff,fffbfa,ffeddf,ffdcbe,eebd93,d0a27a,b48762,966e4a,7c5635,613f20,48290b,2e1500,000000,ffffff,fffbfa,ffeddf,ffdcbe,fab981,db9e69,bd8551,9f6b3a,845325,683d0f,4d2700,2e1500,000000,ffffff,fdfee7,f2f2dd,e3e4ce,c7c8b3,abad99,919280,767766,5e604f,464839,2f3223,1a1d0f,000000,ffffff,fdfee4,f1f2d8,e3e4cb,c7c8b0,abad96,90927c,757862,5e604c,464835,2f3220,1a1d0d,000000</vibrant>
- <expressive>ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,e992ae,cb7793,ac5e78,904761,732f49,581933,3c031e,000000,ffffff,fffbf9,ffeed4,ffdea7,e3c28c,c6a673,aa8c5c,8d7243,735b2e,594319,412d05,281900,000000,ffffff,fffbf9,ffeed4,ffdea6,eac077,cea560,b08b48,937030,78591a,5e4102,422c00,281900,000000,ffffff,fafeef,eff2e4,e1e4d6,c4c8bb,a8ad9f,8e9286,73786b,5b6055,44483e,2d3228,181d14,000000,ffffff,f9ffea,ebf4dd,dde5cf,c1cab4,a6ae9a,8b9380,707966,59614f,424939,2b3324,171e10,000000</expressive>
+ <vibrant>ffffff,fdffd7,eaf99a,d9ed76,bdd05d,a2b444,87992c,6e7d0e,566500,404c00,2b3400,181e00,000000,ffffff,f8ffe3,e4f8c7,d6e9b9,bacd9f,9fb185,85976c,6a7c53,53643e,3c4c28,263514,121f03,000000,ffffff,f5ffec,d1fdc5,c3eeb8,a7d29e,8db684,739b6b,598053,42673d,2a4f27,133812,002202,000000,ffffff,fdfee4,f1f2d8,e3e4cb,c7c8b0,abad96,90927c,757862,5e604c,464835,2f3220,1a1d0d,000000,ffffff,fcffdf,f1f3d4,e2e5c7,c6c9ab,abae91,8f9378,75785f,5d6048,454932,2f321e,1a1d0b,000000</vibrant>
+ <expressive>ffffff,fffbfa,ffecf1,ffd9e4,ffb0ca,e992ae,cb7793,ac5e78,904761,732f49,581933,3c031e,000000,ffffff,f2fff6,d0fbe1,c2ecd3,a7d0b8,8cb49d,729983,587e6a,406653,284e3c,103727,002113,000000,ffffff,fafcff,e4f2ff,c7e7ff,9ccdf0,81b1d3,6696b8,4b7b9c,316383,134b6a,00344e,001e2f,000000,ffffff,fafeef,eff2e4,e1e4d6,c4c8bb,a8ad9f,8e9286,73786b,5b6055,44483e,2d3228,181d14,000000,ffffff,f9ffea,ebf4dd,dde5cf,c1cab4,a6ae9a,8b9380,707966,59614f,424939,2b3324,171e10,000000</expressive>
<rainbow>ffffff,fdffd7,eaf99a,daec7b,becf61,a2b449,889931,6e7d16,566500,404c00,2b3400,181e00,000000,ffffff,fcffdc,f0f3d0,e2e5c2,c6c9a8,aaae8e,909375,74795b,5c6145,454930,2f321b,1a1d08,000000,ffffff,f0fffa,cbfbed,bdeddf,a1d0c3,87b4a8,6d9a8e,527e73,3b665c,224e45,05372f,002019,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
<fruit_salad>ffffff,fffbf9,ffeedc,ffddb6,ffb85d,e69c38,c7821d,a76800,875300,663d00,482a00,2b1700,000000,ffffff,fffbf9,ffeedc,ffddb6,f8bb71,daa059,bc8641,9e6b2a,825414,663d00,482a00,2b1700,000000,ffffff,fcffd5,ebf8a4,ddea96,c1cd7d,a5b264,8b974d,707c35,596320,414b08,2b3400,181e00,000000,ffffff,fdfee7,f2f2dd,e3e4ce,c7c8b3,abad99,919280,767766,5e604f,464839,2f3223,1a1d0f,000000,ffffff,fcffdc,f0f3d0,e2e5c2,c6c9a8,aaae8e,909375,74795b,5c6145,454930,2f321b,1a1d08,000000</fruit_salad>
</theme>
<theme color="ff008772">
<spritz>ffffff,f0fffa,e2f5ed,d4e7df,b8cbc4,9dafa9,83958e,687a74,51625c,3a4a45,23342f,0f1e1a,000000,ffffff,f4fefa,e9f3ef,dae5e0,bec9c4,a3ada9,88938f,6e7875,57615d,3f4945,29322f,141d1b,000000,ffffff,f0fffa,dbf7ed,cde9df,b1ccc3,96b1a8,7d968e,627b74,4b635c,334b45,1c352e,06201a,000000,ffffff,fdfcfb,f2f1ef,e3e2e1,c7c7c5,ababaa,90918f,767675,5e5e5d,464746,2f3130,1a1c1b,000000,ffffff,fdfcfb,f2f1ef,e3e2e1,c7c7c5,ababaa,90918f,767675,5e5e5d,464746,2f3130,1a1c1b,000000</spritz>
<tonal_spot>ffffff,f0fffa,b3ffec,a1f2dd,85d5c1,69baa6,4e9e8c,308372,086b5a,005143,00382d,002019,000000,ffffff,f0fffa,dbf7ed,cde9df,b1ccc3,96b1a8,7d968e,627b74,4b635c,334b45,1c352e,06201a,000000,ffffff,fafcff,e4f3ff,c6e7ff,aacae3,8fafc8,7594ac,5a7a90,426278,2a4a5f,103447,001e2f,000000,ffffff,fafdfa,eff1ef,e0e3e0,c4c7c5,a8aca9,8e918f,737775,5c5f5d,444846,2e3130,191c1b,000000,ffffff,f4fefa,e9f3ef,dae5e0,bec9c4,a3ada9,88938f,6e7875,57615d,3f4945,29322f,141d1b,000000</tonal_spot>
- <vibrant>ffffff,f0fffa,b3ffec,79f8da,5bdbbf,37bfa4,00a38a,00856f,006b59,005143,00382d,002019,000000,ffffff,fdffd8,eef6be,e0e8b1,c4cb97,a8af7e,8e9565,727a4d,5b6238,444a22,2d330e,181e00,000000,ffffff,fdffd8,ecf7ad,dee9a0,c1cd86,a6b16e,8c9656,717b3e,5a6329,424b12,2b3400,181e00,000000,ffffff,f1fffa,e5f4ee,d7e6e0,bbcac4,a0aea9,86948e,6c7974,54615d,3d4945,26332f,111e1a,000000,ffffff,f0fffa,e2f5ed,d4e7df,b8cbc4,9dafa9,83958e,687a74,51625c,3a4a45,23342f,0f1e1a,000000</vibrant>
- <expressive>ffffff,fffbfa,ffede0,ffdcc0,ffb778,e69a59,c78041,a86729,8b5013,6e3900,4d2600,2f1500,000000,ffffff,f6ffe9,def9cd,d0eabf,b5cea5,99b38b,7f9872,657d59,4e6543,374c2d,213618,0c2006,000000,ffffff,f6ffe9,d5fcc1,c7eeb3,acd199,92b580,789a67,5e7f4e,466738,304e23,1a370f,042100,000000,ffffff,f4fffd,e9f3f1,dae5e3,bec9c7,a3adac,889391,6e7877,566060,3f4848,293232,141d1d,000000,ffffff,effffe,e2f5f3,d4e6e5,b8cac9,9dafad,829493,687978,506260,394a48,233333,0e1e1e,000000</expressive>
+ <vibrant>ffffff,f0fffa,b3ffec,79f8da,5bdbbf,37bfa4,00a38a,00856f,006b59,005143,00382d,002019,000000,ffffff,effffd,cafaf5,bbece7,a0cfcb,85b4af,6b9995,517e7a,396662,1f4e4a,013734,00201e,000000,ffffff,efffff,befbff,a8eef5,8dd2d8,71b6bd,569ba1,398086,1a686e,004f54,00363a,002022,000000,ffffff,f0fffa,e2f5ed,d4e7df,b8cbc4,9dafa9,83958e,687a74,51625c,3a4a45,23342f,0f1e1a,000000,ffffff,f0fffa,dff6ed,d1e7df,b5ccc4,9ab0a8,80958e,657b74,4e635c,364b45,21342f,0b1f1b,000000</vibrant>
+ <expressive>ffffff,fffbfa,ffede0,ffdcc0,ffb778,e69a59,c78041,a86729,8b5013,6e3900,4d2600,2f1500,000000,ffffff,f8fdff,dcf5ff,c0e9fa,a4cddd,8ab1c2,6f96a6,547c8b,3c6472,234c5a,063543,001f29,000000,ffffff,fffbfe,f6edff,eaddff,cfbef7,b2a3da,9788be,7d6ea2,645788,4c3f6f,352857,201241,000000,ffffff,f4fffd,e9f3f1,dae5e3,bec9c7,a3adac,889391,6e7877,566060,3f4848,293232,141d1d,000000,ffffff,effffe,e2f5f3,d4e6e5,b8cac9,9dafad,829493,687978,506260,394a48,233333,0e1e1e,000000</expressive>
<rainbow>ffffff,f0fffa,b3ffec,79f8da,5bdbbf,37bfa4,00a38a,00856f,006b59,005143,00382d,002019,000000,ffffff,f0fffa,dbf7ed,cde9df,b1ccc3,96b1a8,7d968e,627b74,4b635c,334b45,1c352e,06201a,000000,ffffff,fafcff,e4f3ff,c6e7ff,aacae3,8fafc8,7594ac,5a7a90,426278,2a4a5f,103447,001e2f,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
<fruit_salad>ffffff,f9ffe1,ddfca5,c9ef88,aed36f,93b757,799c3e,608026,48680d,334f00,213600,121f00,000000,ffffff,f9ffe1,dffbad,d1eca0,b5d086,9ab46e,809956,667e3e,4f6628,384d13,233600,121f00,000000,ffffff,f0fffa,b3ffec,a1f2dd,85d5c1,69baa6,4e9e8c,308372,086b5a,005143,00382d,002019,000000,ffffff,f1fffa,e5f4ee,d7e6e0,bbcac4,a0aea9,86948e,6c7974,54615d,3d4945,26332f,111e1a,000000,ffffff,f0fffa,dbf7ed,cde9df,b1ccc3,96b1a8,7d968e,627b74,4b635c,334b45,1c352e,06201a,000000</fruit_salad>
</theme>
<theme color="ff007fb6">
<spritz>ffffff,fafcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7882,546069,3d4852,27323a,111d25,000000,ffffff,fafcff,ecf1f9,dee3ea,c2c7ce,a6acb2,8b9198,70777d,595f65,41474d,2b3137,171c21,000000,ffffff,fafcff,e4f2ff,d3e5f5,b7c9d8,9caebd,8193a1,677887,50606e,384956,22323f,0c1d29,000000,ffffff,fefcfc,f2f0f1,e4e2e3,c7c6c7,acabab,919192,767677,5e5e5f,464748,303031,1b1b1c,000000,ffffff,fefcfc,f2f0f1,e4e2e3,c7c6c7,acabab,919192,767677,5e5e5f,464748,303031,1b1b1c,000000</spritz>
<tonal_spot>ffffff,fafcff,e4f2ff,c7e6ff,94cdf7,79b1da,5e97be,417ca2,256489,004b6f,00344f,001e30,000000,ffffff,fafcff,e4f2ff,d3e5f5,b7c9d8,9caebd,8193a1,677887,50606e,384956,22323f,0c1d29,000000,ffffff,fffbfd,f7edff,ebdcff,cfc0e9,b2a5cc,978bb0,7c7095,64597b,4c4163,352b4a,201634,000000,ffffff,fbfcff,f0f0f3,e2e2e5,c6c6c9,aaabae,909194,757679,5c5e61,454749,2f3032,191c1e,000000,ffffff,fafcff,ecf1f9,dee3ea,c2c7ce,a6acb2,8b9198,70777d,595f65,41474d,2b3137,171c21,000000</tonal_spot>
- <vibrant>ffffff,fafcff,e4f2ff,c7e6ff,86ceff,57b4ee,3599d2,007db5,006492,004b6f,00344f,001e30,000000,ffffff,f0fffb,cbfaee,bdece1,a1d0c4,87b4aa,6c9a8f,527e75,3a665d,214e46,043730,00201a,000000,ffffff,f0fffb,b8feee,aaf0e1,8ed4c4,73b8a9,589d8f,3c8275,21695d,005045,00382f,00201a,000000,ffffff,fafcff,e9f1fb,dbe4ed,bfc8d1,a4acb5,89919a,6e777f,576067,3f484f,293138,141c23,000000,ffffff,fafcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7882,546069,3d4852,27323a,111d25,000000</vibrant>
- <expressive>ffffff,fcffd8,e8fa9c,d9eb8f,bdcf76,a3b35d,889846,6e7c2e,566417,3f4c00,2a3500,171e00,000000,ffffff,efffff,cafafc,bcebee,a0cfd1,85b3b6,6b989b,507d80,386568,1e4d50,003739,002022,000000,ffffff,efffff,b9fcff,a8eff3,8cd2d7,71b6bb,559ca0,388085,1a686d,004f53,00373a,002022,000000,ffffff,fdfcff,edf0fa,dfe2eb,c3c7cf,a8abb4,8d9099,72767e,5a5e66,43474e,2d3137,171c22,000000,ffffff,fdfcff,e9f1ff,dbe3f1,bfc7d5,a4acb9,8a919f,6f7783,575f6b,404753,29313b,141c26,000000</expressive>
+ <vibrant>ffffff,fafcff,e4f2ff,c7e6ff,86ceff,57b4ee,3599d2,007db5,006492,004b6f,00344f,001e30,000000,ffffff,fcfcff,e8f1ff,cfe4ff,b1c9e8,96adcc,7b92b0,617894,4a607b,314962,19324a,011d34,000000,ffffff,fdfbff,ecf0ff,d6e2ff,b1c7f9,95abdc,7b90c0,6076a3,485e8a,314671,183059,001a43,000000,ffffff,fafcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7882,546069,3d4852,27323a,111d25,000000,ffffff,fafcff,e4f2ff,d6e4f3,bac8d6,9fadba,84929f,697884,52606c,3a4853,24323c,0e1d27,000000</vibrant>
+ <expressive>ffffff,fcffd8,e8fa9c,d9eb8f,bdcf76,a3b35d,889846,6e7c2e,566417,3f4c00,2a3500,171e00,000000,ffffff,fefbff,f1efff,e2dfff,c4c3ea,a9a7ce,8e8db3,737396,5c5b7d,444364,2d2d4d,191837,000000,ffffff,fffbfa,ffecf0,ffd9e3,fdb2c6,df97ab,c17e91,a36476,874c5f,6c3647,511f31,370b1c,000000,ffffff,fdfcff,edf0fa,dfe2eb,c3c7cf,a8abb4,8d9099,72767e,5a5e66,43474e,2d3137,171c22,000000,ffffff,fdfcff,e9f1ff,dbe3f1,bfc7d5,a4acb9,8a919f,6f7783,575f6b,404753,29313b,141c26,000000</expressive>
<rainbow>ffffff,fafcff,e4f2ff,c7e6ff,86ceff,57b4ee,3599d2,007db5,006492,004b6f,00344f,001e30,000000,ffffff,fafcff,e4f2ff,d3e5f5,b7c9d8,9caebd,8193a1,677887,50606e,384956,22323f,0c1d29,000000,ffffff,fffbfd,f7edff,ebdcff,cfc0e9,b2a5cc,978bb0,7c7095,64597b,4c4163,352b4a,201634,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
<fruit_salad>ffffff,effffd,affff9,71f7ee,4fdbd2,24beb6,00a29a,00847d,006a64,00504b,003733,00201e,000000,ffffff,effffd,affff9,9df1ea,80d5ce,65b9b3,489e98,27837d,006a65,00504b,003734,00201e,000000,ffffff,fafcff,e4f2ff,c7e6ff,94cdf7,79b1da,5e97be,417ca2,256489,004b6f,00344f,001e30,000000,ffffff,fafcff,e9f1fb,dbe4ed,bfc8d1,a4acb5,89919a,6e777f,576067,3f484f,293138,141c23,000000,ffffff,fafcff,e4f2ff,d3e5f5,b7c9d8,9caebd,8193a1,677887,50606e,384956,22323f,0c1d29,000000</fruit_salad>
</theme>
<theme color="ff8267c2">
<spritz>ffffff,fffbfd,f6eeff,e8dff1,cbc4d5,b0a8ba,958e9e,7a7383,615c6b,4a4453,332e3c,1d1a26,000000,ffffff,fffbfd,f5eefa,e7e0eb,cbc4cf,afa9b4,948f99,79747e,615c66,49454f,322f37,1d1a22,000000,ffffff,fffbfd,f7edff,e9def8,ccc3dc,b1a7c0,958da4,7a7389,625b71,4a4358,332d41,1e182b,000000,ffffff,fffbfd,f4eff1,e6e1e3,cac5c7,aeaaac,939091,787577,605e5f,484648,313031,1c1b1d,000000,ffffff,fffbfd,f4eff1,e6e1e3,cac5c7,aeaaac,939091,787577,605e5f,484648,313031,1c1b1d,000000</spritz>
<tonal_spot>ffffff,fffbfd,f7edff,ebddff,d1bcfe,b5a1e1,9987c4,7e6da8,66558e,4d3d75,37265d,211047,000000,ffffff,fffbfd,f7edff,e9def8,ccc3dc,b1a7c0,958da4,7a7389,625b71,4a4358,332d41,1e182b,000000,ffffff,fffbfa,ffecf0,ffd8e3,f0b7c7,d29dab,b68391,986976,7e525f,633b48,4a2531,31101c,000000,ffffff,fffbfd,f5eff4,e6e1e5,c9c5c9,aeaaae,939094,787579,605d62,484649,313033,1c1b1e,000000,ffffff,fffbfd,f5eefa,e7e0eb,cbc4cf,afa9b4,948f99,79747e,615c66,49454f,322f37,1d1a22,000000</tonal_spot>
- <vibrant>ffffff,fffbfd,f7edff,ebddff,d2bcff,b89bfb,9d81de,8166c1,694ea7,51358d,391c76,22005c,000000,ffffff,fafcff,e4f2ff,c7e6ff,abcbe4,90afc8,7694ad,5b7991,436278,2b4a5f,123348,001e30,000000,ffffff,fafcff,e4f2ff,c7e6ff,9dccf0,82b0d4,6796b8,4c7b9c,336383,154b6a,00344f,001e30,000000,ffffff,fffbfd,f5eefd,e7e0ee,cbc3d2,afa8b6,948e9c,797480,615c69,494550,322f3a,1d1a24,000000,ffffff,fffbfd,f6eeff,e8dff1,cbc4d5,b0a8ba,958e9e,7a7383,615c6b,4a4453,332e3c,1d1a26,000000</vibrant>
- <expressive>ffffff,f0fffa,b5ffee,95f4de,78d8c2,5bbca7,3ea08d,168572,006b5a,005144,00382e,00201a,000000,ffffff,fdfcff,ebf1ff,d4e3ff,b6c7ea,9aaccd,8092b1,657795,4e5f7c,364764,1f314c,071c36,000000,ffffff,fdfcff,ebf1ff,d4e3ff,acc7f8,92acdb,7792bf,5c77a3,455f8a,2c4770,123158,001b3d,000000,ffffff,fffbfb,f8eef8,eadfea,cdc4ce,b2a8b3,968e98,7b747d,645c65,4b454d,342f37,1f1a21,000000,ffffff,fffbfb,fbecfd,ecdeef,d0c2d3,b4a7b7,998d9c,7e7282,655b69,4d4451,362d3b,201925,000000</expressive>
+ <vibrant>ffffff,fffbfd,f7edff,ebddff,d2bcff,b89bfb,9d81de,8166c1,694ea7,51358d,391c76,22005c,000000,ffffff,fffbfb,fbebff,f3daff,d6bee5,baa3c9,9e89ad,836e91,6a5778,514060,3a2a48,241532,000000,ffffff,fffbfb,ffeaff,ffd6ff,e5b8e9,c89dcd,ac83b1,906996,77517c,5d3a63,45234b,2e0d35,000000,ffffff,fffbfd,f6eeff,e8dff1,cbc4d5,b0a8ba,958e9e,7a7383,615c6b,4a4453,332e3c,1d1a26,000000,ffffff,fffbfd,f7edff,e8dff5,cbc3d8,b0a8bc,958ea1,797386,625b6e,494455,332e3e,1e1928,000000</vibrant>
+ <expressive>ffffff,f0fffa,b5ffee,95f4de,78d8c2,5bbca7,3ea08d,168572,006b5a,005144,00382e,00201a,000000,ffffff,fffbfa,ffebf5,ffd7ed,e9b9d2,cc9eb8,af849c,926a81,795369,5f3c51,46263a,2e1124,000000,ffffff,fffbfa,ffeddf,ffdcbf,fab982,dc9e69,be8452,9f6a3a,845325,683d0f,4d2700,2e1500,000000,ffffff,fffbfb,f8eef8,eadfea,cdc4ce,b2a8b3,968e98,7b747d,645c65,4b454d,342f37,1f1a21,000000,ffffff,fffbfb,fbecfd,ecdeef,d0c2d3,b4a7b7,998d9c,7e7282,655b69,4d4451,362d3b,201925,000000</expressive>
<rainbow>ffffff,fffbfd,f7edff,ebddff,d2bcff,b79df7,9c82da,8167be,684fa3,503789,391d72,22005c,000000,ffffff,fffbfd,f7edff,e9def8,ccc3dc,b1a7c0,958da4,7a7389,625b71,4a4358,332d41,1e182b,000000,ffffff,fffbfa,ffecf0,ffd8e3,f0b7c7,d29dab,b68391,986976,7e525f,633b48,4a2531,31101c,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
<fruit_salad>ffffff,fcfcff,e8f2ff,cee5ff,97cbff,68b1f4,4a96d8,277bbb,00629f,004a7a,003355,001d35,000000,ffffff,fcfcff,e8f2ff,cee5ff,9dcbfb,82afdf,6795c2,4b7aa6,31628d,124a73,003355,001d35,000000,ffffff,fffbfd,f7edff,ebddff,d1bcfe,b5a1e1,9987c4,7e6da8,66558e,4d3d75,37265d,211047,000000,ffffff,fffbfd,f5eefd,e7e0ee,cbc3d2,afa8b6,948e9c,797480,615c69,494550,322f3a,1d1a24,000000,ffffff,fffbfd,f7edff,e9def8,ccc3dc,b1a7c0,958da4,7a7389,625b71,4a4358,332d41,1e182b,000000</fruit_salad>
</theme>
diff --git a/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java b/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java
index 30bd40b..8a37b16 100644
--- a/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java
+++ b/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java
@@ -30,14 +30,23 @@
import org.junit.runner.RunWith;
import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
-import java.security.ProviderException;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.EdECPublicKey;
import java.security.spec.ECGenParameterSpec;
+import java.security.spec.InvalidKeySpecException;
import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
+import java.util.Base64;
+
+import javax.crypto.KeyAgreement;
@RunWith(AndroidJUnit4.class)
public class Curve25519Test {
@@ -52,45 +61,77 @@
@Test
public void x25519KeyAgreementTest() throws NoSuchAlgorithmException, NoSuchProviderException,
- InvalidAlgorithmParameterException {
+ InvalidAlgorithmParameterException, InvalidKeySpecException, InvalidKeyException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
- final String alias = "x25519-alias";
- deleteEntry(alias);
+ // Aliases for both keys.
+ final String firstKeyAlias = "x25519-alias";
+ deleteEntry(firstKeyAlias);
+ final String secondKeyAlias = "x25519-alias-second";
+ deleteEntry(secondKeyAlias);
- KeyGenParameterSpec keySpec = new KeyGenParameterSpec.Builder(alias,
- KeyProperties.PURPOSE_AGREE_KEY)
+ // Generate first x25519 key pair.
+ KeyGenParameterSpec firstKeySpec = new KeyGenParameterSpec.Builder(firstKeyAlias,
+ KeyProperties.PURPOSE_AGREE_KEY)
.setAlgorithmParameterSpec(new ECGenParameterSpec("x25519")).build();
- kpg.initialize(keySpec);
+ kpg.initialize(firstKeySpec);
+ KeyPair firstKeyPair = kpg.generateKeyPair();
- //TODO(b/214203951): Remove this try/catch once Conscrypt class are available.
- try {
- kpg.generateKeyPair();
- fail("Should not be supported yet");
- } catch (ProviderException e) {
- assertThat(e.getMessage()).isEqualTo("Curve XDH not supported yet");
- }
+ // Generate second x25519 key pair.
+ KeyGenParameterSpec secondKeySpec = new KeyGenParameterSpec.Builder(secondKeyAlias,
+ KeyProperties.PURPOSE_AGREE_KEY)
+ .setAlgorithmParameterSpec(new ECGenParameterSpec("x25519")).build();
+ kpg.initialize(secondKeySpec);
+ KeyPair secondKeyPair = kpg.generateKeyPair();
+
+ // Attempt a key agreement with the private key from the first key pair and the public
+ // key from the second key pair.
+ KeyAgreement secondKa = KeyAgreement.getInstance("XDH");
+ secondKa.init(firstKeyPair.getPrivate());
+ secondKa.doPhase(secondKeyPair.getPublic(), true);
+ byte[] secondSecret = secondKa.generateSecret();
+
+ // Attempt a key agreement "the other way around": using the private key from the second
+ // key pair and the public key from the first key pair.
+ KeyAgreement firstKa = KeyAgreement.getInstance("XDH");
+ firstKa.init(secondKeyPair.getPrivate());
+ firstKa.doPhase(firstKeyPair.getPublic(), true);
+ byte[] firstSecret = firstKa.generateSecret();
+
+ // Both secrets being equal means the key agreement was successful.
+ assertThat(Arrays.compare(firstSecret, secondSecret)).isEqualTo(0);
}
@Test
public void ed25519KeyGenerationAndSigningTest()
throws NoSuchAlgorithmException, NoSuchProviderException,
- InvalidAlgorithmParameterException {
+ InvalidAlgorithmParameterException, InvalidKeyException, SignatureException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
final String alias = "ed25519-alias";
deleteEntry(alias);
KeyGenParameterSpec keySpec = new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
- .setAlgorithmParameterSpec(new ECGenParameterSpec("ed25519")).build();
+ .setAlgorithmParameterSpec(new ECGenParameterSpec("ed25519"))
+ .setDigests(KeyProperties.DIGEST_NONE).build();
kpg.initialize(keySpec);
- //TODO(b/214203951): Remove this try/catch once Conscrypt class are available.
- try {
- kpg.generateKeyPair();
- fail("Should not be supported yet");
- } catch (ProviderException e) {
- assertThat(e.getMessage()).isEqualTo("Curve 1.3.101.112 not supported yet");
- }
+ KeyPair kp = kpg.generateKeyPair();
+ assertThat(kp.getPublic()).isInstanceOf(EdECPublicKey.class);
+
+ byte[] data = "helloxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes();
+ Signature signer = Signature.getInstance("Ed25519");
+ signer.initSign(kp.getPrivate());
+ signer.update(data);
+ byte[] sigBytes = signer.sign();
+ assertThat(sigBytes.length).isEqualTo(64);
+ EdECPublicKey publicKey = (EdECPublicKey) kp.getPublic();
+ android.util.Log.i("Curve25519Test", "Manually validate: Payload "
+ + Base64.getEncoder().encodeToString(data) + " encoded key: "
+ + Base64.getEncoder().encodeToString(kp.getPublic().getEncoded())
+ + " signature: " + Base64.getEncoder().encodeToString(sigBytes));
+
+ //TODO: Verify signature over the data when Conscrypt supports validating Ed25519
+ // signatures.
}
@Test
@@ -150,4 +191,4 @@
assertThat(e.getMessage()).contains("cannot be initialized using NamedParameterSpec");
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
index fee9001..ab7a15d 100644
--- a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
@@ -33,6 +33,7 @@
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.android.server.job.nano.JobPackageHistoryProto.START_PERIODIC_JOB;
+import static com.android.server.job.nano.JobPackageHistoryProto.STOP_JOB;
import static com.android.server.job.nano.JobPackageHistoryProto.STOP_PERIODIC_JOB;
import static org.junit.Assert.assertFalse;
@@ -83,6 +84,7 @@
import com.android.compatibility.common.util.ProtoUtils;
import com.android.compatibility.common.util.mainline.MainlineModule;
import com.android.compatibility.common.util.mainline.ModuleDetector;
+import com.android.modules.utils.build.SdkLevel;
import com.android.server.job.nano.JobPackageHistoryProto;
import com.android.server.job.nano.JobSchedulerServiceDumpProto;
import com.android.server.job.nano.JobSchedulerServiceDumpProto.RegisteredJob;
@@ -315,7 +317,12 @@
// We can't simply require startTime <= endTime because the time being reported isn't
// accurate, and sometimes the end time may come before the start time by around 100 ms.
eventually(() -> {
- long stopTime = getLastJobTime(STOP_PERIODIC_JOB);
+ long stopTime;
+ if (SdkLevel.isAtLeastT()) {
+ stopTime = getLastJobTime(STOP_PERIODIC_JOB);
+ } else {
+ stopTime = getLastJobTime(STOP_JOB);
+ }
assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob);
}, EXPECTED_TIMEOUT_MILLIS);
}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index c68b9dd..162f66a 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -6419,11 +6419,11 @@
<!-- @SystemApi Must be required by a safety source to send an update using the
{@link android.safetycenter.SafetyCenterManager}.
- <p>Protection level: signature|privileged
+ <p>Protection level: internal|privileged
@hide
-->
<permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="internal|privileged" />
<!-- @SystemApi Allows an application to launch device manager setup screens.
<p>Not for use by third-party applications.
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index c197d47..bc3947f 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -96,7 +96,6 @@
const val DENY_RADIO_BUTTON = "com.android.permissioncontroller:id/deny_radio_button"
const val NOTIF_TEXT = "permgrouprequest_notifications"
- const val NOTIF_CONTINUE_TEXT = "permgrouprequestcontinue_notifications"
const val ALLOW_BUTTON_TEXT = "grant_dialog_button_allow"
const val ALLOW_FOREGROUND_BUTTON_TEXT = "grant_dialog_button_allow_foreground"
const val ALLOW_FOREGROUND_PREFERENCE_TEXT = "permission_access_only_foreground"
@@ -353,9 +352,7 @@
}
if (waitFindObjectOrNull(By.text(getPermissionControllerString(
- NOTIF_CONTINUE_TEXT, APP_PACKAGE_NAME)), 1000) != null ||
- waitFindObjectOrNull(By.text(getPermissionControllerString(
- NOTIF_TEXT, APP_PACKAGE_NAME)), 1000) != null) {
+ NOTIF_TEXT, APP_PACKAGE_NAME)), 1000) != null) {
if (isAutomotive) {
click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
} else {
@@ -598,7 +595,7 @@
button.click()
}
- val shouldShowStorageWarning = !isTv && !isWatch &&
+ val shouldShowStorageWarning = !isWatch &&
SdkLevel.isAtLeastT() && targetSdk <= Build.VERSION_CODES.S_V2 &&
permission in MEDIA_PERMISSIONS
if (shouldShowStorageWarning) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index b29e99f..eeb3a71 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -55,7 +55,6 @@
const val ACTIVITY_LABEL = "CreateNotif"
const val SECOND_ACTIVITY_LABEL = "EmptyActivity"
const val ALLOW = "to send you"
-const val CONTINUE_ALLOW = "to continue sending you"
const val INTENT_ACTION = "usepermission.createchannels.MAIN"
const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
const val NOTIFICATION_PERMISSION_ENABLED = "notification_permission_enabled"
@@ -124,18 +123,8 @@
}
@Test
- fun reviewRequiredClearedForTAppsOnLaunch() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
- setReviewRequired()
- assertNotificationReviewRequiredState(shouldBeSet = true)
- launchApp()
- assertNotificationReviewRequiredState(shouldBeSet = false)
- }
-
- @Test
fun notificationPromptShowsForLegacyAppAfterCreatingNotificationChannels() {
installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
- setReviewRequired()
launchApp()
clickPermissionRequestAllowButton()
}
@@ -143,21 +132,12 @@
@Test
fun notificationPromptShowsForLegacyAppWithNotificationChannelsOnStart() {
installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
- setReviewRequired()
// create channels, then leave the app
launchApp()
killTestApp()
launchApp()
- waitFindObject(By.textContains(CONTINUE_ALLOW))
- clickPermissionRequestAllowButton()
- }
-
- @Test
- fun nonReviewRequiredLegacyAppsDontShowContinuePrompt() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
- setReviewRequired(false)
- launchApp()
waitFindObject(By.textContains(ALLOW))
+ clickPermissionRequestAllowButton()
}
@Test
@@ -254,49 +234,11 @@
}
@Test
- fun reviewRequiredNotClearedOnNonLauncherIntentCategoryLaunches() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
- setReviewRequired()
- launchApp(launcherCategory = false)
- assertNotificationReviewRequiredState(true)
- }
-
- @Test
- fun reviewRequiredNotClearedOnNonMainIntentActionLaunches() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
- setReviewRequired()
- launchApp(mainIntent = false)
- assertNotificationReviewRequiredState(true)
- }
-
- @Test
- fun reviewRequiredClearedIfActivityOptionSet() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
- setReviewRequired()
- launchApp(isEligibleForPromptOption = true)
- assertNotificationReviewRequiredState(false)
- }
-
- @Test
- fun notificationGrantedAndReviewRequiredClearedOnLegacyGrant() {
+ fun notificationGrantedOnLegacyGrant() {
installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
- setReviewRequired()
launchApp()
clickPermissionRequestAllowButton()
assertAppPermissionGrantedState(POST_NOTIFICATIONS, granted = true)
- assertNotificationReviewRequiredState(shouldBeSet = false)
- }
-
- @Test
- fun notificationReviewRequiredClearedOnLegacyDeny() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
- setReviewRequired()
- launchApp()
- clickPermissionRequestDenyButton()
- waitForIdle()
- SystemUtil.eventually {
- assertNotificationReviewRequiredState(shouldBeSet = false)
- }
}
@Test
@@ -367,23 +309,6 @@
}
@Test
- fun reviewRequiredTAppsShowContinueMessage() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
- setReviewRequired(true)
- assertNotificationReviewRequiredState(true)
- launchApp(requestPermissions = true)
- waitFindObject(By.textContains(CONTINUE_ALLOW))
- }
-
- @Test
- fun nonReviewRequiredTAppsShowAllowMessage() {
- installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
- assertNotificationReviewRequiredState(false)
- launchApp(requestPermissions = true)
- waitFindObject(By.textContains(ALLOW))
- }
-
- @Test
fun legacyAppCannotExplicitlyRequestNotifications() {
installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
launchApp(createChannels = false, requestNotificationPermission = true)
@@ -404,27 +329,6 @@
}
}
- private fun assertNotificationReviewRequiredState(shouldBeSet: Boolean) {
- val flagSet = callWithShellPermissionIdentity {
- (context.packageManager.getPermissionFlags(POST_NOTIFICATIONS,
- APP_PACKAGE_NAME, Process.myUserHandle()) and FLAG_PERMISSION_REVIEW_REQUIRED) != 0
- }
- Assert.assertEquals("Unexpected REVIEW_REQUIRED state for POST_NOTIFICATIONS: ",
- shouldBeSet, flagSet)
- }
-
- private fun setReviewRequired(set: Boolean = true) {
- val flag = if (set) {
- FLAG_PERMISSION_REVIEW_REQUIRED
- } else {
- 0
- }
- runWithShellPermissionIdentity {
- context.packageManager.updatePermissionFlags(POST_NOTIFICATIONS, APP_PACKAGE_NAME,
- FLAG_PERMISSION_REVIEW_REQUIRED, flag, Process.myUserHandle())
- }
- }
-
private fun launchApp(
createChannels: Boolean = true,
createChannelsDelayed: Boolean = false,
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
index 5a1b7a0..b88fcf5 100644
--- a/tests/tests/provider/Android.bp
+++ b/tests/tests/provider/Android.bp
@@ -47,8 +47,7 @@
// uncomment when b/140885436 is fixed
// sdk_version: "test_current",
min_sdk_version: "21",
- //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
- target_sdk_version: "10000",
+ target_sdk_version: "33",
platform_apis: true,
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java b/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
index 8c62f21..c2a2795 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
@@ -30,6 +30,7 @@
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.provider.CallLog;
+import android.provider.CallLog.Calls;
import android.provider.cts.R;
import android.test.InstrumentationTestCase;
import android.util.Pair;
@@ -43,20 +44,172 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CallLogTest extends InstrumentationTestCase {
-
+ // Test Call Log Entry
private static final String TEST_NUMBER = "5625698388";
+ private static final int TEST_DATE = 1000;
+ private static final int TEST_DURATION = 30;
+ // Test Voicemail Log Entry
+ private static final String TEST_VOICEMAIL_NUMBER = "1119871234";
+ private static final int TEST_VOCIEMAIL_DATE = 1;
+ private static final int TEST_VOICEMAIL_DURATION = 5;
+ // Timeout
private static final long CONTENT_RESOLVER_TIMEOUT_MS = 5000;
+ // SQL Selection Column Names
+ private static final String SELECTION_TYPE = "type";
+ private static final String SELECTION_NUMBER = "number";
+ private static final String SELECTION_DATE = "date";
+ private static final String SELECTION_DURATION = "duration";
+ private static final String SELECTION_NEW = "new";
+ // SQL Selection as array
+ private static final String[] SELECTION =
+ new String[]{SELECTION_TYPE, SELECTION_NUMBER, SELECTION_DATE,
+ SELECTION_DURATION, SELECTION_NEW};
+ // Test filter URI that throws Security Exception
+ private static final Uri INVALID_FILTER_URI = Uri.parse(
+ "content://call_log/calls/filter/test\uD83D')) union select type,name,"
+ + "tbl_name,rootpage,sql FROM SQLITE_MASTER; --");
+ // Test call composer URI that throws Security Exception
private static final Uri INVALID_CALL_LOG_URI = Uri.parse(
"content://call_log/call_composer/%2fdata%2fdata%2fcom.android.providers"
+ ".contacts%2fshared_prefs%2fContactsUpgradeReceiver.xml");
-
+ // Test Failure Error
private static final String TEST_FAIL_DID_NOT_TRHOW_SE =
"fail test because Security Exception was not throw";
+ // Instance vars
+ private ContentResolver mContentResolver;
+
+ // Class to objectify the call log data (returned from a Cursor object)
+ public class LogEntry {
+ // properties
+ public Integer type;
+ public String number;
+ public Integer date;
+ public Integer duration;
+ public Integer newCount;
+ public String extras;
+
+ // setter
+ public void setValue(String selectionColumn, String value) {
+ if (value == null) {
+ // Integer.valueOf(value) throws NumberFormatException if string is null.
+ // so return early if value is null.
+ return;
+ }
+ try {
+ switch (selectionColumn) {
+ case SELECTION_TYPE:
+ type = Integer.valueOf(value);
+ break;
+ case SELECTION_NUMBER:
+ number = value;
+ break;
+ case SELECTION_DATE:
+ date = Integer.valueOf(value);
+ break;
+ case SELECTION_DURATION:
+ duration = Integer.valueOf(value);
+ break;
+ case SELECTION_NEW:
+ newCount = Integer.valueOf(value);
+ break;
+ default:
+ extras = value;
+ }
+ } catch (NumberFormatException e) {
+ // pass through
+ }
+ }
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ // Sets up this package as default dialer in super.
+ super.setUp();
+ mContentResolver = getInstrumentation().getContext().getContentResolver();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Ensure that the existing query functionality still works. To verify the functionality,
+ * this test adds a single call and voicemail entry to the logs, queries the logs,
+ * and asserts the entries are returned.
+ */
+ public void testPopulateAndQueryCallAndVoicemailLogs() {
+ try {
+ // needed in order to populate call log database
+ ShellUtils.runShellCommand("telecom set-default-dialer %s",
+ getInstrumentation().getContext().getPackageName());
+
+ populateLogsWithDefaults();
+
+ // query and get cursor
+ Cursor cursor = mContentResolver
+ .query(Calls.CONTENT_URI_WITH_VOICEMAIL, SELECTION, null, null);
+
+ // extract the data from the cursor and put the objects in a map
+ Map<String, LogEntry> entries = collectCursorEntries(cursor);
+
+ // cleanup
+ cursor.close();
+
+ // call entry
+ assertEquals(TEST_NUMBER, entries.get(TEST_NUMBER).number);
+ // voicemail entry
+ assertEquals(TEST_VOICEMAIL_NUMBER, entries.get(TEST_VOICEMAIL_NUMBER).number);
+ } finally {
+ //cleanup
+ deletePopulatedLogs();
+ ShellUtils.runShellCommand("telecom set-default-dialer default");
+ }
+ }
+
+ /**
+ * Test scenario where an app calls {@link ContentResolver#query} with an invalid URI.
+ *
+ * The URI is invalid because it attempts to bypass voicemail permissions and grab the voicemail
+ * log data without the proper voicemail permissions.
+ *
+ * Therefore, a Security Exception is thrown.
+ */
+ public void testInvalidQueryToCallLog() {
+ try {
+ // needed in order to populate call log database
+ ShellUtils.runShellCommand("telecom set-default-dialer %s",
+ getInstrumentation().getContext().getPackageName());
+
+ populateLogsWithDefaults();
+
+ // drop voicemail permissions
+ ShellUtils.runShellCommand("telecom set-default-dialer default");
+
+ // query and get cursor (expecting to hit Security Exception with call)
+ Cursor cursor = mContentResolver
+ .query(INVALID_FILTER_URI, SELECTION, null, null);
+
+ // the previous line should throw an exception
+ fail(TEST_FAIL_DID_NOT_TRHOW_SE);
+ } catch (SecurityException e) {
+ // success...
+ assertNotNull(e.toString());
+ } finally {
+ //cleanup
+ ShellUtils.runShellCommand("telecom set-default-dialer %s",
+ getInstrumentation().getContext().getPackageName());
+ deletePopulatedLogs();
+ ShellUtils.runShellCommand("telecom set-default-dialer default");
+ }
+ }
/**
* Tests scenario where an app gives {@link ContentResolver} a file to open that is not in the
@@ -297,4 +450,66 @@
} catch (InterruptedException e) {
}
}
+
+ private ContentValues getDefaultValues(int type, String number, int date, int duration) {
+ ContentValues values = new ContentValues();
+ values.put(Calls.TYPE, type);
+ values.put(Calls.NUMBER, number);
+ values.put(Calls.NUMBER_PRESENTATION, Calls.PRESENTATION_ALLOWED);
+ values.put(Calls.DATE, date);
+ values.put(Calls.DURATION, duration);
+ values.put(Calls.NEW, 1);
+ return values;
+ }
+
+ private ContentValues getDefaultCallValues() {
+ return getDefaultValues(Calls.INCOMING_TYPE, TEST_NUMBER, TEST_DATE, TEST_DURATION);
+ }
+
+ private ContentValues getDefaultVoicemailValues() {
+ return getDefaultValues(Calls.VOICEMAIL_TYPE, TEST_VOICEMAIL_NUMBER, TEST_VOCIEMAIL_DATE,
+ TEST_VOICEMAIL_DURATION);
+ }
+
+ private void deletePopulatedLogs() {
+ // delete TEST_NUMBER in the call logs
+ mContentResolver.delete(CallLog.Calls.CONTENT_URI,
+ Calls.NUMBER + "=" + TEST_NUMBER, null);
+ // delete TEST_VOICEMAIL_NUMBER in the voicemail logs
+ mContentResolver.delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
+ Calls.NUMBER + "=" + TEST_VOICEMAIL_NUMBER, null);
+ // cleanup extra entry created in this test that does not have a Calls.NUMBER
+ mContentResolver.delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
+ Calls.DATE + "=" + "0", null);
+ }
+
+ private void populateLogsWithDefaults() {
+ // add call log entry
+ mContentResolver.insert(Calls.CONTENT_URI, getDefaultCallValues());
+ // add voicemail entry
+ mContentResolver.insert(Calls.CONTENT_URI_WITH_VOICEMAIL, getDefaultVoicemailValues());
+ }
+
+ /**
+ * Helper method for a test that wants to objectify the cursor data into LogEntry objects.
+ * NOTE: The key for the map is the phone number, so you can only store one object per number.
+ *
+ * @return all the data in the cursor in a LogEntry map
+ */
+ public Map<String, LogEntry> collectCursorEntries(Cursor cursor) {
+ Map<String, LogEntry> entries = new HashMap<>();
+ // iterate through every row in the cursor
+ while (cursor.moveToNext()) {
+ LogEntry e = new LogEntry();
+ // iterate through each column (should be the SELECTION given to query)
+ for (int i = 0; i < cursor.getColumnCount(); i++) {
+ e.setValue(cursor.getColumnName(i), cursor.getString(i));
+ }
+ // don't add if bad number (should never happen)
+ if (e.number != null || !e.number.isEmpty()) {
+ entries.put(e.number, e);
+ }
+ }
+ return entries;
+ }
}
diff --git a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
index ac1e9df..52feb93 100644
--- a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
+++ b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
@@ -230,7 +230,9 @@
val latchEnabled = CountDownLatch(1)
val listenerSensorEnabled = object : OnSensorPrivacyChangedListener {
override fun onSensorPrivacyChanged(params: SensorPrivacyChangedParams) {
- if (params.isEnabled && params.sensor == sensor) {
+ if (params.isEnabled &&
+ params.sensor == sensor &&
+ params.toggleType == TOGGLE_TYPE_SOFTWARE) {
latchEnabled.countDown()
}
}
@@ -250,7 +252,9 @@
val latchDisabled = CountDownLatch(1)
val listenerSensorDisabled = object : OnSensorPrivacyChangedListener {
override fun onSensorPrivacyChanged(params: SensorPrivacyChangedParams) {
- if (!params.isEnabled && params.sensor == sensor) {
+ if (!params.isEnabled &&
+ params.sensor == sensor &&
+ params.toggleType == TOGGLE_TYPE_SOFTWARE) {
latchDisabled.countDown()
}
}
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 0b05c5f..d37a28c 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -146,7 +146,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
-import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -316,32 +315,26 @@
TelephonyManager.NETWORK_TYPE_GPRS,
TelephonyManager.NETWORK_TYPE_EDGE}));
sNetworkTypes.put(CellIdentityWcdma.class,
- Arrays.asList(new Integer[]{
- TelephonyManager.NETWORK_TYPE_UMTS,
- TelephonyManager.NETWORK_TYPE_HSDPA,
- TelephonyManager.NETWORK_TYPE_HSUPA,
- TelephonyManager.NETWORK_TYPE_HSPA,
- TelephonyManager.NETWORK_TYPE_HSPAP}));
+ Arrays.asList(TelephonyManager.NETWORK_TYPE_UMTS,
+ TelephonyManager.NETWORK_TYPE_HSDPA,
+ TelephonyManager.NETWORK_TYPE_HSUPA,
+ TelephonyManager.NETWORK_TYPE_HSPA,
+ TelephonyManager.NETWORK_TYPE_HSPAP));
sNetworkTypes.put(CellIdentityCdma.class,
- Arrays.asList(new Integer[]{
- TelephonyManager.NETWORK_TYPE_CDMA,
- TelephonyManager.NETWORK_TYPE_1xRTT,
- TelephonyManager.NETWORK_TYPE_EVDO_0,
- TelephonyManager.NETWORK_TYPE_EVDO_A,
- TelephonyManager.NETWORK_TYPE_EVDO_B,
- TelephonyManager.NETWORK_TYPE_EHRPD}));
+ Arrays.asList(TelephonyManager.NETWORK_TYPE_CDMA,
+ TelephonyManager.NETWORK_TYPE_1xRTT,
+ TelephonyManager.NETWORK_TYPE_EVDO_0,
+ TelephonyManager.NETWORK_TYPE_EVDO_A,
+ TelephonyManager.NETWORK_TYPE_EVDO_B,
+ TelephonyManager.NETWORK_TYPE_EHRPD));
sNetworkTypes.put(CellIdentityLte.class,
- Arrays.asList(new Integer[]{
- TelephonyManager.NETWORK_TYPE_LTE}));
+ Arrays.asList(TelephonyManager.NETWORK_TYPE_LTE));
sNetworkTypes.put(CellIdentityNr.class,
- Arrays.asList(new Integer[]{
- TelephonyManager.NETWORK_TYPE_NR}));
+ Arrays.asList(TelephonyManager.NETWORK_TYPE_NR));
sNetworkTypes.put(CellIdentityTdscdma.class,
- Arrays.asList(new Integer[]{
- TelephonyManager.NETWORK_TYPE_TD_SCDMA}));
+ Arrays.asList(TelephonyManager.NETWORK_TYPE_TD_SCDMA));
}
-
private int mTestSub;
private TelephonyManagerTest.CarrierConfigReceiver mReceiver;
private int mRadioVersion;
@@ -427,28 +420,20 @@
mAllowedNetworkTypesList = new HashMap<>();
}
long allowedNetworkTypesUser = ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, (tm) -> {
- return tm.getAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
- }
+ mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)
);
long allowedNetworkTypesPower = ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, (tm) -> {
- return tm.getAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER);
- }
+ mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER)
);
long allowedNetworkTypesCarrier = ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, (tm) -> {
- return tm.getAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER);
- }
+ mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER)
);
long allowedNetworkTypesEnable2g = ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, (tm) -> {
- return tm.getAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
- }
+ mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G)
);
mAllowedNetworkTypesList.put(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
allowedNetworkTypesUser);
@@ -598,27 +583,25 @@
grantLocationPermissions();
- TestThread t = new TestThread(new Runnable() {
- public void run() {
- Looper.prepare();
- mListener = new PhoneStateListener() {
- @Override
- public void onCellLocationChanged(CellLocation location) {
- if(!mOnCellLocationChangedCalled) {
- synchronized (mLock) {
- mOnCellLocationChangedCalled = true;
- mLock.notify();
- }
+ TestThread t = new TestThread(() -> {
+ Looper.prepare();
+ mListener = new PhoneStateListener() {
+ @Override
+ public void onCellLocationChanged(CellLocation location) {
+ if (!mOnCellLocationChangedCalled) {
+ synchronized (mLock) {
+ mOnCellLocationChangedCalled = true;
+ mLock.notify();
}
}
- };
-
- synchronized (mLock) {
- mLock.notify(); // mListener is ready
}
+ };
- Looper.loop();
+ synchronized (mLock) {
+ mLock.notify(); // mListener is ready
}
+
+ Looper.loop();
});
synchronized (mLock) {
@@ -1438,22 +1421,20 @@
return;
}
- TestThread t = new TestThread(new Runnable() {
- public void run() {
- Looper.prepare();
+ TestThread t = new TestThread(() -> {
+ Looper.prepare();
- mListener = new PhoneStateListener() {
- @Override
- public void onServiceStateChanged(ServiceState serviceState) {
- synchronized (mLock) {
- mServiceState = serviceState;
- mLock.notify();
- }
+ mListener = new PhoneStateListener() {
+ @Override
+ public void onServiceStateChanged(ServiceState serviceState) {
+ synchronized (mLock) {
+ mServiceState = serviceState;
+ mLock.notify();
}
- };
- mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE);
- Looper.loop();
- }
+ }
+ };
+ mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE);
+ Looper.loop();
});
synchronized (mLock) {
@@ -3357,8 +3338,7 @@
// test without permission: verify SecurityException
long allowedNetworkTypes1 = TelephonyManager.NETWORK_TYPE_BITMASK_NR
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
- long allowedNetworkTypes2 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
- | TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
+ long allowedNetworkTypes2 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
long allowedNetworkTypes3 = TelephonyManager.NETWORK_TYPE_BITMASK_NR
| TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
@@ -3699,7 +3679,7 @@
// NPMS will set policy data to true after tests set it to false,
// so retry disabling policy data to prevent flaky test failures.
// TODO: Set empty policies once we can suppress default policies.
- while ((isDataEnabledForReason || isDataConnectionAvailable) && retry < 10) {
+ while ((isDataEnabledForReason || isDataConnectionAvailable) && retry < 30) {
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
mTelephonyManager,
(tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_POLICY,
@@ -4764,12 +4744,7 @@
return major * 100 + minor;
}
- private Executor mSimpleExecutor = new Executor() {
- @Override
- public void execute(Runnable r) {
- r.run();
- }
- };
+ private Executor mSimpleExecutor = Runnable::run;
private static MockSignalStrengthsTelephonyCallback mMockSignalStrengthsTelephonyCallback;
@@ -4834,16 +4809,14 @@
}
grantLocationPermissions();
- TestThread t = new TestThread(new Runnable() {
- public void run() {
- Looper.prepare();
- mMockCellInfoListener = new MockCellInfoListener();
- synchronized (mLock) {
- mLock.notify(); // listener is ready
- }
-
- Looper.loop();
+ TestThread t = new TestThread(() -> {
+ Looper.prepare();
+ mMockCellInfoListener = new MockCellInfoListener();
+ synchronized (mLock) {
+ mLock.notify(); // listener is ready
}
+
+ Looper.loop();
});
synchronized (mLock) {
@@ -5165,6 +5138,37 @@
// expected
}
}
+
+ @Test
+ public void testIgnoreInvalidNetworkType() {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+
+ // NETWORK_TYPE_BITMASK_LTE_CA is invalid, should be converted into NETWORK_TYPE_BITMASK_LTE
+ long invalidAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_NR
+ | TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
+ long expectedAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_NR
+ | TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+ try {
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+ mTelephonyManager,
+ (tm) -> tm.setAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER,
+ invalidAllowedNetworkTypes));
+
+ long deviceAllowedNetworkTypes = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelephonyManager, (tm) -> {
+ return tm.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER);
+ }
+ );
+ assertEquals(expectedAllowedNetworkTypes, deviceAllowedNetworkTypes);
+ } catch (SecurityException se) {
+ fail("testIgnoreInvalidNetworkType: SecurityException not expected");
+ }
+ }
+
@Test
public void getSimSlotMappingTest() {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
@@ -5196,103 +5200,54 @@
return true;
}
- private static class ServiceStateListener extends TelephonyCallback
- implements TelephonyCallback.ServiceStateListener {
- CountDownLatch mLatch;
- Predicate<ServiceState> mStateToWaitFor;
+ private static class ServiceStateRadioStateListener extends TelephonyCallback
+ implements TelephonyCallback.ServiceStateListener,
+ TelephonyCallback.RadioPowerStateListener {
+ ServiceState mServiceState;
+ int mRadioPowerState;
- ServiceStateListener(Predicate<ServiceState> stateToWaitFor) {
- mLatch = new CountDownLatch(1);
- mStateToWaitFor = stateToWaitFor;
+ ServiceStateRadioStateListener(ServiceState serviceState, int radioPowerState) {
+ mServiceState = serviceState;
+ mRadioPowerState = radioPowerState;
}
@Override
public void onServiceStateChanged(ServiceState ss) {
- if (mStateToWaitFor.test(ss)) {
- mLatch.countDown();
- }
- }
-
- public void waitForServiceStateChange(long timeout, TimeUnit unit) throws Exception {
- if (!mLatch.await(timeout, unit)) {
- throw new IllegalStateException("ServiceState did not change to satisfy condition");
- }
- }
- }
-
- private void waitForServiceState(Predicate<ServiceState> condition, long timeout, TimeUnit unit)
- throws Exception {
- ServiceStateListener callback = new ServiceStateListener(condition);
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
- tm -> tm.registerTelephonyCallback(Runnable::run, callback));
- try {
- callback.waitForServiceStateChange(timeout, unit);
- } finally {
- mTelephonyManager.unregisterTelephonyCallback(callback);
- }
- }
-
- private static class RadioPowerStateListener extends TelephonyCallback
- implements TelephonyCallback.RadioPowerStateListener {
- CountDownLatch mLatch;
- @RadioPowerState int mStateToWaitFor;
-
- RadioPowerStateListener(@RadioPowerState int stateToWaitFor) {
- mLatch = new CountDownLatch(1);
- mStateToWaitFor = stateToWaitFor;
+ mServiceState = ss;
}
@Override
- public void onRadioPowerStateChanged(@RadioPowerState int state) {
- if (state == mStateToWaitFor) {
- mLatch.countDown();
- }
- }
-
- public void waitForRadioPowerStateChange() throws Exception {
- if (!mLatch.await(10, TimeUnit.SECONDS)) {
- throw new IllegalStateException(
- "Radio power state did not change to " + mStateToWaitFor);
- }
- }
- }
-
- private void setRadioPower(boolean powerOn) throws Exception {
- RadioPowerStateListener callback =
- new RadioPowerStateListener(
- powerOn
- ? TelephonyManager.RADIO_POWER_ON
- : TelephonyManager.RADIO_POWER_OFF);
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
- tm -> tm.registerTelephonyCallback(Runnable::run, callback),
- permission.READ_PRIVILEGED_PHONE_STATE);
- try {
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
- tm -> tm.setRadioPower(powerOn),
- permission.MODIFY_PHONE_STATE);
- callback.waitForRadioPowerStateChange();
- } finally {
- mTelephonyManager.unregisterTelephonyCallback(callback);
+ public void onRadioPowerStateChanged(int radioState) {
+ mRadioPowerState = radioState;
}
}
@Test
- public void testSetVoiceServiceStateOverride() throws Exception {
+ public void testSetVoiceServiceStateOverride() {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));
+ ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener(
+ mTelephonyManager.getServiceState(), mTelephonyManager.getRadioPowerState());
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+ tm -> tm.registerTelephonyCallback(Runnable::run, callback));
boolean turnedRadioOff = false;
boolean setServiceStateOverride = false;
try {
if (mTelephonyManager.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
Log.i(TAG, "testSetVoiceServiceStateOverride: turning radio off to force OOS");
- setRadioPower(false);
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+ tm -> tm.setRadioPower(false), permission.MODIFY_PHONE_STATE);
turnedRadioOff = true;
// Wait until ServiceState reflects the power change
- waitForServiceState(
- ss -> ss.getState() != ServiceState.STATE_IN_SERVICE, 10, TimeUnit.SECONDS);
+ int retry = 0;
+ while ((callback.mRadioPowerState != TelephonyManager.RADIO_POWER_OFF
+ || callback.mServiceState.getState() == ServiceState.STATE_IN_SERVICE)
+ && retry < 10) {
+ retry++;
+ waitForMs(1000);
+ }
+ assertEquals(TelephonyManager.RADIO_POWER_OFF, callback.mRadioPowerState);
+ assertNotEquals(ServiceState.STATE_IN_SERVICE, callback.mServiceState.getState());
}
// This could be OUT_OF_SERVICE or POWER_OFF, it doesn't really matter for this test as
// long as it's not IN_SERVICE
@@ -5300,35 +5255,42 @@
Log.i(TAG, "testSetVoiceServiceStateOverride: originalSS = " + originalServiceState);
assertNotEquals(ServiceState.STATE_IN_SERVICE, originalServiceState);
- // Wait for device to finish processing RADIO_POWER_OFF.
- // Otherwise, Telecom will clear the voice state override before SST processes it.
- waitForMs(10000);
+ // Telecom will sometimes remove the override after radio reboots.
+ // Retry setting the override to prevent flaky test failures.
+ int listenerState = callback.mServiceState.getState();
+ int telephonyManagerState = originalServiceState;
+ int retry = 0;
+ while ((listenerState != ServiceState.STATE_IN_SERVICE
+ || telephonyManagerState != ServiceState.STATE_IN_SERVICE) && retry < 3) {
+ // We should see the override in both ServiceStateListener and getServiceState
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+ tm -> tm.setVoiceServiceStateOverride(true),
+ permission.BIND_TELECOM_CONNECTION_SERVICE);
+ setServiceStateOverride = true;
- // We should see the override reflected by both ServiceStateListener and getServiceState
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
- tm -> tm.setVoiceServiceStateOverride(true),
- permission.BIND_TELECOM_CONNECTION_SERVICE);
- setServiceStateOverride = true;
- waitForServiceState(
- ss -> ss.getState() == ServiceState.STATE_IN_SERVICE, 5, TimeUnit.SECONDS);
- assertEquals(
- ServiceState.STATE_IN_SERVICE, mTelephonyManager.getServiceState().getState());
+ ServiceState serviceState = mTelephonyManager.getServiceState();
+ if (serviceState != null) {
+ telephonyManagerState = serviceState.getState();
+ }
+ listenerState = callback.mServiceState.getState();
+ retry++;
+ waitForMs(5000);
+ }
+ assertEquals(ServiceState.STATE_IN_SERVICE, listenerState);
+ assertEquals(ServiceState.STATE_IN_SERVICE, telephonyManagerState);
// When we take away the override, things flip back to the original state since there
// were no other material changes made to the device that would impact ServiceState
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
tm -> tm.setVoiceServiceStateOverride(false),
permission.BIND_TELECOM_CONNECTION_SERVICE);
- waitForServiceState(ss -> ss.getState() == originalServiceState, 5, TimeUnit.SECONDS);
+ assertEquals(originalServiceState, callback.mServiceState.getState());
assertEquals(originalServiceState, mTelephonyManager.getServiceState().getState());
} finally {
if (setServiceStateOverride) {
// No harm in calling this again if we already did, but call just in case we failed
// an assertion related to setOverride(true)
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
tm -> tm.setVoiceServiceStateOverride(false),
permission.BIND_TELECOM_CONNECTION_SERVICE);
}
@@ -5336,11 +5298,18 @@
// Turn the radio back on and wait for ServiceState to become stable again so we
// don't cause flakes in other tests
Log.i(TAG, "testSetVoiceServiceStateOverride: turning radio back on");
- setRadioPower(true);
- waitForServiceState(
- ss -> ss.getState() == ServiceState.STATE_IN_SERVICE, 30, TimeUnit.SECONDS);
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+ tm -> tm.setRadioPower(true), permission.MODIFY_PHONE_STATE);
+ int retry = 0;
+ while ((callback.mRadioPowerState != TelephonyManager.RADIO_POWER_ON
+ || callback.mServiceState.getState() != ServiceState.STATE_IN_SERVICE)
+ && retry < 10) {
+ retry++;
+ waitForMs(1000);
+ }
+ assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);
+ assertEquals(ServiceState.STATE_IN_SERVICE, callback.mServiceState.getState());
}
}
}
}
-
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
index 81850a8..7a76aca 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
@@ -179,6 +179,7 @@
// Remove the SIM
assertTrue(sMockModemManager.removeSimCard(slotId));
+ TimeUnit.SECONDS.sleep(2);
simCardState = sTelephonyManager.getSimCardState();
assertEquals(TelephonyManager.SIM_STATE_ABSENT, simCardState);
}
diff --git a/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java b/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
index 910050f..eed8158 100644
--- a/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
@@ -57,6 +57,10 @@
// Make sure we got the streaming services
List<FileServiceInfo> serviceInfos =
(List<FileServiceInfo>) mCallback.waitOnFileServicesUpdated().arg1;
+ if (!CtsDownloadService.FILE_SERVICE_INFO.equals(serviceInfos.get(0))) {
+ mDownloadSession.requestUpdateFileServices(testClasses);
+ serviceInfos = (List<FileServiceInfo>) mCallback.waitOnFileServicesUpdated().arg1;
+ }
assertEquals(CtsDownloadService.FILE_SERVICE_INFO, serviceInfos.get(0));
assertEquals(0, mCallback.getNumErrorCalls());
diff --git a/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java b/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
index 436f611..a6850b2 100644
--- a/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
@@ -24,12 +24,12 @@
import android.telephony.mbms.MbmsErrors;
import android.telephony.mbms.StreamingServiceInfo;
+import org.junit.Test;
+
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import org.junit.Test;
-
public class MbmsStreamingSessionTest extends MbmsStreamingTestBase {
@Test
public void testDuplicateSession() throws Exception {
@@ -50,6 +50,11 @@
// Make sure we got the streaming services
List<StreamingServiceInfo> serviceInfos =
(List<StreamingServiceInfo>) mCallback.waitOnStreamingServicesUpdated().arg1;
+ if (!CtsStreamingService.STREAMING_SERVICE_INFO.equals(serviceInfos.get(0))) {
+ mStreamingSession.requestUpdateStreamingServices(testClasses);
+ serviceInfos =
+ (List<StreamingServiceInfo>) mCallback.waitOnStreamingServicesUpdated().arg1;
+ }
assertEquals(CtsStreamingService.STREAMING_SERVICE_INFO, serviceInfos.get(0));
assertEquals(0, mCallback.getNumErrorCalls());
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 d83bdb2..3b004dd 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -5492,9 +5492,10 @@
network.setBssidAllowlist(Collections.emptyList());
mWifiManager.updateNetwork(network);
}
- // trigger a disconnect and wait for disconnect.
- mWifiManager.disconnect();
- waitForDisconnection();
+
+ // Disable and re-enable Wifi to avoid reconnect to the secondary candidate
+ setWifiEnabled(false);
+ setWifiEnabled(true);
// Now trigger scan and ensure that the device does not connect to any networks.
mWifiManager.startScan();