Snap for 8730993 from 9436194c79a6d9681d3109de641476c7a0f0d971 to mainline-tzdata3-release
Change-Id: I25c43a0fdcc0bcca9a78bc7edd9559a14ea02810
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
index b2035c8..f87c6b9 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb
index e108ba3..03cf8a0 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v1.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index 9211e61..c93ee73 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index a5d0827..d5922e1 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb
index 9f834b3..18e12ee 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index d684672..00f9f6c 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
deleted file mode 100644
index 918ce0c..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-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: "shim/prebuilts//arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- git_branch: "tm-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 275064d..861ffa3 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index 3b24219..79de375 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index 866da01..91f5ef2 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
index 2f99030..e8f2283 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_rebootless.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index abaf998..e56d855 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
index 5bf4e32..ec3b1d6 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index ff3a295..a8b55ab 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index af3c9b3..23567d8 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index 45e3352..84c7328 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index 078ac5a..ed4ca4b 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index 0798f5f..5fb0fb2 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 44a33be..38f20a0 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index 19099b5..ac823c9 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 6db5911..0281ed4 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb
index d0c5a40..50c821d 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v3.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
index 179ba8d..f900c46 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v3_rebootless.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index 15d980c..d908d0e 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index 01313db..cb1a634 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
index 1673a81..0d09fcb 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb
index 83580fe..742bca4 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v1.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index 5c23eea..783107c 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index 36df5ad..5ab45ea 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb
index c2d9242..aee50ef 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index 92dba07..9eb21ee 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
deleted file mode 100644
index a3228fb..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_upgrades_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-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: "shim/prebuilts//x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- git_branch: "tm-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 1534301..670489d 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index b8e1de5..c5d28ff 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index d9c58de..17ae6c5 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
index 0c4bbda..c817a79 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index 826a238..b121049 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
index 3199a49..39e49e1 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index eb0acfa..2056dc1 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index 19268fc..229b0f3 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index c86aef6..fc464db 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index 1f0f41d..cffcd60 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index def0f0d..c2168d8 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 2a1c96f..1f2469a 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index ad5a295..986a459 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 21c2689..d53ab6c 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb
index 84113df..ca8bade 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v3.apex"
}
@@ -8,7 +8,7 @@
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
index cc3a401..e2c369f 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index ab5a34e..ea06694 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index 6d51168..3d41a84 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8572644"
+ build_id: "7552332"
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/system/apex"
- git_branch: "tm-dev"
+ git_branch: "sc-dev"
transform: TRANSFORM_NONE
transform_options {
}
diff --git a/Android.bp b/Android.bp
index e17f64c..b198f25 100644
--- a/Android.bp
+++ b/Android.bp
@@ -28,6 +28,7 @@
],
}
+// TODO(b/178585590): delete this after testing linking strategy
soong_config_module_type {
name: "library_linking_strategy_apex_defaults",
module_type: "apex_defaults",
diff --git a/apexd/Android.bp b/apexd/Android.bp
index ce5d170..ba2de03 100644
--- a/apexd/Android.bp
+++ b/apexd/Android.bp
@@ -87,7 +87,6 @@
"libavb",
"libdm",
"libext2_uuid",
- "libsigningutils",
"libverity_tree",
"libvold_binder",
"libxml2",
@@ -149,11 +148,11 @@
"libapexd-deps",
],
srcs: [
- "apex_classpath.cpp",
"apex_database.cpp",
"apexd.cpp",
"apexd_lifecycle.cpp",
"apexd_loop.cpp",
+ "apexd_prepostinstall.cpp",
"apexd_private.cpp",
"apexd_session.cpp",
"apexd_verity.cpp",
@@ -213,9 +212,7 @@
static_libs: [
"lib_apex_session_state_proto",
"lib_apex_manifest_proto",
- "lib_microdroid_metadata_proto",
"libavb",
- "libverity_tree",
],
static: {
whole_static_libs: ["libc++fs"],
@@ -237,7 +234,6 @@
"apex_file_repository.cpp",
"apex_manifest.cpp",
"apex_shim.cpp",
- "apexd_verity.cpp",
],
host_supported: true,
target: {
@@ -251,7 +247,6 @@
export_header_lib_headers: [
"libutils_headers",
],
- export_include_dirs: ["."],
}
genrule {
@@ -341,17 +336,6 @@
}
genrule {
- // Extract the root digest with avbtool
- name: "apex.apexd_test_erofs_digest",
- out: ["apex.apexd_test_erofs_digest.txt"],
- srcs: [":apex.apexd_test_erofs"],
- tools: ["avbtool"],
- cmd: "unzip -q $(in) -d $(genDir) apex_payload.img && " +
- "$(location avbtool) print_partition_digests --image $(genDir)/apex_payload.img " +
- "| cut -c 3-| tee $(out)"
-}
-
-genrule {
// Generates an apex which has same module name as apex.apexd_test.apex, but
// is actually signed with a different key.
name: "gen_key_mismatch_apex",
@@ -430,18 +414,18 @@
],
data: [
":apex.apexd_test",
- ":apex.apexd_test_erofs",
":apex.apexd_test_f2fs",
":apex.apexd_test_digest",
- ":apex.apexd_test_erofs_digest",
":apex.apexd_test_f2fs_digest",
- ":apex.apexd_test_classpath",
":apex.apexd_test_different_app",
":apex.apexd_test_no_hashtree",
":apex.apexd_test_no_hashtree_2",
":apex.apexd_test_no_inst_key",
":apex.apexd_test_f2fs_no_inst_key",
":apex.apexd_test_nocode",
+ ":apex.apexd_test_postinstall",
+ ":apex.apexd_test_preinstall",
+ ":apex.apexd_test_prepostinstall.fail",
":apex.apexd_test_v2",
":apex.corrupted_b146895998",
":apex.banned_name",
@@ -470,7 +454,6 @@
":com.android.apex.compressed.v1_original",
":com.android.apex.compressed.v2",
":com.android.apex.compressed.v2_original",
- ":com.android.sepolicy",
":gen_manifest_mismatch_compressed_apex_v2",
"apexd_testdata/com.android.apex.test_package.avbpubkey",
"apexd_testdata/com.android.apex.compressed.avbpubkey",
@@ -491,7 +474,6 @@
":test.rebootless_apex_priv_app_in_apex",
],
srcs: [
- "apex_classpath_test.cpp",
"apex_database_test.cpp",
"apex_file_test.cpp",
"apex_file_repository_test.cpp",
@@ -546,12 +528,3 @@
api_dir: "apex-info-list-api",
gen_writer: true,
}
-
-xsd_config {
- name: "apex-info-list-tinyxml",
- srcs: ["ApexInfoList.xsd"],
- package_name: "com.android.apex",
- api_dir: "apex-info-list-api",
- gen_writer: true,
- tinyxml: true,
-}
diff --git a/apexd/AndroidTest.xml b/apexd/AndroidTest.xml
index bc2eae6..6f65f4e 100644
--- a/apexd/AndroidTest.xml
+++ b/apexd/AndroidTest.xml
@@ -33,6 +33,8 @@
<option name="remount-system" value="true" />
<option name="push" value="apex.apexd_test.apex->/system_ext/apex/apex.apexd_test.apex" />
<option name="push" value="apex.apexd_test_different_app.apex->/system_ext/apex/apex.apexd_test_different_app.apex" />
+ <option name="push" value="apex.apexd_test_postinstall.apex->/system_ext/apex/apex.apexd_test_postinstall.apex" />
+ <option name="push" value="apex.apexd_test_preinstall.apex->/system_ext/apex/apex.apexd_test_preinstall.apex" />
</target_preparer>
<!-- system_server might still hold a reference to apexservice. This means that apexd is still
diff --git a/apexd/ApexInfoList.xsd b/apexd/ApexInfoList.xsd
index a327fc6..440b975 100644
--- a/apexd/ApexInfoList.xsd
+++ b/apexd/ApexInfoList.xsd
@@ -33,7 +33,6 @@
<xs:attribute name="isFactory" type="xs:boolean" use="required"/>
<xs:attribute name="isActive" type="xs:boolean" use="required"/>
<xs:attribute name="lastUpdateMillis" type="xs:long"/>
- <xs:attribute name="provideSharedApexLibs" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
diff --git a/apexd/TEST_MAPPING b/apexd/TEST_MAPPING
index bcf6133..77ff9b8 100644
--- a/apexd/TEST_MAPPING
+++ b/apexd/TEST_MAPPING
@@ -2,9 +2,6 @@
"presubmit": [
{
"name": "ApexTestCases"
- },
- {
- "name": "MicrodroidHostTestCases"
}
],
"imports": [
diff --git a/apexd/aidl/android/apex/ApexInfo.aidl b/apexd/aidl/android/apex/ApexInfo.aidl
index fb590f2..9cc4d75 100644
--- a/apexd/aidl/android/apex/ApexInfo.aidl
+++ b/apexd/aidl/android/apex/ApexInfo.aidl
@@ -24,18 +24,4 @@
@utf8InCpp String versionName;
boolean isFactory;
boolean isActive;
-
- // Populated only for getStagedApex() API
- boolean hasClassPathJars;
-
- // Will be set to true if during this boot a different APEX package of the APEX was
- // activated, than in the previous boot.
- // This can happen in the following situations:
- // 1. It was part of the staged session that was applied during this boot.
- // 2. A compressed system APEX was decompressed during this boot.
- // 3. apexd failed to activate an APEX on /data/apex/active (that was successfully
- // activated during last boot) and needed to fallback to pre-installed counterpart.
- // Note: this field can only be set to true during boot, after boot is completed
- // (sys.boot_completed = 1) value of this field will always be false.
- boolean activeApexChanged;
}
diff --git a/apexd/aidl/android/apex/IApexService.aidl b/apexd/aidl/android/apex/IApexService.aidl
index d33970c..2d77a82 100644
--- a/apexd/aidl/android/apex/IApexService.aidl
+++ b/apexd/aidl/android/apex/IApexService.aidl
@@ -29,7 +29,6 @@
ApexSessionInfo[] getSessions();
ApexSessionInfo getStagedSessionInfo(int session_id);
- ApexInfo[] getStagedApexInfos(in ApexSessionParams params);
ApexInfo[] getActivePackages();
ApexInfo[] getAllPackages();
@@ -76,6 +75,26 @@
* Not meant for use outside of testing. The call will not be
* functional on user builds.
*/
+ void activatePackage(in @utf8InCpp String package_path);
+ /**
+ * Not meant for use outside of testing. The call will not be
+ * functional on user builds.
+ */
+ void deactivatePackage(in @utf8InCpp String package_path);
+ /**
+ * Not meant for use outside of testing. The call will not be
+ * functional on user builds.
+ */
+ void preinstallPackages(in @utf8InCpp List<String> package_tmp_paths);
+ /**
+ * Not meant for use outside of testing. The call will not be
+ * functional on user builds.
+ */
+ void postinstallPackages(in @utf8InCpp List<String> package_tmp_paths);
+ /**
+ * Not meant for use outside of testing. The call will not be
+ * functional on user builds.
+ */
void stagePackages(in @utf8InCpp List<String> package_tmp_paths);
/**
* Not meant for use outside of testing. The call will not be
diff --git a/apexd/apex-info-list-api/current.txt b/apexd/apex-info-list-api/current.txt
index 8e8615f..8db5a9a 100644
--- a/apexd/apex-info-list-api/current.txt
+++ b/apexd/apex-info-list-api/current.txt
@@ -9,7 +9,6 @@
method public String getModuleName();
method public String getModulePath();
method public String getPreinstalledModulePath();
- method public boolean getProvideSharedApexLibs();
method public long getVersionCode();
method public String getVersionName();
method public void setIsActive(boolean);
@@ -18,7 +17,6 @@
method public void setModuleName(String);
method public void setModulePath(String);
method public void setPreinstalledModulePath(String);
- method public void setProvideSharedApexLibs(boolean);
method public void setVersionCode(long);
method public void setVersionName(String);
}
diff --git a/apexd/apex_classpath.cpp b/apexd/apex_classpath.cpp
deleted file mode 100644
index 68b3fdb..0000000
--- a/apexd/apex_classpath.cpp
+++ /dev/null
@@ -1,131 +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.
- */
-
-#include "apex_classpath.h"
-
-#include <android-base/file.h>
-#include <android-base/scopeguard.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <logwrap/logwrap.h>
-
-#include <fstream>
-#include <regex>
-
-namespace android {
-namespace apex {
-
-using ::android::base::Error;
-using ::android::base::StringPrintf;
-
-android::base::Result<ClassPath> ClassPath::DeriveClassPath(
- const std::vector<std::string>& temp_mounted_apex_paths,
- const std::string& sdkext_module_name) {
- if (temp_mounted_apex_paths.empty()) {
- return Error()
- << "Invalid argument: There are no APEX to derive claspath from";
- }
- // Call derive_classpath binary to generate required information
-
- // Prefer using the binary from staged session if possible
- std::string apex_of_binary =
- StringPrintf("/apex/%s", sdkext_module_name.c_str());
- for (const auto& temp_mounted_apex_path : temp_mounted_apex_paths) {
- if (temp_mounted_apex_path.starts_with(apex_of_binary + "@")) {
- apex_of_binary = temp_mounted_apex_path;
- break;
- }
- }
- std::string binary_path =
- StringPrintf("%s/bin/derive_classpath", apex_of_binary.c_str());
- std::string scan_dirs_flag =
- StringPrintf("--scan-dirs=%s",
- android::base::Join(temp_mounted_apex_paths, ",").c_str());
-
- // Create a temp file to write output
- auto temp_output_path = "/apex/derive_classpath_temp";
- auto cleanup = [temp_output_path]() {
- android::base::RemoveFileIfExists(temp_output_path);
- };
- auto scope_guard = android::base::make_scope_guard(cleanup);
- // Cleanup to ensure we are creating an empty file
- cleanup();
- // Create the empty file where derive_classpath will write into
- std::ofstream _(temp_output_path);
-
- const char* const argv[] = {binary_path.c_str(), scan_dirs_flag.c_str(),
- temp_output_path};
- auto rc = logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG,
- false, nullptr);
- if (rc != 0) {
- return Error() << "Running derive_classpath failed; binary path: " +
- binary_path;
- }
-
- return ClassPath::ParseFromFile(temp_output_path);
-}
-
-// Parse the string output into structured information
-// The raw output from derive_classpath has the following format:
-// ```
-// export BOOTCLASSPATH path/to/jar1:/path/to/jar2
-// export DEX2OATBOOTCLASSPATH
-// export SYSTEMSERVERCLASSPATH path/to/some/jar
-android::base::Result<ClassPath> ClassPath::ParseFromFile(
- const std::string& file_path) {
- ClassPath result;
-
- std::string contents;
- auto read_status = android::base::ReadFileToString(file_path, &contents,
- /*follow_symlinks=*/false);
- if (!read_status) {
- return Error() << "Failed to read classpath info from file";
- }
-
- // Jars in apex have the following format: /apex/<package-name>/*
- const std::regex capture_apex_package_name("^/apex/([^/]+)/");
-
- for (const auto& line : android::base::Split(contents, "\n")) {
- // Split the line by space. The second element determines which type of
- // classpath we are dealing with and the third element are the jars
- // separated by :
- auto tokens = android::base::Split(line, " ");
- if (tokens.size() < 3) {
- continue;
- }
- auto jars_list = tokens[2];
- for (const auto& jar_path : android::base::Split(jars_list, ":")) {
- std::smatch match;
- if (std::regex_search(jar_path, match, capture_apex_package_name)) {
- auto package_name = match[1];
- result.AddPackageWithClasspathJars(package_name);
- }
- }
- }
- return result;
-}
-
-void ClassPath::AddPackageWithClasspathJars(const std::string& package) {
- packages_with_classpath_jars.insert(package);
-}
-
-bool ClassPath::HasClassPathJars(const std::string& package) {
- return packages_with_classpath_jars.find(package) !=
- packages_with_classpath_jars.end();
-}
-
-} // namespace apex
-} // namespace android
diff --git a/apexd/apex_classpath.h b/apexd/apex_classpath.h
deleted file mode 100644
index de3d07f..0000000
--- a/apexd/apex_classpath.h
+++ /dev/null
@@ -1,59 +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.
- */
-
-#ifndef ANDROID_APEXD_APEX_CLASSPATH_H_
-#define ANDROID_APEXD_APEX_CLASSPATH_H_
-
-#include <android-base/result.h>
-
-#include <set>
-#include <string>
-
-namespace android {
-namespace apex {
-
-/**
- * An utility class that contains logic to extract classpath fragments
- * information from mounted APEX.
- *
- * The bulk of the work is done by derive_classpath binary, which is found
- * inside sdkext module. This class is a wrapper for calling that binary and
- * parsing its string output into a structured object.
- */
-class ClassPath {
- static constexpr const char* kSdkExtModuleName = "com.android.sdkext";
-
- public:
- static android::base::Result<ClassPath> DeriveClassPath(
- const std::vector<std::string>& temp_mounted_apex_paths,
- const std::string& sdkext_module_name = kSdkExtModuleName);
-
- bool HasClassPathJars(const std::string& package);
-
- // Exposed for testing only
- static android::base::Result<ClassPath> ParseFromFile(
- const std::string& file_path);
-
- private:
- void AddPackageWithClasspathJars(const std::string& package);
-
- std::set<std::string> packages_with_classpath_jars;
-};
-
-} // namespace apex
-} // namespace android
-
-#endif // ANDROID_APEXD_APEXD_CHECKPOINT_H_
diff --git a/apexd/apex_classpath_test.cpp b/apexd/apex_classpath_test.cpp
deleted file mode 100644
index efa4f3f..0000000
--- a/apexd/apex_classpath_test.cpp
+++ /dev/null
@@ -1,118 +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.
- */
-
-#include "apex_classpath.h"
-
-#include <android-base/file.h>
-#include <android-base/result-gmock.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <fstream>
-#include <string>
-
-namespace android {
-namespace apex {
-
-using android::base::WriteStringToFile;
-using android::base::testing::Ok;
-using android::base::testing::WithMessage;
-using ::testing::HasSubstr;
-
-TEST(ApexClassPathUnitTest, ParseFromFile) {
- TemporaryFile output;
- WriteStringToFile(
- "export BOOTCLASSPATH /apex/a/jar1:/apex/b/jar2\n"
- "export SYSTEMSERVERCLASSPATH\n"
- "export UNEXPECTED /apex/c/\n",
- output.path);
- auto result = ClassPath::ParseFromFile(output.path);
- ASSERT_THAT(result, Ok());
-
- ASSERT_THAT(result->HasClassPathJars("a"), true);
- ASSERT_THAT(result->HasClassPathJars("b"), true);
- ASSERT_THAT(result->HasClassPathJars("c"), true);
- ASSERT_THAT(result->HasClassPathJars("d"), false);
-}
-
-TEST(ApexClassPathUnitTest, ParseFromFileJarsNotInApex) {
- TemporaryFile output;
- // We accept jars with regex: /apex/<package-name>/*
- WriteStringToFile("export BOOTCLASSPATH a:b\n", output.path);
- auto result = ClassPath::ParseFromFile(output.path);
- ASSERT_THAT(result, Ok());
-
- ASSERT_THAT(result->HasClassPathJars("a"), false);
- ASSERT_THAT(result->HasClassPathJars("b"), false);
-}
-
-TEST(ApexClassPathUnitTest, ParseFromFilePackagesWithSamePrefix) {
- TemporaryFile output;
- WriteStringToFile(
- "export BOOTCLASSPATH /apex/media/:/apex/mediaprovider\n"
- "export SYSTEMSERVERCLASSPATH /apex/mediafoo/\n",
- output.path);
- auto result = ClassPath::ParseFromFile(output.path);
- ASSERT_THAT(result, Ok());
-
- ASSERT_THAT(result->HasClassPathJars("media"), true);
- // "/apex/mediaprovider" did not end with /
- ASSERT_THAT(result->HasClassPathJars("mediaprovider"), false);
- // A prefix of an apex name present should not be accepted
- ASSERT_THAT(result->HasClassPathJars("m"), false);
-}
-
-TEST(ApexClassPathUnitTest, ParseFromFileDoesNotExist) {
- auto result = ClassPath::ParseFromFile("/file/does/not/exist");
- ASSERT_THAT(result, HasError(WithMessage(HasSubstr(
- "Failed to read classpath info from file"))));
-}
-
-TEST(ApexClassPathUnitTest, ParseFromFileEmptyJars) {
- TemporaryFile output;
- WriteStringToFile(
- "export BOOTCLASSPATH\n"
- "export SYSTEMSERVERCLASSPATH \n"
- "export DEX2OATBOOTCLASSPATH \n",
- output.path);
- auto result = ClassPath::ParseFromFile(output.path);
- ASSERT_THAT(result, Ok());
-}
-
-TEST(ApexClassPathUnitTest, DeriveClassPathNoStagedApex) {
- auto result = ClassPath::DeriveClassPath({});
- ASSERT_THAT(
- result,
- HasError(WithMessage(HasSubstr(
- "Invalid argument: There are no APEX to derive claspath from"))));
-}
-
-TEST(ApexClassPathUnitTest, DeriveClassPathPreferBinaryInStagedApex) {
- // Default location uses provided package name to compose binary path
- auto result = ClassPath::DeriveClassPath({"/apex/temp@123"}, "different");
- ASSERT_THAT(result,
- HasError(WithMessage(HasSubstr(
- "binary path: /apex/different/bin/derive_classpath"))));
-
- // When staged apex has same package name, we use that location instead
- result = ClassPath::DeriveClassPath({"/apex/temp@123"}, "temp");
- ASSERT_THAT(result,
- HasError(WithMessage(HasSubstr(
- "binary path: /apex/temp@123/bin/derive_classpath"))));
-}
-
-} // namespace apex
-} // namespace android
diff --git a/apexd/apex_constants.h b/apexd/apex_constants.h
index edb51c3..798afd5 100644
--- a/apexd/apex_constants.h
+++ b/apexd/apex_constants.h
@@ -66,17 +66,6 @@
static constexpr const char* kApexStatusStarting = "starting";
static constexpr const char* kApexStatusActivated = "activated";
static constexpr const char* kApexStatusReady = "ready";
-static constexpr const char* kMultiApexSelectPersistPrefix =
- "persist.vendor.apex.";
-static constexpr const char* kMultiApexSelectBootconfigPrefix =
- "ro.boot.vendor.apex.";
-
-static constexpr const char* kVmPayloadMetadataPartitionProp =
- "apexd.payload_metadata.path";
-static constexpr const std::chrono::seconds kBlockApexWaitTime(10);
-
-static constexpr const char* kMetadataSepolicyStagedDir =
- "/metadata/sepolicy/staged";
// Banned APEX names
static const std::unordered_set<std::string> kBannedApexName = {
diff --git a/apexd/apex_file.cpp b/apexd/apex_file.cpp
index 9ed48aa..c043def 100644
--- a/apexd/apex_file.cpp
+++ b/apexd/apex_file.cpp
@@ -16,25 +16,25 @@
#include "apex_file.h"
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/scopeguard.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
#include <fcntl.h>
-#include <libavb/libavb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-#include <ziparchive/zip_archive.h>
#include <filesystem>
#include <fstream>
#include <span>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/scopeguard.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <libavb/libavb.h>
+#include <ziparchive/zip_archive.h>
+
#include "apex_constants.h"
#include "apexd_utils.h"
-#include "apexd_verity.h"
using android::base::borrowed_fd;
using android::base::ErrnoError;
@@ -60,10 +60,9 @@
const char* magic;
};
constexpr const FsMagic kFsType[] = {{"f2fs", 1024, 4, "\x10\x20\xf5\xf2"},
- {"ext4", 1024 + 0x38, 2, "\123\357"},
- {"erofs", 1024, 4, "\xe2\xe1\xf5\xe0"}};
+ {"ext4", 1024 + 0x38, 2, "\123\357"}};
-Result<std::string> RetrieveFsType(borrowed_fd fd, uint32_t image_offset) {
+Result<std::string> RetrieveFsType(borrowed_fd fd, int32_t image_offset) {
for (const auto& fs : kFsType) {
char buf[fs.len];
if (!ReadFullyAtOffset(fd, buf, fs.len, image_offset + fs.offset)) {
@@ -79,7 +78,7 @@
} // namespace
Result<ApexFile> ApexFile::Open(const std::string& path) {
- std::optional<uint32_t> image_offset;
+ std::optional<int32_t> image_offset;
std::optional<size_t> image_size;
std::string manifest_content;
std::string pubkey;
@@ -88,15 +87,14 @@
unique_fd fd(open(path.c_str(), O_RDONLY | O_BINARY | O_CLOEXEC));
if (fd < 0) {
- return ErrnoError() << "Failed to open package " << path << ": "
- << "I/O error";
+ return Error() << "Failed to open package " << path << ": "
+ << "I/O error";
}
ZipArchiveHandle handle;
auto handle_guard =
android::base::make_scope_guard([&handle] { CloseArchive(handle); });
- int ret = OpenArchiveFd(fd.get(), path.c_str(), &handle,
- /*assume_ownership=*/false);
+ int ret = OpenArchiveFd(fd.get(), path.c_str(), &handle, false);
if (ret < 0) {
return Error() << "Failed to open package " << path << ": "
<< ErrorCodeString(ret);
@@ -183,6 +181,16 @@
static constexpr int kVbMetaMaxSize = 64 * 1024;
+std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
+ std::ostringstream s;
+
+ s << std::hex << std::setfill('0');
+ for (size_t i = 0; i < bytes_len; i++) {
+ s << std::setw(2) << static_cast<int>(bytes[i]);
+ }
+ return s.str();
+}
+
std::string GetSalt(const AvbHashtreeDescriptor& desc,
const uint8_t* trailing_data) {
const uint8_t* desc_salt = trailing_data + desc.partition_name_len;
diff --git a/apexd/apex_file.h b/apexd/apex_file.h
index 56077bb..60d5feb 100644
--- a/apexd/apex_file.h
+++ b/apexd/apex_file.h
@@ -42,15 +42,12 @@
class ApexFile {
public:
static android::base::Result<ApexFile> Open(const std::string& path);
-
ApexFile() = delete;
ApexFile(ApexFile&&) = default;
ApexFile& operator=(ApexFile&&) = default;
const std::string& GetPath() const { return apex_path_; }
- const std::optional<uint32_t>& GetImageOffset() const {
- return image_offset_;
- }
+ const std::optional<int32_t>& GetImageOffset() const { return image_offset_; }
const std::optional<size_t>& GetImageSize() const { return image_size_; }
const ::apex::proto::ApexManifest& GetManifest() const { return manifest_; }
const std::string& GetBundledPublicKey() const { return apex_pubkey_; }
@@ -62,7 +59,7 @@
private:
ApexFile(const std::string& apex_path,
- const std::optional<uint32_t>& image_offset,
+ const std::optional<int32_t>& image_offset,
const std::optional<size_t>& image_size,
::apex::proto::ApexManifest manifest, const std::string& apex_pubkey,
const std::optional<std::string>& fs_type, bool is_compressed)
@@ -75,7 +72,7 @@
is_compressed_(is_compressed) {}
std::string apex_path_;
- std::optional<uint32_t> image_offset_;
+ std::optional<int32_t> image_offset_;
std::optional<size_t> image_size_;
::apex::proto::ApexManifest manifest_;
std::string apex_pubkey_;
diff --git a/apexd/apex_file_repository.cpp b/apexd/apex_file_repository.cpp
index e82feb4..c50d136 100644
--- a/apexd/apex_file_repository.cpp
+++ b/apexd/apex_file_repository.cpp
@@ -18,19 +18,17 @@
#include "apex_file_repository.h"
+#include <unordered_map>
+
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/result.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <microdroid/metadata.h>
-
-#include <unordered_map>
#include "apex_constants.h"
#include "apex_file.h"
#include "apexd_utils.h"
-#include "apexd_verity.h"
using android::base::EndsWith;
using android::base::Error;
@@ -40,24 +38,6 @@
namespace android {
namespace apex {
-std::string ConsumeApexPackageSuffix(const std::string& path) {
- std::string_view path_view(path);
- android::base::ConsumeSuffix(&path_view, kApexPackageSuffix);
- android::base::ConsumeSuffix(&path_view, kCompressedApexPackageSuffix);
- return std::string(path_view);
-}
-
-std::string GetApexSelectFilenameFromProp(
- const std::vector<std::string>& prefixes, const std::string& apex_name) {
- for (const std::string& prefix : prefixes) {
- const std::string& filename = GetProperty(prefix + apex_name, "");
- if (filename != "") {
- return ConsumeApexPackageSuffix(filename);
- }
- }
- return "";
-}
-
Result<void> ApexFileRepository::ScanBuiltInDir(const std::string& dir) {
LOG(INFO) << "Scanning " << dir << " for pre-installed ApexFiles";
if (access(dir.c_str(), F_OK) != 0 && errno == ENOENT) {
@@ -80,59 +60,6 @@
}
const std::string& name = apex_file->GetManifest().name();
-
- // Check if this APEX name is treated as a multi-install APEX.
- //
- // Note: apexd is a oneshot service which runs at boot, but can be restarted
- // when needed (such as staging an APEX update). If a multi-install select
- // property changes between boot and when apexd restarts, the LOG messages
- // below will report the version that will be activated on next reboot,
- // which may differ from the currently-active version.
- std::string select_filename = GetApexSelectFilenameFromProp(
- multi_install_select_prop_prefixes_, name);
- if (!select_filename.empty()) {
- std::string path;
- if (!android::base::Realpath(apex_file->GetPath(), &path)) {
- LOG(ERROR) << "Unable to resolve realpath of APEX with path "
- << apex_file->GetPath();
- continue;
- }
- if (enforce_multi_install_partition_ &&
- !android::base::StartsWith(path, "/vendor/apex/")) {
- LOG(ERROR) << "Multi-install APEX " << path
- << " can only be preinstalled on /vendor/apex/.";
- continue;
- }
-
- auto& keys = multi_install_public_keys_[name];
- keys.insert(apex_file->GetBundledPublicKey());
- if (keys.size() > 1) {
- LOG(ERROR) << "Multi-install APEXes for " << name
- << " have different public keys.";
- // If any versions of a multi-installed APEX differ in public key,
- // then no version should be installed.
- if (auto it = pre_installed_store_.find(name);
- it != pre_installed_store_.end()) {
- pre_installed_store_.erase(it);
- }
- continue;
- }
-
- if (ConsumeApexPackageSuffix(android::base::Basename(path)) ==
- select_filename) {
- LOG(INFO) << "Found APEX at path " << path << " for multi-install APEX "
- << name;
- // Add the APEX file to the store if its filename matches the property.
- pre_installed_store_.emplace(name, std::move(*apex_file));
- } else {
- LOG(INFO) << "Skipping APEX at path " << path
- << " because it does not match expected multi-install"
- << " APEX property for " << name;
- }
-
- continue;
- }
-
auto it = pre_installed_store_.find(name);
if (it == pre_installed_store_.end()) {
pre_installed_store_.emplace(name, std::move(*apex_file));
@@ -157,7 +84,6 @@
<< " (" << name << ") has unexpectedly changed";
}
}
- multi_install_public_keys_.clear();
return {};
}
@@ -176,130 +102,6 @@
return {};
}
-Result<int> ApexFileRepository::AddBlockApex(
- const std::string& metadata_partition) {
- CHECK(!block_disk_path_.has_value())
- << "AddBlockApex() can't be called twice.";
-
- auto metadata_ready = WaitForFile(metadata_partition, kBlockApexWaitTime);
- if (!metadata_ready.ok()) {
- LOG(ERROR) << "Error waiting for metadata_partition : "
- << metadata_ready.error();
- return {};
- }
-
- // TODO(b/185069443) consider moving the logic to find disk_path from
- // metadata_partition to its own library
- LOG(INFO) << "Scanning " << metadata_partition << " for host apexes";
- if (access(metadata_partition.c_str(), F_OK) != 0 && errno == ENOENT) {
- LOG(WARNING) << metadata_partition << " does not exist. Skipping";
- return {};
- }
-
- std::string metadata_realpath;
- if (!android::base::Realpath(metadata_partition, &metadata_realpath)) {
- LOG(WARNING) << "Can't get realpath of " << metadata_partition
- << ". Skipping";
- return {};
- }
-
- std::string_view metadata_path_view(metadata_realpath);
- if (!android::base::ConsumeSuffix(&metadata_path_view, "1")) {
- LOG(WARNING) << metadata_realpath << " is not a first partition. Skipping";
- return {};
- }
-
- block_disk_path_ = std::string(metadata_path_view);
-
- // Read the payload metadata.
- // "metadata" can be overridden by microdroid_manager. To ensure that
- // "microdroid" is started with the same/unmodified set of host APEXes,
- // microdroid stores APEXes' pubkeys in its encrypted instance disk. Next
- // time, microdroid checks if there's pubkeys in the instance disk and use
- // them to activate APEXes. Microdroid_manager passes pubkeys in instance.img
- // via the following file.
- if (auto exists = PathExists("/apex/vm-payload-metadata");
- exists.ok() && *exists) {
- metadata_realpath = "/apex/vm-payload-metadata";
- LOG(INFO) << "Overriding metadata to " << metadata_realpath;
- }
- auto metadata = android::microdroid::ReadMetadata(metadata_realpath);
- if (!metadata.ok()) {
- LOG(WARNING) << "Failed to load metadata from " << metadata_realpath
- << ". Skipping: " << metadata.error();
- return {};
- }
-
- int ret = 0;
-
- // subsequent partitions are APEX archives.
- static constexpr const int kFirstApexPartition = 2;
- for (int i = 0; i < metadata->apexes_size(); i++) {
- const auto& apex_config = metadata->apexes(i);
-
- const std::string apex_path =
- *block_disk_path_ + std::to_string(i + kFirstApexPartition);
-
- auto apex_ready = WaitForFile(apex_path, kBlockApexWaitTime);
- if (!apex_ready.ok()) {
- return Error() << "Error waiting for apex file : " << apex_ready.error();
- }
-
- auto apex_file = ApexFile::Open(apex_path);
- if (!apex_file.ok()) {
- return Error() << "Failed to open " << apex_path << " : "
- << apex_file.error();
- }
-
- // When metadata specifies the public key of the apex, it should match the
- // bundled key. Otherwise we accept it.
- if (apex_config.public_key() != "" &&
- apex_config.public_key() != apex_file->GetBundledPublicKey()) {
- return Error() << "public key doesn't match: " << apex_path;
- }
-
- const std::string& name = apex_file->GetManifest().name();
-
- BlockApexOverride overrides;
-
- // A block device doesn't have an inherent timestamp, so it is carried in
- // the metadata.
- if (int64_t last_update_seconds = apex_config.last_update_seconds();
- last_update_seconds != 0) {
- overrides.last_update_seconds = last_update_seconds;
- }
-
- // When metadata specifies the root digest of the apex, it should be used
- // when activating the apex. So we need to keep it.
- if (auto root_digest = apex_config.root_digest(); root_digest != "") {
- overrides.block_apex_root_digest =
- BytesToHex(reinterpret_cast<const uint8_t*>(root_digest.data()),
- root_digest.size());
- }
-
- if (overrides.last_update_seconds.has_value() ||
- overrides.block_apex_root_digest.has_value()) {
- block_apex_overrides_.emplace(name, std::move(overrides));
- }
-
- // APEX should be unique.
- for (const auto* store : {&pre_installed_store_, &data_store_}) {
- auto it = store->find(name);
- if (it != store->end()) {
- return Error() << "duplicate of " << name << " found in "
- << it->second.GetPath();
- }
- }
- // Depending on whether the APEX was a factory version in the host or not,
- // put it to different stores.
- auto& store = apex_config.is_factory() ? pre_installed_store_ : data_store_;
- store.emplace(name, std::move(*apex_file));
-
- ret++;
- }
- return {ret};
-}
-
// TODO(b/179497746): AddDataApex should not concern with filtering out invalid
// apex.
Result<void> ApexFileRepository::AddDataApex(const std::string& data_dir) {
@@ -326,19 +128,10 @@
const std::string& name = apex_file->GetManifest().name();
if (!HasPreInstalledVersion(name)) {
- LOG(ERROR) << "Skipping " << file << " : no preinstalled apex";
+ LOG(ERROR) << "Skipping " << file << " : no preisntalled apex";
// Ignore data apex without corresponding pre-installed apex
continue;
}
-
- std::string select_filename = GetApexSelectFilenameFromProp(
- multi_install_select_prop_prefixes_, name);
- if (!select_filename.empty()) {
- LOG(WARNING) << "APEX " << name << " is a multi-installed APEX."
- << " Any updated version in /data will always overwrite"
- << " the multi-installed preinstalled version, if possible.";
- }
-
auto pre_installed_public_key = GetPublicKey(name);
if (!pre_installed_public_key.ok() ||
apex_file->GetBundledPublicKey() != *pre_installed_public_key) {
@@ -379,14 +172,6 @@
const std::string& name) const {
auto it = pre_installed_store_.find(name);
if (it == pre_installed_store_.end()) {
- // Special casing for APEXes backed by block devices, i.e. APEXes in VM.
- // Inside a VM, we fall back to find the key from data_store_. This is
- // because an APEX is put to either pre_installed_store_ or data_store,
- // depending on whether it was a factory APEX or not in the host.
- it = data_store_.find(name);
- if (it != data_store_.end() && IsBlockApex(it->second)) {
- return it->second.GetBundledPublicKey();
- }
return Error() << "No preinstalled apex found for package " << name;
}
return it->second.GetBundledPublicKey();
@@ -414,24 +199,6 @@
return it->second.GetPath();
}
-std::optional<std::string> ApexFileRepository::GetBlockApexRootDigest(
- const std::string& name) const {
- auto it = block_apex_overrides_.find(name);
- if (it == block_apex_overrides_.end()) {
- return std::nullopt;
- }
- return it->second.block_apex_root_digest;
-}
-
-std::optional<int64_t> ApexFileRepository::GetBlockApexLastUpdateSeconds(
- const std::string& name) const {
- auto it = block_apex_overrides_.find(name);
- if (it == block_apex_overrides_.end()) {
- return std::nullopt;
- }
- return it->second.last_update_seconds;
-}
-
bool ApexFileRepository::HasPreInstalledVersion(const std::string& name) const {
return pre_installed_store_.find(name) != pre_installed_store_.end();
}
@@ -454,11 +221,6 @@
return it->second.GetPath() == apex.GetPath() || IsDecompressedApex(apex);
}
-bool ApexFileRepository::IsBlockApex(const ApexFile& apex) const {
- return block_disk_path_.has_value() &&
- apex.GetPath().starts_with(*block_disk_path_);
-}
-
std::vector<ApexFileRef> ApexFileRepository::GetPreInstalledApexFiles() const {
std::vector<ApexFileRef> result;
for (const auto& it : pre_installed_store_) {
diff --git a/apexd/apex_file_repository.h b/apexd/apex_file_repository.h
index 1a1cf94..e9ccf7e 100644
--- a/apexd/apex_file_repository.h
+++ b/apexd/apex_file_repository.h
@@ -16,18 +16,15 @@
#pragma once
-#include <android-base/result.h>
-
#include <functional>
-#include <optional>
#include <string>
#include <unordered_map>
-#include <unordered_set>
#include <vector>
-
#include "apex_constants.h"
#include "apex_file.h"
+#include <android-base/result.h>
+
namespace android {
namespace apex {
@@ -42,15 +39,10 @@
// mounts apexes (e.g. apexd, otapreopt_chroot).
class ApexFileRepository final {
public:
- // c-tors and d-tor are exposed for testing.
+ // c-tor and d-tor are exposed for testing.
explicit ApexFileRepository(
const std::string& decompression_dir = kApexDecompressedDir)
: decompression_dir_(decompression_dir){};
- explicit ApexFileRepository(
- bool enforce_multi_install_partition,
- const std::vector<std::string>& multi_install_select_prop_prefixes)
- : multi_install_select_prop_prefixes_(multi_install_select_prop_prefixes),
- enforce_multi_install_partition_(enforce_multi_install_partition){};
~ApexFileRepository() {
pre_installed_store_.clear();
@@ -68,24 +60,6 @@
android::base::Result<void> AddPreInstalledApex(
const std::vector<std::string>& prebuilt_dirs);
- // Populate instance by collecting host-provided apex files via
- // |metadata_partition|. Host can provide its apexes to a VM instance via the
- // virtual disk image which has partitions: (see
- // /packages/modules/Virtualization/microdroid for the details)
- // - metadata partition(/dev/block/vd*1) should be accessed by
- // setting the system property apexd.payload_metadata.prop. On microdroid,
- // this is /dev/block/by-name/payload-metadata.
- // - each subsequence partition(/dev/block/vd*{2,3,..}) represents an APEX
- // archive.
- // It will fail if there is more than one apex with the same name in
- // pre-installed and block apexes. Note: this call is **not thread safe** and
- // is expected to be performed in a single thread during initialization of
- // apexd. After initialization is finished, all queries to the instance are
- // thread safe.
- // This will return the number of block apexes that were added.
- android::base::Result<int> AddBlockApex(
- const std::string& metadata_partition);
-
// Populate instance by collecting data apex files from the given |data_dir|.
// Note: this call is **not thread safe** and is expected to be performed in a
// single thread during initialization of apexd. After initialization is
@@ -104,14 +78,6 @@
android::base::Result<const std::string> GetDataPath(
const std::string& name) const;
- // Returns root digest of an apex with the given |name| for block apexes.
- std::optional<std::string> GetBlockApexRootDigest(
- const std::string& name) const;
-
- // Returns timestamp to be used for the block apex of the given |name|.
- std::optional<int64_t> GetBlockApexLastUpdateSeconds(
- const std::string& name) const;
-
// Checks whether there is a pre-installed version of an apex with the given
// |name|.
bool HasPreInstalledVersion(const std::string& name) const;
@@ -125,9 +91,6 @@
// Checks if given |apex| is decompressed from a pre-installed APEX
bool IsDecompressedApex(const ApexFile& apex) const;
- // Checks if given |apex| is loaded from block device.
- bool IsBlockApex(const ApexFile& apex) const;
-
// Returns reference to all pre-installed APEX on device
std::vector<ApexFileRef> GetPreInstalledApexFiles() const;
@@ -152,9 +115,7 @@
void Reset(const std::string& decompression_dir = kApexDecompressedDir) {
pre_installed_store_.clear();
data_store_.clear();
- block_apex_overrides_.clear();
decompression_dir_ = decompression_dir;
- block_disk_path_.reset();
}
private:
@@ -169,41 +130,9 @@
android::base::Result<void> ScanBuiltInDir(const std::string& dir);
std::unordered_map<std::string, ApexFile> pre_installed_store_, data_store_;
-
- // Multi-installed APEX name -> all encountered public keys for this APEX.
- std::unordered_map<std::string, std::unordered_set<std::string>>
- multi_install_public_keys_;
-
- // Prefixes used when looking for multi-installed APEX sysprops.
- // Order matters: the first non-empty prop value is returned.
- std::vector<std::string> multi_install_select_prop_prefixes_ = {
- // Check persist props first, to allow users to override bootconfig.
- kMultiApexSelectPersistPrefix,
- kMultiApexSelectBootconfigPrefix,
- };
-
- // Allows multi-install APEXes outside of expected partitions.
- // Only set false in tests.
- bool enforce_multi_install_partition_ = true;
-
// Decompression directory which will be used to determine if apex is
// decompressed or not
std::string decompression_dir_;
-
- // Disk path where block apexes are read from. AddBlockApex() sets this.
- std::optional<std::string> block_disk_path_;
-
- // Information from the metadata for block apexes, overriding the file data.
- struct BlockApexOverride {
- // Root digest for the APEX. When specified in block apex config, it
- // should be used/checked when activating the apex to avoid
- // TOCTOU(time-of-check to time-of-use).
- std::optional<std::string> block_apex_root_digest;
- // The last update time of the APEX.
- std::optional<int64_t> last_update_seconds;
- };
-
- std::unordered_map<std::string, BlockApexOverride> block_apex_overrides_;
};
} // namespace apex
diff --git a/apexd/apex_file_repository_test.cpp b/apexd/apex_file_repository_test.cpp
index bf73092..c1f5d53 100644
--- a/apexd/apex_file_repository_test.cpp
+++ b/apexd/apex_file_repository_test.cpp
@@ -14,22 +14,20 @@
* limitations under the License.
*/
-#include "apex_file_repository.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <errno.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <microdroid/metadata.h>
-#include <sys/stat.h>
-
#include <filesystem>
#include <string>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
#include "apex_file.h"
+#include "apex_file_repository.h"
#include "apexd_test_utils.h"
#include "apexd_verity.h"
@@ -162,90 +160,6 @@
"");
}
-TEST(ApexFileRepositoryTest, InitializeMultiInstalledSuccess) {
- // Prepare test data.
- TemporaryDir td;
- std::string apex_file = GetTestFile("apex.apexd_test.apex");
- fs::copy(apex_file, StringPrintf("%s/version_a.apex", td.path));
- fs::copy(apex_file, StringPrintf("%s/version_b.apex", td.path));
- std::string apex_name = ApexFile::Open(apex_file)->GetManifest().name();
-
- std::string persist_prefix = "debug.apexd.test.persistprefix.";
- std::string bootconfig_prefix = "debug.apexd.test.bootconfigprefix.";
- ApexFileRepository instance(/*enforce_multi_install_partition=*/false,
- /*multi_install_select_prop_prefixes=*/{
- persist_prefix, bootconfig_prefix});
-
- auto test_fn = [&](const std::string& selected_filename) {
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
- auto ret = instance.GetPreinstalledPath(apex_name);
- ASSERT_TRUE(IsOk(ret));
- ASSERT_EQ(StringPrintf("%s/%s", td.path, selected_filename.c_str()), *ret);
- instance.Reset();
- };
-
- // Start with version_a in bootconfig.
- android::base::SetProperty(bootconfig_prefix + apex_name, "version_a.apex");
- test_fn("version_a.apex");
- // Developer chooses version_b with persist prop.
- android::base::SetProperty(persist_prefix + apex_name, "version_b.apex");
- test_fn("version_b.apex");
- // Developer goes back to version_a with persist prop.
- android::base::SetProperty(persist_prefix + apex_name, "version_a.apex");
- test_fn("version_a.apex");
-
- android::base::SetProperty(persist_prefix + apex_name, "");
- android::base::SetProperty(bootconfig_prefix + apex_name, "");
-}
-
-TEST(ApexFileRepositoryTest, InitializeMultiInstalledSkipsForDifferingKeys) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("apex.apexd_test.apex"),
- StringPrintf("%s/version_a.apex", td.path));
- fs::copy(GetTestFile("apex.apexd_test_different_key.apex"),
- StringPrintf("%s/version_b.apex", td.path));
- std::string apex_name =
- ApexFile::Open(GetTestFile("apex.apexd_test.apex"))->GetManifest().name();
- std::string prop_prefix = "debug.apexd.test.bootconfigprefix.";
- std::string prop = prop_prefix + apex_name;
- android::base::SetProperty(prop, "version_a.apex");
-
- ApexFileRepository instance(
- /*enforce_multi_install_partition=*/false,
- /*multi_install_select_prop_prefixes=*/{prop_prefix});
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
- // Neither version should be have been installed.
- ASSERT_FALSE(IsOk(instance.GetPreinstalledPath(apex_name)));
-
- android::base::SetProperty(prop, "");
-}
-
-TEST(ApexFileRepositoryTest, InitializeMultiInstalledSkipsForInvalidPartition) {
- // Prepare test data.
- TemporaryDir td;
- // Note: These test files are on /data, which is not a valid partition for
- // multi-installed APEXes.
- fs::copy(GetTestFile("apex.apexd_test.apex"),
- StringPrintf("%s/version_a.apex", td.path));
- fs::copy(GetTestFile("apex.apexd_test.apex"),
- StringPrintf("%s/version_b.apex", td.path));
- std::string apex_name =
- ApexFile::Open(GetTestFile("apex.apexd_test.apex"))->GetManifest().name();
- std::string prop_prefix = "debug.apexd.test.bootconfigprefix.";
- std::string prop = prop_prefix + apex_name;
- android::base::SetProperty(prop, "version_a.apex");
-
- ApexFileRepository instance(
- /*enforce_multi_install_partition=*/true,
- /*multi_install_select_prop_prefixes=*/{prop_prefix});
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
- // Neither version should be have been installed.
- ASSERT_FALSE(IsOk(instance.GetPreinstalledPath(apex_name)));
-
- android::base::SetProperty(prop, "");
-}
-
TEST(ApexFileRepositoryTest,
InitializeSameNameDifferentPathAbortsCompressedApex) {
// Prepare test data.
@@ -588,236 +502,5 @@
"");
}
-struct ApexFileRepositoryTestAddBlockApex : public ::testing::Test {
- TemporaryDir test_dir;
-
- struct PayloadMetadata {
- android::microdroid::Metadata metadata;
- std::string path;
- PayloadMetadata(const std::string& path) : path(path) {}
- PayloadMetadata& apex(const std::string& name,
- const std::string& public_key = "",
- const std::string& root_digest = "",
- int64_t last_update_seconds = 0,
- bool is_factory = true) {
- auto apex = metadata.add_apexes();
- apex->set_name(name);
- apex->set_public_key(public_key);
- apex->set_root_digest(root_digest);
- apex->set_last_update_seconds(last_update_seconds);
- apex->set_is_factory(is_factory);
- return *this;
- }
- ~PayloadMetadata() {
- metadata.set_version(1);
- std::ofstream out(path);
- android::microdroid::WriteMetadata(metadata, out);
- }
- };
-};
-
-TEST_F(ApexFileRepositoryTestAddBlockApex,
- ScansPayloadDisksAndAddApexFilesToPreInstalled) {
- // prepare payload disk
- // <test-dir>/vdc1 : metadata
- // /vdc2 : apex.apexd_test.apex
- // /vdc3 : apex.apexd_test_different_app.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
- const auto& test_apex_bar = GetTestFile("apex.apexd_test_different_app.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
- const std::string apex_bar_path = test_dir.path + "/vdc3"s;
-
- PayloadMetadata(metadata_partition_path)
- .apex(test_apex_foo)
- .apex(test_apex_bar);
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
- auto loop_device2 = WriteBlockApex(test_apex_bar, apex_bar_path);
-
- // call ApexFileRepository::AddBlockApex()
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_RESULT_OK(status);
-
- auto apex_foo = ApexFile::Open(apex_foo_path);
- ASSERT_RESULT_OK(apex_foo);
- // block apexes can be identified with IsBlockApex
- ASSERT_TRUE(instance.IsBlockApex(*apex_foo));
-
- // "block" apexes are treated as "pre-installed"
- auto ret_foo = instance.GetPreInstalledApex("com.android.apex.test_package");
- ASSERT_THAT(ret_foo, ApexFileEq(ByRef(*apex_foo)));
-
- auto apex_bar = ApexFile::Open(apex_bar_path);
- ASSERT_RESULT_OK(apex_bar);
- auto ret_bar =
- instance.GetPreInstalledApex("com.android.apex.test_package_2");
- ASSERT_THAT(ret_bar, ApexFileEq(ByRef(*apex_bar)));
-}
-
-TEST_F(ApexFileRepositoryTestAddBlockApex,
- ScansOnlySpecifiedInMetadataPartition) {
- // prepare payload disk
- // <test-dir>/vdc1 : metadata with apex.apexd_test.apex only
- // /vdc2 : apex.apexd_test.apex
- // /vdc3 : apex.apexd_test_different_app.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
- const auto& test_apex_bar = GetTestFile("apex.apexd_test_different_app.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
- const std::string apex_bar_path = test_dir.path + "/vdc3"s;
-
- // metadata lists only "foo"
- PayloadMetadata(metadata_partition_path).apex(test_apex_foo);
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
- auto loop_device2 = WriteBlockApex(test_apex_bar, apex_bar_path);
-
- // call ApexFileRepository::AddBlockApex()
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_RESULT_OK(status);
-
- // foo is added, but bar is not
- auto ret_foo = instance.GetPreinstalledPath("com.android.apex.test_package");
- ASSERT_TRUE(IsOk(ret_foo));
- ASSERT_EQ(apex_foo_path, *ret_foo);
- auto ret_bar =
- instance.GetPreinstalledPath("com.android.apex.test_package_2");
- ASSERT_FALSE(IsOk(ret_bar));
-}
-
-TEST_F(ApexFileRepositoryTestAddBlockApex, FailsWhenTheresDuplicateNames) {
- // prepare payload disk
- // <test-dir>/vdc1 : metadata with v1 and v2 of apex.apexd_test
- // /vdc2 : apex.apexd_test.apex
- // /vdc3 : apex.apexd_test_v2.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
- const auto& test_apex_bar = GetTestFile("apex.apexd_test_v2.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
- const std::string apex_bar_path = test_dir.path + "/vdc3"s;
-
- PayloadMetadata(metadata_partition_path)
- .apex(test_apex_foo)
- .apex(test_apex_bar);
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
- auto loop_device2 = WriteBlockApex(test_apex_bar, apex_bar_path);
-
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_FALSE(IsOk(status));
-}
-
-TEST_F(ApexFileRepositoryTestAddBlockApex, GetBlockApexRootDigest) {
- // prepare payload disk with root digest
- // <test-dir>/vdc1 : metadata with apex.apexd_test.apex only
- // /vdc2 : apex.apexd_test.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
-
- // root digest is stored as bytes in metadata and as hexadecimal in
- // ApexFileRepository
- const std::string root_digest = "root_digest";
- const std::string hex_root_digest = BytesToHex(
- reinterpret_cast<const uint8_t*>(root_digest.data()), root_digest.size());
-
- // metadata lists "foo"
- PayloadMetadata(metadata_partition_path)
- .apex(test_apex_foo, /*public_key=*/"", root_digest);
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
-
- // call ApexFileRepository::AddBlockApex()
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_TRUE(IsOk(status));
-
- ASSERT_EQ(hex_root_digest,
- instance.GetBlockApexRootDigest("com.android.apex.test_package"));
-}
-
-TEST_F(ApexFileRepositoryTestAddBlockApex, GetBlockApexLastUpdateSeconds) {
- // prepare payload disk with last update time
- // <test-dir>/vdc1 : metadata with apex.apexd_test.apex only
- // /vdc2 : apex.apexd_test.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
-
- const int64_t last_update_seconds = 123456789;
-
- // metadata lists "foo"
- PayloadMetadata(metadata_partition_path)
- .apex(test_apex_foo, /*public_key=*/"", /*root_digest=*/"",
- last_update_seconds);
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
-
- // call ApexFileRepository::AddBlockApex()
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_TRUE(IsOk(status));
-
- ASSERT_EQ(last_update_seconds, instance.GetBlockApexLastUpdateSeconds(
- "com.android.apex.test_package"));
-}
-
-TEST_F(ApexFileRepositoryTestAddBlockApex, VerifyPublicKeyWhenAddingBlockApex) {
- // prepare payload disk
- // <test-dir>/vdc1 : metadata with apex.apexd_test.apex only
- // /vdc2 : apex.apexd_test.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
-
- // metadata lists "foo"
- PayloadMetadata(metadata_partition_path)
- .apex(test_apex_foo, /*public_key=*/"wrong public key");
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
-
- // call ApexFileRepository::AddBlockApex()
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_FALSE(IsOk(status));
-}
-
-TEST_F(ApexFileRepositoryTestAddBlockApex, RespectIsFactoryBitFromMetadata) {
- // prepare payload disk
- // <test-dir>/vdc1 : metadata with apex.apexd_test.apex only
- // /vdc2 : apex.apexd_test.apex
-
- const auto& test_apex_foo = GetTestFile("apex.apexd_test.apex");
-
- const std::string metadata_partition_path = test_dir.path + "/vdc1"s;
- const std::string apex_foo_path = test_dir.path + "/vdc2"s;
- auto loop_device1 = WriteBlockApex(test_apex_foo, apex_foo_path);
-
- for (const bool is_factory : {true, false}) {
- // metadata lists "foo"
- PayloadMetadata(metadata_partition_path)
- .apex(test_apex_foo, /*public_key=*/"", /*root_digest=*/"",
- /*last_update_seconds=*/0, is_factory);
-
- // call ApexFileRepository::AddBlockApex()
- ApexFileRepository instance;
- auto status = instance.AddBlockApex(metadata_partition_path);
- ASSERT_TRUE(IsOk(status))
- << "failed to add block apex with is_factory=" << is_factory;
- ASSERT_EQ(is_factory,
- instance.HasPreInstalledVersion("com.android.apex.test_package"));
- }
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apex_file_test.cpp b/apexd/apex_file_test.cpp
index a9d83a2..3da7448 100644
--- a/apexd/apex_file_test.cpp
+++ b/apexd/apex_file_test.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <limits>
#include <string>
#include <android-base/file.h>
@@ -45,9 +44,7 @@
};
constexpr const ApexFileTestParam kParameters[] = {
- {"ext4", "apex.apexd_test"},
- {"f2fs", "apex.apexd_test_f2fs"},
- {"erofs", "apex.apexd_test_erofs"}};
+ {"ext4", "apex.apexd_test"}, {"f2fs", "apex.apexd_test_f2fs"}};
class ApexFileTest : public ::testing::TestWithParam<ApexFileTestParam> {};
@@ -58,7 +55,7 @@
Result<ApexFile> apex_file = ApexFile::Open(file_path);
ASSERT_TRUE(apex_file.ok());
- uint32_t zip_image_offset;
+ int32_t zip_image_offset;
size_t zip_image_size;
{
ZipArchiveHandle handle;
@@ -72,7 +69,7 @@
ASSERT_EQ(0, rc);
zip_image_offset = entry.offset;
- EXPECT_EQ(zip_image_offset % 4096, 0U);
+ EXPECT_EQ(zip_image_offset % 4096, 0);
zip_image_size = entry.uncompressed_length;
EXPECT_EQ(zip_image_size, entry.compressed_length);
}
@@ -81,21 +78,6 @@
EXPECT_EQ(zip_image_size, apex_file->GetImageSize().value());
}
-TEST_P(ApexFileTest, OpenBlockApex) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
-
- TemporaryFile temp_file;
- auto loop_device = WriteBlockApex(file_path, temp_file.path);
-
- Result<ApexFile> apex_file_sized = ApexFile::Open(temp_file.path);
- ASSERT_RESULT_OK(apex_file_sized);
-
- EXPECT_EQ(apex_file->GetImageOffset(), apex_file_sized->GetImageOffset());
- EXPECT_EQ(apex_file->GetImageSize(), apex_file_sized->GetImageSize());
-}
-
TEST(ApexFileTest, GetOffsetMissingFile) {
const std::string file_path = kTestDataDir + "missing.apex";
Result<ApexFile> apex_file = ApexFile::Open(file_path);
@@ -241,7 +223,7 @@
::testing::HasSubstr("Cannot verify ApexVerity of compressed APEX"));
}
-TEST(ApexFileTest, DISABLED_DecompressCompressedApex) {
+TEST(ApexFileTest, DecompressCompressedApex) {
const std::string file_path =
kTestDataDir + "com.android.apex.compressed.v1.capex";
Result<ApexFile> apex_file = ApexFile::Open(file_path);
diff --git a/apexd/apex_shim.cpp b/apexd/apex_shim.cpp
index 441c971..0031c3f 100644
--- a/apexd/apex_shim.cpp
+++ b/apexd/apex_shim.cpp
@@ -53,17 +53,8 @@
"apex_manifest.pb",
"etc/hash.txt",
"app/CtsShim/CtsShim.apk",
- "app/CtsShim@1/CtsShim.apk",
- "app/CtsShim@2/CtsShim.apk",
- "app/CtsShim@3/CtsShim.apk",
"app/CtsShimTargetPSdk/CtsShimTargetPSdk.apk",
- "app/CtsShimTargetPSdk@1/CtsShimTargetPSdk.apk",
- "app/CtsShimTargetPSdk@2/CtsShimTargetPSdk.apk",
- "app/CtsShimTargetPSdk@3/CtsShimTargetPSdk.apk",
"priv-app/CtsShimPriv/CtsShimPriv.apk",
- "priv-app/CtsShimPriv@1/CtsShimPriv.apk",
- "priv-app/CtsShimPriv@2/CtsShimPriv.apk",
- "priv-app/CtsShimPriv@3/CtsShimPriv.apk",
};
Result<std::string> CalculateSha512(const std::string& path) {
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index ff60ed7..e0562f0 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -14,9 +14,24 @@
* limitations under the License.
*/
-#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
-
#include "apexd.h"
+#include "apex_file_repository.h"
+#include "apexd_private.h"
+
+#include "apex_constants.h"
+#include "apex_database.h"
+#include "apex_file.h"
+#include "apex_manifest.h"
+#include "apex_shim.h"
+#include "apexd_checkpoint.h"
+#include "apexd_lifecycle.h"
+#include "apexd_loop.h"
+#include "apexd_prepostinstall.h"
+#include "apexd_rollback_utils.h"
+#include "apexd_session.h"
+#include "apexd_utils.h"
+#include "apexd_verity.h"
+#include "com_android_apex.h"
#include <ApexProperties.sysprop.h>
#include <android-base/chrono_utils.h>
@@ -29,16 +44,17 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <dirent.h>
-#include <fcntl.h>
#include <google/protobuf/util/message_differencer.h>
#include <libavb/libavb.h>
#include <libdm/dm.h>
#include <libdm/dm_table.h>
#include <libdm/dm_target.h>
+#include <selinux/android.h>
+
+#include <dirent.h>
+#include <fcntl.h>
#include <linux/f2fs.h>
#include <linux/loop.h>
-#include <selinux/android.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
@@ -47,7 +63,7 @@
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
-#include <utils/Trace.h>
+#include <algorithm>
#include <algorithm>
#include <array>
@@ -69,23 +85,6 @@
#include <unordered_map>
#include <unordered_set>
-#include "VerityUtils.h"
-#include "apex_constants.h"
-#include "apex_database.h"
-#include "apex_file.h"
-#include "apex_file_repository.h"
-#include "apex_manifest.h"
-#include "apex_shim.h"
-#include "apexd_checkpoint.h"
-#include "apexd_lifecycle.h"
-#include "apexd_loop.h"
-#include "apexd_private.h"
-#include "apexd_rollback_utils.h"
-#include "apexd_session.h"
-#include "apexd_utils.h"
-#include "apexd_verity.h"
-#include "com_android_apex.h"
-
using android::base::boot_clock;
using android::base::ConsumePrefix;
using android::base::ErrnoError;
@@ -93,10 +92,10 @@
using android::base::GetProperty;
using android::base::Join;
using android::base::ParseUint;
+using android::base::ReadFully;
using android::base::RemoveFileIfExists;
using android::base::Result;
using android::base::SetProperty;
-using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
using android::dm::DeviceMapper;
@@ -128,15 +127,6 @@
bool gSupportsFsCheckpoints = false;
bool gInFsCheckpointMode = false;
-// APEXEs for which a different version was activated than in the previous boot.
-// This can happen in the following scenarios:
-// 1. This APEX is part of the staged session that was applied during this
-// boot.
-// 2. This is a compressed APEX that was decompressed during this boot.
-// 3. We failed to activate APEX from /data/apex/active and fallback to the
-// pre-installed APEX.
-std::set<std::string> gChangedActiveApexes;
-
static constexpr size_t kLoopDeviceSetupAttempts = 3u;
// Please DO NOT add new modules to this list without contacting mainline-modularization@ first.
@@ -314,9 +304,22 @@
bool cleared_;
};
-Result<DmVerityDevice> CreateVerityDevice(
- DeviceMapper& dm, const std::string& name, const DmTable& table,
- const std::chrono::milliseconds& timeout) {
+Result<DmVerityDevice> CreateVerityDevice(const std::string& name,
+ const DmTable& table) {
+ DeviceMapper& dm = DeviceMapper::Instance();
+
+ if (dm.GetState(name) != DmDeviceState::INVALID) {
+ // Delete dangling dm-device. This can happen if apexd fails to delete it
+ // while unmounting an apex.
+ LOG(WARNING) << "Deleting existing dm device " << name;
+ auto result = DeleteVerityDevice(name, /* deferred= */ false);
+ if (!result.ok()) {
+ return result.error();
+ }
+ }
+
+ auto timeout = std::chrono::milliseconds(
+ android::sysprop::ApexProperties::dm_create_timeout().value_or(1000));
std::string dev_path;
if (!dm.CreateDevice(name, table, &dev_path, timeout)) {
return Errorf("Couldn't create verity device.");
@@ -324,52 +327,6 @@
return DmVerityDevice(name, dev_path);
}
-Result<DmVerityDevice> CreateVerityDevice(const std::string& name,
- const DmTable& table,
- bool reuse_device) {
- ATRACE_NAME("CreateVerityDevice");
- LOG(VERBOSE) << "Creating verity device " << name;
- auto timeout = std::chrono::milliseconds(
- android::sysprop::ApexProperties::dm_create_timeout().value_or(1000));
-
- DeviceMapper& dm = DeviceMapper::Instance();
-
- auto state = dm.GetState(name);
- if (state == DmDeviceState::INVALID) {
- return CreateVerityDevice(dm, name, table, timeout);
- }
-
- if (reuse_device) {
- if (state == DmDeviceState::ACTIVE) {
- LOG(WARNING) << "Deleting existing active dm device " << name;
- if (auto r = DeleteVerityDevice(name, /* deferred= */ false); !r.ok()) {
- return r.error();
- }
- return CreateVerityDevice(dm, name, table, timeout);
- }
- if (!dm.LoadTableAndActivate(name, table)) {
- dm.DeleteDevice(name);
- return Error() << "Failed to activate dm device " << name;
- }
- std::string path;
- if (!dm.WaitForDevice(name, timeout, &path)) {
- dm.DeleteDevice(name);
- return Error() << "Failed waiting for dm device " << name;
- }
- return DmVerityDevice(name, path);
- } else {
- if (state != DmDeviceState::INVALID) {
- // Delete dangling dm-device. This can happen if apexd fails to delete it
- // while unmounting an apex.
- LOG(WARNING) << "Deleting existing dm device " << name;
- if (auto r = DeleteVerityDevice(name, /* deferred= */ false); !r.ok()) {
- return r.error();
- }
- }
- return CreateVerityDevice(dm, name, table, timeout);
- }
-}
-
/**
* When we create hardlink for a new apex package in kActiveApexPackagesDataDir,
* there might be an older version of the same package already present in there.
@@ -467,10 +424,8 @@
const std::string& mount_point,
const std::string& device_name,
const std::string& hashtree_file,
- bool verify_image, bool reuse_device,
+ bool verify_image,
bool temp_mount = false) {
- auto tag = "MountPackageImpl: " + apex.GetManifest().name();
- ATRACE_NAME(tag.c_str());
if (apex.IsCompressed()) {
return Error() << "Cannot directly mount compressed APEX "
<< apex.GetPath();
@@ -510,10 +465,8 @@
}
loop::LoopbackDeviceUniqueFd loopback_device;
for (size_t attempts = 1;; ++attempts) {
- Result<loop::LoopbackDeviceUniqueFd> ret =
- loop::CreateAndConfigureLoopDevice(full_path,
- apex.GetImageOffset().value(),
- apex.GetImageSize().value());
+ Result<loop::LoopbackDeviceUniqueFd> ret = loop::CreateLoopDevice(
+ full_path, apex.GetImageOffset().value(), apex.GetImageSize().value());
if (ret.ok()) {
loopback_device = std::move(*ret);
break;
@@ -537,18 +490,6 @@
return Error() << "Failed to verify Apex Verity data for " << full_path
<< ": " << verity_data.error();
}
- if (instance.IsBlockApex(apex)) {
- auto root_digest =
- instance.GetBlockApexRootDigest(apex.GetManifest().name());
- if (root_digest.has_value() &&
- root_digest.value() != verity_data->root_digest) {
- return Error() << "Failed to verify Apex Verity data for " << full_path
- << ": root digest (" << verity_data->root_digest
- << ") mismatches with the one (" << root_digest.value()
- << ") specified in config";
- }
- }
-
std::string block_device = loopback_device.name;
MountedApexData apex_data(loopback_device.name, apex.GetPath(), mount_point,
/* device_name = */ "",
@@ -559,11 +500,8 @@
// dm-verity because they are already in the dm-verity protected partition;
// system. However, note that we don't skip verification to ensure that APEXes
// are correctly signed.
- const bool mount_on_verity = !instance.IsPreInstalledApex(apex) ||
- // decompressed apexes are on /data
- instance.IsDecompressedApex(apex) ||
- // block apexes are from host
- instance.IsBlockApex(apex);
+ const bool mount_on_verity =
+ !instance.IsPreInstalledApex(apex) || instance.IsDecompressedApex(apex);
DmVerityDevice verity_dev;
loop::LoopbackDeviceUniqueFd loop_for_hash;
@@ -574,10 +512,7 @@
!st.ok()) {
return st.error();
}
- auto create_loop_status =
- loop::CreateAndConfigureLoopDevice(hashtree_file,
- /* image_offset= */ 0,
- /* image_size= */ 0);
+ auto create_loop_status = loop::CreateLoopDevice(hashtree_file, 0, 0);
if (!create_loop_status.ok()) {
return create_loop_status.error();
}
@@ -589,7 +524,7 @@
CreateVerityTable(*verity_data, loopback_device.name, hash_device,
/* restart_on_corruption = */ !verify_image);
Result<DmVerityDevice> verity_dev_res =
- CreateVerityDevice(device_name, *verity_table, reuse_device);
+ CreateVerityDevice(device_name, *verity_table);
if (!verity_dev_res.ok()) {
return Error() << "Failed to create Apex Verity device " << full_path
<< ": " << verity_dev_res.error();
@@ -668,8 +603,7 @@
}
auto ret =
MountPackageImpl(apex, mount_point, temp_device_name, hashtree_file,
- /* verify_image = */ true, /* reuse_device= */ false,
- /* temp_mount = */ true);
+ /* verify_image = */ true, /* temp_mount = */ true);
if (!ret.ok()) {
LOG(DEBUG) << "Cleaning up " << hashtree_file;
if (TEMP_FAILURE_RETRY(unlink(hashtree_file.c_str())) != 0) {
@@ -728,95 +662,6 @@
namespace {
-// TODO(b/218672709): get the ro.build.version.sdk version of the device.
-const auto kSepolicyLevel = std::to_string(__ANDROID_API_T__);
-const auto kVersionedSepolicyZip = "SEPolicy-" + kSepolicyLevel + ".zip";
-const auto kVersionedSepolicySig = "SEPolicy-" + kSepolicyLevel + ".zip.sig";
-const auto kVersionedSepolicyFsv =
- "SEPolicy-" + kSepolicyLevel + ".zip.fsv_sig";
-
-const auto kSepolicyZip = "SEPolicy.zip";
-const auto kSepolicySig = "SEPolicy.zip.sig";
-const auto kSepolicyFsv = "SEPolicy.zip.fsv_sig";
-
-Result<void> CopySepolicyToMetadata(const std::string& mount_point) {
- LOG(DEBUG) << "Copying SEPolicy files to /metadata/sepolicy/staged.";
- const auto policy_dir = mount_point + "/etc";
-
- // Find SEPolicy zip and signature files.
- std::optional<std::string> sepolicy_zip;
- std::optional<std::string> sepolicy_sig;
- std::optional<std::string> sepolicy_fsv;
- auto status =
- WalkDir(policy_dir, [&sepolicy_zip, &sepolicy_sig, &sepolicy_fsv](
- const std::filesystem::directory_entry& entry) {
- if (!entry.is_regular_file()) {
- return;
- }
- const auto& path = entry.path().string();
- if (base::EndsWith(path, kVersionedSepolicyZip)) {
- sepolicy_zip = path;
- } else if (base::EndsWith(path, kVersionedSepolicySig)) {
- sepolicy_sig = path;
- } else if (base::EndsWith(path, kVersionedSepolicyFsv)) {
- sepolicy_fsv = path;
- }
- });
- if (!status.ok()) {
- return status.error();
- }
- if (sepolicy_zip->empty() || sepolicy_sig->empty() || sepolicy_fsv->empty()) {
- return Error() << "SEPolicy files not found.";
- }
- LOG(INFO) << "SEPolicy files found.";
-
- // Set up staging directory.
- std::error_code ec;
- const auto staged_dir =
- std::string(gConfig->metadata_sepolicy_staged_dir) + "/";
- status = CreateDirIfNeeded(staged_dir, 0755);
- if (!status.ok()) {
- return status.error();
- }
-
- // Clean up after myself.
- auto scope_guard = android::base::make_scope_guard([&staged_dir]() {
- std::error_code ec;
- std::filesystem::remove_all(staged_dir, ec);
- if (ec) {
- LOG(WARNING) << "Failed to clear " << staged_dir << ": " << ec.message();
- }
- });
-
- // Copy files to staged folder.
- const auto stagedSepolicyZip = staged_dir + kSepolicyZip;
- const auto stagedSepolicyFsv = staged_dir + kSepolicyFsv;
- std::map<std::string, std::string> from_to = {
- {*sepolicy_zip, stagedSepolicyZip},
- {*sepolicy_sig, staged_dir + kSepolicySig},
- {*sepolicy_fsv, stagedSepolicyFsv}};
- for (const auto& [from, to] : from_to) {
- std::filesystem::copy_file(
- from, to, std::filesystem::copy_options::update_existing, ec);
- if (ec) {
- return Error() << "Failed to copy " << from << " to " << to << ": "
- << ec.message();
- }
- }
-
- status = enableFsVerity(stagedSepolicyZip, stagedSepolicyFsv);
- if (!status.ok()) {
- // TODO(b/218672709): once we have a release certificate available, return
- // an error and make the ApexdMountTest#CopySepolicyToMetadata test pass.
- LOG(ERROR) << status.error().message();
- } else {
- LOG(INFO) << "fs-verity enabled on " << stagedSepolicyZip;
- }
-
- scope_guard.Disable();
- return {};
-}
-
template <typename VerifyFn>
Result<void> RunVerifyFnInsideTempMount(const ApexFile& apex,
const VerifyFn& verify_fn,
@@ -855,6 +700,65 @@
return {};
}
+template <typename HookFn, typename HookCall>
+Result<void> PrePostinstallPackages(const std::vector<ApexFile>& apexes,
+ HookFn fn, HookCall call) {
+ auto scope_guard = android::base::make_scope_guard([&]() {
+ for (const ApexFile& apex_file : apexes) {
+ apexd_private::UnmountTempMount(apex_file);
+ }
+ });
+ if (apexes.empty()) {
+ return Errorf("Empty set of inputs");
+ }
+
+ // 1) Check whether the APEXes have hooks.
+ bool has_hooks = false;
+ for (const ApexFile& apex_file : apexes) {
+ if (!(apex_file.GetManifest().*fn)().empty()) {
+ has_hooks = true;
+ break;
+ }
+ }
+
+ // 2) If we found hooks, temp mount if required, and run the pre/post-install.
+ if (has_hooks) {
+ std::vector<std::string> mount_points;
+ for (const ApexFile& apex : apexes) {
+ // Retrieve the mount data if the apex is already temp mounted, temp
+ // mount it otherwise.
+ std::string mount_point =
+ apexd_private::GetPackageTempMountPoint(apex.GetManifest());
+ Result<MountedApexData> mount_data =
+ apexd_private::GetTempMountedApexData(apex.GetManifest().name());
+ if (!mount_data.ok()) {
+ mount_data = VerifyAndTempMountPackage(apex, mount_point);
+ if (!mount_data.ok()) {
+ return mount_data.error();
+ }
+ }
+ mount_points.push_back(mount_point);
+ }
+
+ Result<void> install_status = (*call)(apexes, mount_points);
+ if (!install_status.ok()) {
+ return install_status;
+ }
+ }
+
+ return {};
+}
+
+Result<void> PreinstallPackages(const std::vector<ApexFile>& apexes) {
+ return PrePostinstallPackages(apexes, &ApexManifest::preinstallhook,
+ &StagePreInstall);
+}
+
+Result<void> PostinstallPackages(const std::vector<ApexFile>& apexes) {
+ return PrePostinstallPackages(apexes, &ApexManifest::postinstallhook,
+ &StagePostInstall);
+}
+
// Converts a list of apex file paths into a list of ApexFile objects
//
// Returns error when trying to open empty set of inputs.
@@ -914,8 +818,6 @@
return {};
}
-static constexpr auto kSepolicyApexName = "com.android.sepolicy.apex";
-
// A version of apex verification that happens on SubmitStagedSession.
// This function contains checks that might be expensive to perform, e.g. temp
// mounting a package and reading entire dm-verity device, and shouldn't be run
@@ -926,13 +828,10 @@
return verify_package_boot_status;
}
- const auto validate_fn = [&apex_file](const std::string& mount_point) {
- if (apex_file.GetManifest().name() == kSepolicyApexName) {
- return CopySepolicyToMetadata(mount_point);
- }
+ constexpr const auto kSuccessFn = [](const std::string& /*mount_point*/) {
return Result<void>{};
};
- return RunVerifyFnInsideTempMount(apex_file, validate_fn, false);
+ return RunVerifyFnInsideTempMount(apex_file, kSuccessFn, false);
}
template <typename VerifyApexFn>
@@ -954,9 +853,9 @@
return std::move(*apex_files);
}
-Result<ApexFile> VerifySessionDir(int session_id) {
- std::string session_dir_path =
- StringPrintf("%s/session_%d", gConfig->staged_session_dir, session_id);
+Result<ApexFile> VerifySessionDir(const int session_id) {
+ std::string session_dir_path = std::string(kStagedSessionsDir) + "/session_" +
+ std::to_string(session_id);
LOG(INFO) << "Scanning " << session_dir_path
<< " looking for packages to be validated";
Result<std::vector<std::string>> scan =
@@ -1143,12 +1042,10 @@
void SetConfig(const ApexdConfig& config) { gConfig = config; }
Result<void> MountPackage(const ApexFile& apex, const std::string& mount_point,
- const std::string& device_name, bool reuse_device,
- bool temp_mount) {
- auto ret =
- MountPackageImpl(apex, mount_point, device_name,
- GetHashTreeFileName(apex, /* is_new= */ false),
- /* verify_image = */ false, reuse_device, temp_mount);
+ const std::string& device_name) {
+ auto ret = MountPackageImpl(apex, mount_point, device_name,
+ GetHashTreeFileName(apex, /* is_new= */ false),
+ /* verify_image = */ false);
if (!ret.ok()) {
return ret.error();
}
@@ -1337,9 +1234,7 @@
}
Result<void> ActivatePackageImpl(const ApexFile& apex_file,
- const std::string& device_name,
- bool reuse_device) {
- ATRACE_NAME("ActivatePackageImpl");
+ const std::string& device_name) {
const ApexManifest& manifest = apex_file.GetManifest();
if (!IsValidPackageName(manifest.name())) {
@@ -1398,8 +1293,7 @@
apexd_private::GetPackageMountPoint(manifest);
if (!version_found_mounted) {
- auto mount_status = MountPackage(apex_file, mount_point, device_name,
- reuse_device, /*temp_mount=*/false);
+ auto mount_status = MountPackage(apex_file, mount_point, device_name);
if (!mount_status.ok()) {
return mount_status;
}
@@ -1453,8 +1347,8 @@
if (!apex_file.ok()) {
return apex_file.error();
}
- return ActivatePackageImpl(*apex_file, GetPackageId(apex_file->GetManifest()),
- /* reuse_device= */ false);
+ return ActivatePackageImpl(*apex_file,
+ GetPackageId(apex_file->GetManifest()));
}
Result<void> DeactivatePackage(const std::string& full_path) {
@@ -1469,74 +1363,6 @@
/* deferred= */ false);
}
-Result<std::vector<ApexFile>> GetStagedApexFiles(
- int session_id, const std::vector<int>& child_session_ids) {
- auto session = ApexSession::GetSession(session_id);
- if (!session.ok()) {
- return session.error();
- }
- // We should only accept sessions in SessionState::STAGED state
- auto session_state = (*session).GetState();
- if (session_state != SessionState::STAGED) {
- return Error() << "Session " << session_id << " is not in state STAGED";
- }
-
- std::vector<int> ids_to_scan;
- if (!child_session_ids.empty()) {
- ids_to_scan = child_session_ids;
- } else {
- ids_to_scan = {session_id};
- }
-
- // Find apex files in the staging directory
- std::vector<std::string> apex_file_paths;
- for (int id_to_scan : ids_to_scan) {
- std::string session_dir_path = std::string(gConfig->staged_session_dir) +
- "/session_" + std::to_string(id_to_scan);
- Result<std::vector<std::string>> scan =
- FindFilesBySuffix(session_dir_path, {kApexPackageSuffix});
- if (!scan.ok()) {
- return scan.error();
- }
- if (scan->size() != 1) {
- return Error() << "Expected exactly one APEX file in directory "
- << session_dir_path << ". Found: " << scan->size();
- }
- std::string& apex_file_path = (*scan)[0];
- apex_file_paths.push_back(std::move(apex_file_path));
- }
-
- return OpenApexFiles(apex_file_paths);
-}
-
-Result<ClassPath> MountAndDeriveClassPath(
- const std::vector<ApexFile>& apex_files) {
- auto guard = android::base::make_scope_guard([&]() {
- for (const auto& apex : apex_files) {
- apexd_private::UnmountTempMount(apex);
- }
- });
-
- // Mount the staged apex files
- std::vector<std::string> temp_mounted_apex_paths;
- for (const auto& apex : apex_files) {
- const std::string& temp_mount_point =
- apexd_private::GetPackageTempMountPoint(apex.GetManifest());
- const std::string& package_id = GetPackageId(apex.GetManifest());
- const std::string& temp_device_name = package_id + ".tmp";
- auto mount_status =
- MountPackage(apex, temp_mount_point, temp_device_name,
- /*reuse_device=*/false, /*temp_mount=*/true);
- if (!mount_status.ok()) {
- return mount_status.error();
- }
- temp_mounted_apex_paths.push_back(temp_mount_point);
- }
-
- // Calculate classpaths of temp mounted staged apexs
- return ClassPath::DeriveClassPath(temp_mounted_apex_paths);
-}
-
std::vector<ApexFile> GetActivePackages() {
std::vector<ApexFile> ret;
gMountedApexes.ForallMountedApexes(
@@ -1686,20 +1512,6 @@
return ErrnoError() << "Cannot find matching package for: " << packageName;
}
-Result<void> DeleteStagedSepolicy() {
- const auto staged_dir =
- std::string(gConfig->metadata_sepolicy_staged_dir) + "/";
- LOG(DEBUG) << "Deleting " << staged_dir;
- std::error_code ec;
- auto removed = std::filesystem::remove_all(staged_dir, ec);
- if (removed == 0) {
- LOG(INFO) << staged_dir << " already deleted.";
- } else if (ec) {
- return Error() << "Failed to clear " << staged_dir << ": " << ec.message();
- }
- return {};
-}
-
/**
* Abort individual staged session.
*
@@ -1710,16 +1522,6 @@
if (!session.ok()) {
return Error() << "No session found with id " << session_id;
}
-
- const auto& apex_names = session->GetApexNames();
- if (std::find(std::begin(apex_names), std::end(apex_names),
- kSepolicyApexName) != std::end(apex_names)) {
- const auto result = DeleteStagedSepolicy();
- if (!result.ok()) {
- return result.error();
- }
- }
-
switch (session->GetState()) {
case SessionState::VERIFIED:
[[clang::fallthrough]];
@@ -1732,12 +1534,40 @@
namespace {
-enum ActivationMode { kBootstrapMode = 0, kBootMode, kOtaChrootMode, kVmMode };
+// TODO(b/179497746): Avoid scanning apex directly here
+// Only used in OnBootstrap. Should we remove this function?
+Result<std::vector<ApexFile>> ScanApexFiles(const char* apex_package_dir,
+ bool include_compressed = false) {
+ LOG(INFO) << "Scanning " << apex_package_dir << " looking for APEX packages.";
+ if (access(apex_package_dir, F_OK) != 0 && errno == ENOENT) {
+ LOG(INFO) << "... does not exist. Skipping";
+ return {};
+ }
+ std::vector<std::string> suffix_list = {kApexPackageSuffix};
+ if (include_compressed) {
+ suffix_list.push_back(kCompressedApexPackageSuffix);
+ }
+ Result<std::vector<std::string>> scan =
+ FindFilesBySuffix(apex_package_dir, suffix_list);
+ if (!scan.ok()) {
+ return Error() << "Failed to scan " << apex_package_dir << " : "
+ << scan.error();
+ }
+ std::vector<ApexFile> ret;
+ for (const auto& name : *scan) {
+ Result<ApexFile> apex_file = ApexFile::Open(name);
+ if (!apex_file.ok()) {
+ LOG(ERROR) << "Failed to scan " << name << " : " << apex_file.error();
+ } else {
+ ret.emplace_back(std::move(*apex_file));
+ }
+ }
+ return ret;
+}
std::vector<Result<void>> ActivateApexWorker(
- ActivationMode mode, std::queue<const ApexFile*>& apex_queue,
+ bool is_ota_chroot, std::queue<const ApexFile*>& apex_queue,
std::mutex& mutex) {
- ATRACE_NAME("ActivateApexWorker");
std::vector<Result<void>> ret;
while (true) {
@@ -1749,20 +1579,13 @@
apex_queue.pop();
}
- std::string device_name;
- if (mode == ActivationMode::kBootMode) {
- device_name = apex->GetManifest().name();
- } else {
- device_name = GetPackageId(apex->GetManifest());
- }
- if (mode == ActivationMode::kOtaChrootMode) {
+ std::string device_name = GetPackageId(apex->GetManifest());
+ if (is_ota_chroot) {
device_name += ".chroot";
}
- bool reuse_device = mode == ActivationMode::kBootMode;
- auto res = ActivatePackageImpl(*apex, device_name, reuse_device);
- if (!res.ok()) {
- ret.push_back(Error() << "Failed to activate " << apex->GetPath() << "("
- << device_name << "): " << res.error());
+ if (auto res = ActivatePackageImpl(*apex, device_name); !res.ok()) {
+ ret.push_back(Error() << "Failed to activate " << apex->GetPath() << " : "
+ << res.error());
} else {
ret.push_back({});
}
@@ -1772,8 +1595,7 @@
}
Result<void> ActivateApexPackages(const std::vector<ApexFileRef>& apexes,
- ActivationMode mode) {
- ATRACE_NAME("ActivateApexPackages");
+ bool is_ota_chroot) {
std::queue<const ApexFile*> apex_queue;
std::mutex apex_queue_mutex;
@@ -1798,7 +1620,7 @@
futures.reserve(worker_num);
for (size_t i = 0; i < worker_num; i++) {
futures.push_back(std::async(std::launch::async, ActivateApexWorker,
- std::ref(mode), std::ref(apex_queue),
+ std::ref(is_ota_chroot), std::ref(apex_queue),
std::ref(apex_queue_mutex)));
}
@@ -1831,7 +1653,7 @@
// such apexes that were coming from /data partition we will attempt to activate
// their corresponding pre-installed copies.
Result<void> ActivateMissingApexes(const std::vector<ApexFileRef>& apexes,
- ActivationMode mode) {
+ bool is_ota_chroot) {
LOG(INFO) << "Trying to activate pre-installed versions of missing apexes";
const auto& file_repository = ApexFileRepository::GetInstance();
const auto& activated_apexes = GetActivePackagesMap();
@@ -1866,22 +1688,13 @@
}
std::vector<ApexFile> decompressed_apex;
if (!compressed_apex.empty()) {
- decompressed_apex = ProcessCompressedApex(
- compressed_apex,
- /* is_ota_chroot= */ mode == ActivationMode::kOtaChrootMode);
+ decompressed_apex =
+ ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ false);
for (const ApexFile& apex_file : decompressed_apex) {
fallback_apexes.emplace_back(std::cref(apex_file));
}
}
- if (mode == kBootMode) {
- // Treat fallback to pre-installed APEXes as a change of the acitve APEX,
- // since we are already in a pretty dire situation, so it's better if we
- // drop all the caches.
- for (const auto& apex : fallback_apexes) {
- gChangedActiveApexes.insert(apex.get().GetManifest().name());
- }
- }
- return ActivateApexPackages(fallback_apexes, mode);
+ return ActivateApexPackages(fallback_apexes, is_ota_chroot);
}
} // namespace
@@ -2128,6 +1941,7 @@
void OnBootCompleted() {
ApexdLifecycle::GetInstance().MarkBootCompleted();
+ BootCompletedCleanup();
}
// Returns true if any session gets staged
@@ -2231,7 +2045,17 @@
continue;
}
- std::vector<std::string> staged_apex_names;
+ // Run postinstall, if necessary.
+ Result<void> postinstall_status = PostinstallPackages(apexes);
+ if (!postinstall_status.ok()) {
+ std::string error_message =
+ StringPrintf("Postinstall failed for session %d %s", session_id,
+ postinstall_status.error().message().c_str());
+ LOG(ERROR) << error_message;
+ session.SetErrorMessage(error_message);
+ continue;
+ }
+
for (const auto& apex : apexes) {
// TODO(b/158470836): Avoid opening ApexFile repeatedly.
Result<ApexFile> apex_file = ApexFile::Open(apex);
@@ -2239,7 +2063,7 @@
LOG(ERROR) << "Cannot open apex file during staging: " << apex;
continue;
}
- staged_apex_names.push_back(apex_file->GetManifest().name());
+ session.AddApexName(apex_file->GetManifest().name());
}
const Result<void> result = StagePackages(apexes);
@@ -2255,10 +2079,6 @@
// Session was OK, release scopeguard.
scope_guard.Disable();
- for (const std::string& apex : staged_apex_names) {
- gChangedActiveApexes.insert(apex);
- }
-
auto st = session.UpdateStateAndCommit(SessionState::ACTIVATED);
if (!st.ok()) {
LOG(ERROR) << "Failed to mark " << session
@@ -2267,6 +2087,24 @@
}
}
+Result<void> PreinstallPackages(const std::vector<std::string>& paths) {
+ Result<std::vector<ApexFile>> apex_files = OpenApexFiles(paths);
+ if (!apex_files.ok()) {
+ return apex_files.error();
+ }
+ LOG(DEBUG) << "PreinstallPackages() for " << Join(paths, ',');
+ return PreinstallPackages(*apex_files);
+}
+
+Result<void> PostinstallPackages(const std::vector<std::string>& paths) {
+ Result<std::vector<ApexFile>> apex_files = OpenApexFiles(paths);
+ if (!apex_files.ok()) {
+ return apex_files.error();
+ }
+ LOG(DEBUG) << "PostinstallPackages() for " << Join(paths, ',');
+ return PostinstallPackages(*apex_files);
+}
+
namespace {
std::string StageDestPath(const ApexFile& apex_file) {
return StringPrintf("%s/%s%s", gConfig->active_apex_data_dir,
@@ -2511,7 +2349,6 @@
}
int OnBootstrap() {
- ATRACE_NAME("OnBootstrap");
auto time_started = boot_clock::now();
Result<void> pre_allocate = PreAllocateLoopDevices();
if (!pre_allocate.ok()) {
@@ -2520,41 +2357,14 @@
}
ApexFileRepository& instance = ApexFileRepository::GetInstance();
- Result<void> status =
- instance.AddPreInstalledApex(gConfig->apex_built_in_dirs);
+ static const std::vector<std::string> kBootstrapApexDirs{
+ kApexPackageSystemDir, kApexPackageSystemExtDir, kApexPackageVendorDir};
+ Result<void> status = instance.AddPreInstalledApex(kBootstrapApexDirs);
if (!status.ok()) {
LOG(ERROR) << "Failed to collect APEX keys : " << status.error();
return 1;
}
- // TODO(b/209491448) Remove this.
- auto block_count = AddBlockApex(instance);
- if (!block_count.ok()) {
- LOG(ERROR) << status.error();
- return 1;
- }
- pre_allocate = loop::PreAllocateLoopDevices(*block_count);
- if (!pre_allocate.ok()) {
- LOG(ERROR) << "Failed to pre-allocate loop devices for block apexes : "
- << pre_allocate.error();
- }
-
- DeviceMapper& dm = DeviceMapper::Instance();
- // Create empty dm device for each found APEX.
- // This is a boot time optimization that makes use of the fact that user space
- // paths will be created by ueventd before apexd is started, and hence
- // reducing the time to activate APEXEs on /data.
- // Note: since at this point we don't know which APEXes are updated, we are
- // optimistically creating a verity device for all of them. Once boot
- // finishes, apexd will clean up unused devices.
- // TODO(b/192241176): move to apexd_verity.{h,cpp}
- for (const auto& apex : instance.GetPreInstalledApexFiles()) {
- const std::string& name = apex.get().GetManifest().name();
- if (!dm.CreateEmptyDevice(name)) {
- LOG(ERROR) << "Failed to create empty device " << name;
- }
- }
-
// Create directories for APEX shared libraries.
auto sharedlibs_apex_dir = CreateSharedLibsApexDir();
if (!sharedlibs_apex_dir.ok()) {
@@ -2563,16 +2373,26 @@
}
// Find all bootstrap apexes
- std::vector<ApexFileRef> bootstrap_apexes;
- for (const auto& apex : instance.GetPreInstalledApexFiles()) {
- if (IsBootstrapApex(apex.get())) {
- bootstrap_apexes.push_back(apex);
+ std::vector<ApexFile> bootstrap_apexes;
+ for (const auto& dir : kBootstrapApexDirs) {
+ auto scan = ScanApexFiles(dir.c_str());
+ if (!scan.ok()) {
+ LOG(ERROR) << "Failed to scan APEX files in " << dir << " : "
+ << scan.error();
+ return 1;
}
+ std::copy_if(std::make_move_iterator(scan->begin()),
+ std::make_move_iterator(scan->end()),
+ std::back_inserter(bootstrap_apexes), IsBootstrapApex);
}
// Now activate bootstrap apexes.
- auto ret =
- ActivateApexPackages(bootstrap_apexes, ActivationMode::kBootstrapMode);
+ std::vector<ApexFileRef> bootstrap_apexes_ref;
+ std::transform(bootstrap_apexes.begin(), bootstrap_apexes.end(),
+ std::back_inserter(bootstrap_apexes_ref),
+ [](const auto& x) { return std::cref(x); });
+ auto ret = ActivateApexPackages(bootstrap_apexes_ref,
+ /* is_ota_chroot= */ false);
if (!ret.ok()) {
LOG(ERROR) << "Failed to activate bootstrap apex files : " << ret.error();
return 1;
@@ -2624,13 +2444,6 @@
<< status.error();
return;
}
-
- // TODO(b/209491448) Remove this.
- if (auto block_status = AddBlockApex(instance); !block_status.ok()) {
- LOG(ERROR) << status.error();
- return;
- }
-
gMountedApexes.PopulateFromMounts(gConfig->active_apex_data_dir,
gConfig->decompression_dir,
gConfig->apex_hash_tree_dir);
@@ -2766,13 +2579,6 @@
if (!result.ok()) {
return result.error();
}
- auto ctx = GetfileconPath(apex_path);
- if (!ctx.ok()) {
- return ctx.error();
- }
- if (!StartsWith(*ctx, gConfig->active_apex_selinux_ctx)) {
- return Error() << apex_path << " has wrong SELinux context " << *ctx;
- }
return std::move(*apex);
}
@@ -2883,7 +2689,6 @@
return Error() << "Failed to decompress CAPEX: " << return_apex.error();
}
- gChangedActiveApexes.insert(return_apex->GetManifest().name());
/// Release compressed blocks in case decompression_dest is on f2fs-compressed
// filesystem.
ReleaseF2fsCompressedBlocks(decompression_dest);
@@ -2947,7 +2752,6 @@
}
void OnStart() {
- ATRACE_NAME("OnStart");
LOG(INFO) << "Marking APEXd as starting";
auto time_started = boot_clock::now();
if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusStarting)) {
@@ -2996,7 +2800,6 @@
const auto& all_apex = instance.AllApexFilesByName();
// There can be multiple APEX packages with package name X. Determine which
// one to activate.
- // TODO(b/218672709): skip activation of sepolicy APEX during boot.
auto activation_list = SelectApexForActivation(all_apex, instance);
// Process compressed APEX, if any
@@ -3032,7 +2835,7 @@
// TODO(b/179248390): activate parallelly if possible
auto activate_status =
- ActivateApexPackages(activation_list, ActivationMode::kBootMode);
+ ActivateApexPackages(activation_list, /* is_ota_chroot= */ false);
if (!activate_status.ok()) {
std::string error_message =
StringPrintf("Failed to activate packages: %s",
@@ -3043,8 +2846,8 @@
if (!revert_status.ok()) {
LOG(ERROR) << "Failed to revert : " << revert_status.error();
}
- auto retry_status =
- ActivateMissingApexes(activation_list, ActivationMode::kBootMode);
+ auto retry_status = ActivateMissingApexes(activation_list,
+ /* is_ota_chroot= */ false);
if (!retry_status.ok()) {
LOG(ERROR) << retry_status.error();
}
@@ -3119,7 +2922,7 @@
}
std::vector<ApexFile> ret;
- auto guard = android::base::make_scope_guard([&]() {
+ auto guard = android::base::make_scope_guard([&ret]() {
for (const auto& apex : ret) {
apexd_private::UnmountTempMount(apex);
}
@@ -3129,10 +2932,15 @@
if (!verified.ok()) {
return verified.error();
}
- LOG(DEBUG) << verified->GetPath() << " is verified";
ret.push_back(std::move(*verified));
}
+ // Run preinstall, if necessary.
+ Result<void> preinstall_status = PreinstallPackages(ret);
+ if (!preinstall_status.ok()) {
+ return preinstall_status.error();
+ }
+
if (has_rollback_enabled && is_rollback) {
return Error() << "Cannot set session " << session_id << " as both a"
<< " rollback and enabled for rollback.";
@@ -3148,9 +2956,6 @@
session->SetHasRollbackEnabled(has_rollback_enabled);
session->SetIsRollback(is_rollback);
session->SetRollbackId(rollback_id);
- for (const auto& apex_file : ret) {
- session->AddApexName(apex_file.GetManifest().name());
- }
Result<void> commit_status =
(*session).UpdateStateAndCommit(SessionState::VERIFIED);
if (!commit_status.ok()) {
@@ -3162,14 +2967,6 @@
ReleaseF2fsCompressedBlocks(apex.GetPath());
}
- // The scope guard above uses lambda that captures ret by reference.
- // Unfortunately, for the capture by-reference, lifetime of the captured
- // reference ends together with the lifetime of the closure object. This means
- // that we need to manually call UnmountTempMount here.
- for (const auto& apex : ret) {
- apexd_private::UnmountTempMount(apex);
- }
-
return ret;
}
@@ -3250,40 +3047,9 @@
}
}
-bool IsApexDevice(const std::string& dev_name) {
- auto& repo = ApexFileRepository::GetInstance();
- for (const auto& apex : repo.GetPreInstalledApexFiles()) {
- if (StartsWith(dev_name, apex.get().GetManifest().name())) {
- return true;
- }
- }
- return false;
-}
-
-// TODO(b/192241176): move to apexd_verity.{h,cpp}.
-void DeleteUnusedVerityDevices() {
- DeviceMapper& dm = DeviceMapper::Instance();
- std::vector<DeviceMapper::DmBlockDevice> all_devices;
- if (!dm.GetAvailableDevices(&all_devices)) {
- LOG(WARNING) << "Failed to fetch dm devices";
- return;
- }
- for (const auto& dev : all_devices) {
- auto state = dm.GetState(dev.name());
- if (state == DmDeviceState::SUSPENDED && IsApexDevice(dev.name())) {
- LOG(INFO) << "Deleting unused dm device " << dev.name();
- auto res = DeleteVerityDevice(dev.name(), /* deferred= */ false);
- if (!res.ok()) {
- LOG(WARNING) << res.error();
- }
- }
- }
-}
-
void BootCompletedCleanup() {
RemoveInactiveDataApex();
ApexSession::DeleteFinalizedSessions();
- DeleteUnusedVerityDevices();
}
int UnmountAll() {
@@ -3353,9 +3119,9 @@
}
// Given a single new APEX incoming via OTA, should we allocate space for it?
-bool ShouldAllocateSpaceForDecompression(const std::string& new_apex_name,
- const int64_t new_apex_version,
- const ApexFileRepository& instance) {
+Result<bool> ShouldAllocateSpaceForDecompression(
+ const std::string& new_apex_name, const int64_t new_apex_version,
+ const ApexFileRepository& instance) {
// An apex at most will have two versions on device: pre-installed and data.
// Check if there is a pre-installed version for the new apex.
@@ -3394,24 +3160,6 @@
return new_apex_version > data_version;
}
-int64_t CalculateSizeForCompressedApex(
- const std::vector<std::tuple<std::string, int64_t, int64_t>>&
- compressed_apexes,
- const ApexFileRepository& instance) {
- int64_t result = 0;
- for (const auto& compressed_apex : compressed_apexes) {
- std::string module_name;
- int64_t version_code;
- int64_t decompressed_size;
- std::tie(module_name, version_code, decompressed_size) = compressed_apex;
- if (ShouldAllocateSpaceForDecompression(module_name, version_code,
- instance)) {
- result += decompressed_size;
- }
- }
- return result;
-}
-
void CollectApexInfoList(std::ostream& os,
const std::vector<ApexFile>& active_apexs,
const std::vector<ApexFile>& inactive_apexs) {
@@ -3428,22 +3176,18 @@
preinstalled_module_path = *preinstalled_path;
}
- std::optional<int64_t> mtime =
- instance.GetBlockApexLastUpdateSeconds(apex.GetManifest().name());
- if (!mtime.has_value()) {
- struct stat stat_buf;
- if (stat(apex.GetPath().c_str(), &stat_buf) == 0) {
- mtime.emplace(stat_buf.st_mtime);
- } else {
- PLOG(WARNING) << "Failed to stat " << apex.GetPath();
- }
+ std::optional<int64_t> mtime;
+ struct stat stat_buf;
+ if (stat(apex.GetPath().c_str(), &stat_buf) == 0) {
+ mtime.emplace(stat_buf.st_mtime);
+ } else {
+ PLOG(WARNING) << "Failed to stat " << apex.GetPath();
}
com::android::apex::ApexInfo apex_info(
apex.GetManifest().name(), apex.GetPath(), preinstalled_module_path,
apex.GetManifest().version(), apex.GetManifest().versionname(),
- instance.IsPreInstalledApex(apex), is_active, mtime,
- apex.GetManifest().providesharedapexlibs());
- apex_infos.emplace_back(std::move(apex_info));
+ instance.IsPreInstalledApex(apex), is_active, mtime);
+ apex_infos.emplace_back(apex_info);
};
for (const auto& apex : active_apexs) {
convert_to_autogen(apex, /* is_active= */ true);
@@ -3503,73 +3247,6 @@
return {};
}
-// Adds block apexes if system property is set.
-Result<int> AddBlockApex(ApexFileRepository& instance) {
- auto prop = GetProperty(gConfig->vm_payload_metadata_partition_prop, "");
- if (prop != "") {
- auto block_count = instance.AddBlockApex(prop);
- if (!block_count.ok()) {
- return Error() << "Failed to scan block APEX files: "
- << block_count.error();
- }
- return block_count;
- } else {
- LOG(INFO) << "No block apex metadata partition found, not adding block "
- << "apexes";
- }
- return 0;
-}
-
-// When running in the VM mode, we follow the minimal start-up operations.
-// - CreateSharedLibsApexDir
-// - AddPreInstalledApex: note that CAPEXes are not supported in the VM mode
-// - AddBlockApex
-// - ActivateApexPackages
-// - setprop apexd.status: activated/ready
-int OnStartInVmMode() {
- // waits for /dev/loop-control
- loop::PreAllocateLoopDevices(0);
-
- // Create directories for APEX shared libraries.
- if (auto status = CreateSharedLibsApexDir(); !status.ok()) {
- LOG(ERROR) << "Failed to create /apex/sharedlibs : " << status.ok();
- return 1;
- }
-
- auto& instance = ApexFileRepository::GetInstance();
-
- // Scan pre-installed apexes
- if (auto status = instance.AddPreInstalledApex(gConfig->apex_built_in_dirs);
- !status.ok()) {
- LOG(ERROR) << "Failed to scan pre-installed APEX files: " << status.error();
- return 1;
- }
-
- if (auto status = AddBlockApex(instance); !status.ok()) {
- LOG(ERROR) << status.error();
- return 1;
- }
-
- if (auto status = ActivateApexPackages(instance.GetPreInstalledApexFiles(),
- ActivationMode::kVmMode);
- !status.ok()) {
- LOG(ERROR) << "Failed to activate apex packages : " << status.error();
- return 1;
- }
- if (auto status = ActivateApexPackages(instance.GetDataApexFiles(),
- ActivationMode::kVmMode);
- !status.ok()) {
- LOG(ERROR) << "Failed to activate apex packages : " << status.error();
- return 1;
- }
-
- OnAllPackagesActivated(false);
- // In VM mode, we don't run a separate --snapshotde mode.
- // Instead, we mark apexd.status "ready" right now.
- OnAllPackagesReady();
- return 0;
-}
-
int OnOtaChrootBootstrap() {
auto& instance = ApexFileRepository::GetInstance();
if (auto status = instance.AddPreInstalledApex(gConfig->apex_built_in_dirs);
@@ -3621,13 +3298,13 @@
}
}
- auto activate_status =
- ActivateApexPackages(activation_list, ActivationMode::kOtaChrootMode);
+ auto activate_status = ActivateApexPackages(activation_list,
+ /* is_ota_chroot= */ true);
if (!activate_status.ok()) {
LOG(ERROR) << "Failed to activate apex packages : "
<< activate_status.error();
- auto retry_status =
- ActivateMissingApexes(activation_list, ActivationMode::kOtaChrootMode);
+ auto retry_status = ActivateMissingApexes(activation_list,
+ /* is_ota_chroot= */ true);
if (!retry_status.ok()) {
LOG(ERROR) << retry_status.error();
}
@@ -3673,8 +3350,8 @@
return 0;
}
-int ActivateFlattenedApex() {
- LOG(INFO) << "ActivateFlattenedApex";
+int OnOtaChrootBootstrapFlattenedApex() {
+ LOG(INFO) << "OnOtaChrootBootstrapFlattenedApex";
std::vector<com::android::apex::ApexInfo> apex_infos;
@@ -3728,8 +3405,7 @@
/* versionCode= */ manifest->version(),
/* versionName= */ manifest->versionname(),
/* isFactory= */ true, /* isActive= */ true,
- /* lastUpdateMillis= */ 0,
- /* provideSharedApexLibs= */ false);
+ /* lastUpdateMillis= */ 0);
}
}
@@ -3988,9 +3664,7 @@
// previously active APEX is still around. We need to create a new one.
std::string old_new_id = GetPackageId(temp_apex->GetManifest()) + "_" +
std::to_string(*new_id_minor + 1);
- auto res = ActivatePackageImpl(*cur_apex, old_new_id,
- /* reuse_device= */ false);
- if (!res.ok()) {
+ if (auto res = ActivatePackageImpl(*cur_apex, old_new_id); !res.ok()) {
// At this point not much we can do... :(
LOG(ERROR) << res.error();
}
@@ -4010,10 +3684,8 @@
}
// 4. And activate new one.
- auto activate_status = ActivatePackageImpl(*new_apex, new_id,
- /* reuse_device= */ false);
- if (!activate_status.ok()) {
- return activate_status.error();
+ if (auto res = ActivatePackageImpl(*new_apex, new_id); !res.ok()) {
+ return res.error();
}
// Accept the install.
@@ -4037,14 +3709,5 @@
return new_apex;
}
-bool IsActiveApexChanged(const ApexFile& apex) {
- return gChangedActiveApexes.find(apex.GetManifest().name()) !=
- gChangedActiveApexes.end();
-}
-
-std::set<std::string>& GetChangedActiveApexesForTesting() {
- return gChangedActiveApexes;
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd.h b/apexd/apexd.h
index c30df4c..2465bde 100644
--- a/apexd/apexd.h
+++ b/apexd/apexd.h
@@ -17,14 +17,13 @@
#ifndef ANDROID_APEXD_APEXD_H_
#define ANDROID_APEXD_APEXD_H_
-#include <android-base/macros.h>
-#include <android-base/result.h>
-
#include <ostream>
#include <string>
#include <vector>
-#include "apex_classpath.h"
+#include <android-base/macros.h>
+#include <android-base/result.h>
+
#include "apex_constants.h"
#include "apex_database.h"
#include "apex_file.h"
@@ -48,27 +47,12 @@
const char* ota_reserved_dir;
const char* apex_hash_tree_dir;
const char* staged_session_dir;
- const char* metadata_sepolicy_staged_dir;
- // Overrides the path to the "metadata" partition which is by default
- // /dev/block/by-name/payload-metadata It should be a path pointing the first
- // partition of the VM payload disk. So, realpath() of this path is checked if
- // it has the suffix "1". For example, /test-dir/test-metadata-1 can be valid
- // and the subsequent numbers should point APEX files.
- const char* vm_payload_metadata_partition_prop;
- const char* active_apex_selinux_ctx;
};
static const ApexdConfig kDefaultConfig = {
- kApexStatusSysprop,
- kApexPackageBuiltinDirs,
- kActiveApexPackagesDataDir,
- kApexDecompressedDir,
- kOtaReservedDir,
- kApexHashTreeDir,
+ kApexStatusSysprop, kApexPackageBuiltinDirs, kActiveApexPackagesDataDir,
+ kApexDecompressedDir, kOtaReservedDir, kApexHashTreeDir,
kStagedSessionsDir,
- kMetadataSepolicyStagedDir,
- kVmPayloadMetadataPartitionProp,
- "u:object_r:staging_data_file",
};
class CheckpointInterface;
@@ -83,6 +67,8 @@
android::base::Result<void> PreinstallPackages(
const std::vector<std::string>& paths) WARN_UNUSED;
+android::base::Result<void> PostinstallPackages(
+ const std::vector<std::string>& paths) WARN_UNUSED;
android::base::Result<void> StagePackages(
const std::vector<std::string>& tmpPaths) WARN_UNUSED;
@@ -93,11 +79,6 @@
const int session_id, const std::vector<int>& child_session_ids,
const bool has_rollback_enabled, const bool is_rollback,
const int rollback_id) WARN_UNUSED;
-android::base::Result<std::vector<ApexFile>> GetStagedApexFiles(
- const int session_id,
- const std::vector<int>& child_session_ids) WARN_UNUSED;
-android::base::Result<ClassPath> MountAndDeriveClassPath(
- const std::vector<ApexFile>&) WARN_UNUSED;
android::base::Result<void> MarkStagedSessionReady(const int session_id)
WARN_UNUSED;
android::base::Result<void> MarkStagedSessionSuccessful(const int session_id)
@@ -191,13 +172,8 @@
android::base::Result<void> RemountPackages();
// Exposed for unit tests
-bool ShouldAllocateSpaceForDecompression(const std::string& new_apex_name,
- int64_t new_apex_version,
- const ApexFileRepository& instance);
-
-int64_t CalculateSizeForCompressedApex(
- const std::vector<std::tuple<std::string, int64_t, int64_t>>&
- compressed_apexes,
+android::base::Result<bool> ShouldAllocateSpaceForDecompression(
+ const std::string& new_apex_name, int64_t new_apex_version,
const ApexFileRepository& instance);
void CollectApexInfoList(std::ostream& os,
@@ -208,15 +184,12 @@
android::base::Result<void> ReserveSpaceForCompressedApex(
int64_t size, const std::string& dest_dir);
-// Entry point when running in the VM mode (with --vm arg)
-int OnStartInVmMode();
-
// Activates apexes in otapreot_chroot environment.
// TODO(b/172911822): support compressed apexes.
int OnOtaChrootBootstrap();
-// Activates flattened apexes
-int ActivateFlattenedApex();
+// Activates flattened apexes in otapreopt_chroot environment.
+int OnOtaChrootBootstrapFlattenedApex();
android::apex::MountedApexDatabase& GetApexDatabaseForTesting();
@@ -224,14 +197,6 @@
// TODO(ioffe): add more documentation.
android::base::Result<ApexFile> InstallPackage(const std::string& package_path);
-// Exposed for testing.
-android::base::Result<int> AddBlockApex(ApexFileRepository& instance);
-
-bool IsActiveApexChanged(const ApexFile& apex);
-
-// Shouldn't be used outside of apexd_test.cpp
-std::set<std::string>& GetChangedActiveApexesForTesting();
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_checkpoint_vold.h b/apexd/apexd_checkpoint_vold.h
index 3e8ce7d..f547532 100644
--- a/apexd/apexd_checkpoint_vold.h
+++ b/apexd/apexd_checkpoint_vold.h
@@ -51,7 +51,7 @@
VoldCheckpointInterface(VoldCheckpointInterface&& other) noexcept;
private:
- explicit VoldCheckpointInterface(sp<os::IVold>&& vold_service);
+ VoldCheckpointInterface(sp<os::IVold>&& vold_service);
sp<os::IVold> vold_service_;
bool supports_fs_checkpoints_;
diff --git a/apexd/apexd_lifecycle.cpp b/apexd/apexd_lifecycle.cpp
index b3fa1d0..41c1abe 100644
--- a/apexd/apexd_lifecycle.cpp
+++ b/apexd/apexd_lifecycle.cpp
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#include <chrono>
-#include <thread>
+#define LOG_TAG "apexd"
#include "apexd_lifecycle.h"
@@ -24,8 +23,6 @@
#include "apexd_utils.h"
-#define LOG_TAG "apexd"
-
using android::base::GetProperty;
using android::base::Result;
using android::base::WaitForProperty;
@@ -43,35 +40,32 @@
while (!boot_completed_) {
// Check for change in either crashing property or sys.boot_completed
// Wait for updatable_crashing property change for most of the time
- // (arbitrary 10s), briefly check if boot has completed successfully,
+ // (arbitrary 30s), briefly check if boot has completed successfully,
// if not continue waiting for updatable_crashing.
// We use this strategy so that we can quickly detect if an updatable
// process is crashing.
if (WaitForProperty("sys.init.updatable_crashing", "1",
- std::chrono::seconds(10))) {
+ std::chrono::seconds(30))) {
auto name = GetProperty("sys.init.updatable_crashing_process_name", "");
LOG(ERROR) << "Native process '" << (name.empty() ? "[unknown]" : name)
<< "' is crashing. Attempting a revert";
auto result = revert_fn(name, "");
if (!result.ok()) {
LOG(ERROR) << "Revert failed : " << result.error();
- return WaitForBootStatus();
+ break;
} else {
- // This should never be reached, since revert_fn should've rebooted
- // the device.
- LOG(FATAL) << "Active sessions were reverted, but reboot wasn't "
- "triggered.";
+ // This should never be reached, since revert_fn should've rebooted a
+ // device. But if for some reason we end up here, let's reboot it
+ // manually.
+ LOG(ERROR) << "Active sessions were reverted, but reboot wasn't "
+ "triggered. Rebooting manually";
+ Reboot();
+ return;
}
}
}
}
-void ApexdLifecycle::WaitForBootStatus() {
- while (!boot_completed_) {
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
-}
-
void ApexdLifecycle::MarkBootCompleted() { boot_completed_ = true; }
} // namespace apex
diff --git a/apexd/apexd_lifecycle.h b/apexd/apexd_lifecycle.h
index be99834..ecdef96 100644
--- a/apexd/apexd_lifecycle.h
+++ b/apexd/apexd_lifecycle.h
@@ -32,8 +32,6 @@
ApexdLifecycle& operator=(const ApexdLifecycle&) = delete;
ApexdLifecycle& operator=(ApexdLifecycle&&) = delete;
- void WaitForBootStatus();
-
public:
static ApexdLifecycle& GetInstance() {
static ApexdLifecycle instance;
diff --git a/apexd/apexd_loop.cpp b/apexd/apexd_loop.cpp
index 36521b0..08805ea 100644
--- a/apexd/apexd_loop.cpp
+++ b/apexd/apexd_loop.cpp
@@ -15,24 +15,18 @@
*/
#define LOG_TAG "apexd"
-#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
#include "apexd_loop.h"
-#include <array>
-#include <filesystem>
#include <mutex>
-#include <string_view>
#include <dirent.h>
#include <fcntl.h>
-#include <libdm/dm.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/statfs.h>
-#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
@@ -42,7 +36,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <utils/Trace.h>
#include "apexd_utils.h"
#include "string_log.h"
@@ -52,12 +45,21 @@
using android::base::Error;
using android::base::GetBoolProperty;
using android::base::ParseUint;
-using android::base::ReadFileToString;
using android::base::Result;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
-using android::dm::DeviceMapper;
+
+#ifndef LOOP_CONFIGURE
+// These can be removed whenever we pull in the Linux v5.8 UAPI headers
+struct loop_config {
+ __u32 fd;
+ __u32 block_size;
+ struct loop_info64 info;
+ __u64 __reserved[8];
+};
+#define LOOP_CONFIGURE 0x4C0A
+#endif
namespace android {
namespace apex {
@@ -84,168 +86,6 @@
}
}
-Result<void> ConfigureScheduler(const std::string& device_path) {
- if (!StartsWith(device_path, "/dev/")) {
- return Error() << "Invalid argument " << device_path;
- }
-
- const std::string device_name = Basename(device_path);
-
- const std::string sysfs_path =
- StringPrintf("/sys/block/%s/queue/scheduler", device_name.c_str());
- unique_fd sysfs_fd(open(sysfs_path.c_str(), O_RDWR | O_CLOEXEC));
- if (sysfs_fd.get() == -1) {
- return ErrnoError() << "Failed to open " << sysfs_path;
- }
-
- // Kernels before v4.1 only support 'noop'. Kernels [v4.1, v5.0) support
- // 'noop' and 'none'. Kernels v5.0 and later only support 'none'.
- static constexpr const std::array<std::string_view, 2> kNoScheduler = {
- "none", "noop"};
-
- int ret = 0;
-
- for (const std::string_view& scheduler : kNoScheduler) {
- ret = write(sysfs_fd.get(), scheduler.data(), scheduler.size());
- if (ret > 0) {
- break;
- }
- }
-
- if (ret <= 0) {
- return ErrnoError() << "Failed to write to " << sysfs_path;
- }
-
- return {};
-}
-
-// Return the parent device of a partition. Converts e.g. "sda26" into "sda".
-static Result<std::string> PartitionParent(const std::string& blockdev) {
- if (blockdev.find('/') != std::string::npos) {
- return Error() << "Invalid argument " << blockdev;
- }
- std::error_code ec;
- for (const auto& entry :
- std::filesystem::directory_iterator("/sys/class/block", ec)) {
- const std::string path = entry.path().string();
- if (std::filesystem::exists(
- StringPrintf("%s/%s", path.c_str(), blockdev.c_str()))) {
- return Basename(path);
- }
- }
- return blockdev;
-}
-
-// Convert a major:minor pair into a block device name.
-static std::string BlockdevName(dev_t dev) {
- std::error_code ec;
- for (const auto& entry :
- std::filesystem::directory_iterator("/dev/block", ec)) {
- struct stat statbuf;
- if (stat(entry.path().string().c_str(), &statbuf) < 0) {
- continue;
- }
- if (dev == statbuf.st_rdev) {
- return Basename(entry.path().string());
- }
- }
- return {};
-}
-
-// For file `file_path`, retrieve the block device backing the filesystem on
-// which the file exists and return the queue depth of the block device. The
-// loop in this function may e.g. traverse the following hierarchy:
-// /dev/block/dm-9 (system-verity; dm-verity)
-// -> /dev/block/dm-1 (system_b; dm-linear)
-// -> /dev/sda26
-static Result<uint32_t> BlockDeviceQueueDepth(const std::string& file_path) {
- struct stat statbuf;
- int res = stat(file_path.c_str(), &statbuf);
- if (res < 0) {
- return ErrnoErrorf("stat({})", file_path.c_str());
- }
- std::string blockdev = "/dev/block/" + BlockdevName(statbuf.st_dev);
- LOG(VERBOSE) << file_path << " -> " << blockdev;
- if (blockdev.empty()) {
- return Errorf("Failed to convert {}:{} (path {})", major(statbuf.st_dev),
- minor(statbuf.st_dev), file_path.c_str());
- }
- auto& dm = DeviceMapper::Instance();
- for (;;) {
- std::optional<std::string> child = dm.GetParentBlockDeviceByPath(blockdev);
- if (!child) {
- break;
- }
- LOG(VERBOSE) << blockdev << " -> " << *child;
- blockdev = *child;
- }
- std::optional<std::string> maybe_blockdev =
- android::dm::ExtractBlockDeviceName(blockdev);
- if (!maybe_blockdev) {
- return Error() << "Failed to remove /dev/block/ prefix from " << blockdev;
- }
- Result<std::string> maybe_parent = PartitionParent(*maybe_blockdev);
- if (!maybe_parent.ok()) {
- return Error() << "Failed to determine parent of " << *maybe_blockdev;
- }
- blockdev = *maybe_parent;
- LOG(VERBOSE) << "Partition parent: " << blockdev;
- const std::string nr_tags_path =
- StringPrintf("/sys/class/block/%s/mq/0/nr_tags", blockdev.c_str());
- std::string nr_tags;
- if (!ReadFileToString(nr_tags_path, &nr_tags)) {
- return Error() << "Failed to read " << nr_tags_path;
- }
- nr_tags = android::base::Trim(nr_tags);
- LOG(VERBOSE) << file_path << " is backed by /dev/" << blockdev
- << " and that block device supports queue depth " << nr_tags;
- return strtol(nr_tags.c_str(), NULL, 0);
-}
-
-// Set 'nr_requests' of `loop_device_path` equal to the queue depth of
-// the block device backing `file_path`.
-Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
- const std::string& file_path) {
- if (!StartsWith(loop_device_path, "/dev/")) {
- return Error() << "Invalid argument " << loop_device_path;
- }
-
- const std::string loop_device_name = Basename(loop_device_path);
-
- const std::string sysfs_path =
- StringPrintf("/sys/block/%s/queue/nr_requests", loop_device_name.c_str());
- std::string cur_nr_requests_str;
- if (!ReadFileToString(sysfs_path, &cur_nr_requests_str)) {
- return Error() << "Failed to read " << sysfs_path;
- }
- cur_nr_requests_str = android::base::Trim(cur_nr_requests_str);
- uint32_t cur_nr_requests = 0;
- if (!ParseUint(cur_nr_requests_str.c_str(), &cur_nr_requests)) {
- return Error() << "Failed to parse " << cur_nr_requests_str;
- }
-
- unique_fd sysfs_fd(open(sysfs_path.c_str(), O_RDWR | O_CLOEXEC));
- if (sysfs_fd.get() == -1) {
- return ErrnoErrorf("Failed to open {}", sysfs_path);
- }
-
- const auto qd = BlockDeviceQueueDepth(file_path);
- if (!qd.ok()) {
- return qd.error();
- }
- if (*qd == cur_nr_requests) {
- return {};
- }
- // Only report write failures if reducing the queue depth. Attempts to
- // increase the queue depth are rejected by the kernel if no I/O scheduler
- // is associated with the request queue.
- if (!WriteStringToFd(StringPrintf("%u", *qd), sysfs_fd) &&
- *qd < cur_nr_requests) {
- return ErrnoErrorf("Failed to write {} to {}", *qd, sysfs_path);
- }
- return {};
-}
-
Result<void> ConfigureReadAhead(const std::string& device_path) {
CHECK(StartsWith(device_path, "/dev/"));
std::string device_name = Basename(device_path);
@@ -319,7 +159,7 @@
}
Result<void> ConfigureLoopDevice(const int device_fd, const std::string& target,
- const uint32_t image_offset,
+ const int32_t image_offset,
const size_t image_size) {
static bool use_loop_configure;
static std::once_flag once_flag;
@@ -347,7 +187,6 @@
* kernel driver will automatically enable Direct I/O when it sees that
* condition is now met.
*/
- bool use_buffered_io = false;
unique_fd target_fd(open(target.c_str(), O_RDONLY | O_CLOEXEC | O_DIRECT));
if (target_fd.get() == -1) {
struct statfs stbuf;
@@ -360,7 +199,6 @@
return Error(saved_errno) << "Failed to open " << target;
}
LOG(WARNING) << "Fallback to buffered I/O for " << target;
- use_buffered_io = true;
target_fd.reset(open(target.c_str(), O_RDONLY | O_CLOEXEC));
if (target_fd.get() == -1) {
return ErrnoError() << "Failed to open " << target;
@@ -378,12 +216,10 @@
if (use_loop_configure) {
struct loop_config config;
memset(&config, 0, sizeof(config));
+ li.lo_flags |= LO_FLAGS_DIRECT_IO;
config.fd = target_fd.get();
config.info = li;
config.block_size = 4096;
- if (!use_buffered_io) {
- li.lo_flags |= LO_FLAGS_DIRECT_IO;
- }
if (ioctl(device_fd, LOOP_CONFIGURE, &config) == -1) {
return ErrnoError() << "Failed to LOOP_CONFIGURE";
@@ -442,13 +278,14 @@
// a loop device for it. To work around this we keep polling for loop device
// to be created until ueventd's cold boot sequence is done.
// See comment on kLoopDeviceRetryAttempts.
+ unique_fd sysfs_fd;
bool cold_boot_done = GetBoolProperty("ro.cold_boot_done", false);
for (size_t i = 0; i != kLoopDeviceRetryAttempts; ++i) {
if (!cold_boot_done) {
cold_boot_done = GetBoolProperty("ro.cold_boot_done", false);
}
for (const auto& device : candidate_devices) {
- unique_fd sysfs_fd(open(device.c_str(), O_RDWR | O_CLOEXEC));
+ sysfs_fd.reset(open(device.c_str(), O_RDWR | O_CLOEXEC));
if (sysfs_fd.get() != -1) {
return LoopbackDeviceUniqueFd(std::move(sysfs_fd), device);
}
@@ -465,17 +302,15 @@
}
Result<LoopbackDeviceUniqueFd> CreateLoopDevice(const std::string& target,
- uint32_t image_offset,
- size_t image_size) {
- ATRACE_NAME("CreateLoopDevice");
-
+ const int32_t image_offset,
+ const size_t image_size) {
unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
if (ctl_fd.get() == -1) {
return ErrnoError() << "Failed to open loop-control";
}
- static std::mutex mtx;
- std::lock_guard lock(mtx);
+ static std::mutex mlock;
+ std::lock_guard lock(mlock);
int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
if (num == -1) {
return ErrnoError() << "Failed LOOP_CTL_GET_FREE";
@@ -487,39 +322,10 @@
}
CHECK_NE(loop_device->device_fd.get(), -1);
- Result<void> configure_status = ConfigureLoopDevice(
+ Result<void> configureStatus = ConfigureLoopDevice(
loop_device->device_fd.get(), target, image_offset, image_size);
- if (!configure_status.ok()) {
- return configure_status.error();
- }
-
- return loop_device;
-}
-
-Result<LoopbackDeviceUniqueFd> CreateAndConfigureLoopDevice(
- const std::string& target, uint32_t image_offset, size_t image_size) {
- ATRACE_NAME("CreateAndConfigureLoopDevice");
- // Do minimal amount of work while holding a mutex. We need it because
- // acquiring + configuring a loop device is not atomic. Ideally we should
- // pre-acquire all the loop devices in advance, so that when we run APEX
- // activation in-parallel, we can do it without holding any lock.
- // Unfortunately, this will require some refactoring of how we manage loop
- // devices, and probably some new loop-control ioctls, so for the time being
- // we just limit the scope that requires locking.
- auto loop_device = CreateLoopDevice(target, image_offset, image_size);
- if (!loop_device.ok()) {
- return loop_device.error();
- }
-
- Result<void> sched_status = ConfigureScheduler(loop_device->name);
- if (!sched_status.ok()) {
- LOG(WARNING) << "Configuring I/O scheduler failed: "
- << sched_status.error();
- }
-
- Result<void> qd_status = ConfigureQueueDepth(loop_device->name, target);
- if (!qd_status.ok()) {
- LOG(WARNING) << qd_status.error();
+ if (!configureStatus.ok()) {
+ return configureStatus.error();
}
Result<void> read_ahead_status = ConfigureReadAhead(loop_device->name);
diff --git a/apexd/apexd_loop.h b/apexd/apexd_loop.h
index 3c356d9..c727944 100644
--- a/apexd/apexd_loop.h
+++ b/apexd/apexd_loop.h
@@ -55,17 +55,13 @@
int Get() { return device_fd.get(); }
};
-android::base::Result<LoopbackDeviceUniqueFd> WaitForDevice(int num);
-
-android::base::Result<void> ConfigureQueueDepth(
- const std::string& loop_device_path, const std::string& file_path);
-
android::base::Result<void> ConfigureReadAhead(const std::string& device_path);
android::base::Result<void> PreAllocateLoopDevices(size_t num);
-android::base::Result<LoopbackDeviceUniqueFd> CreateAndConfigureLoopDevice(
- const std::string& target, uint32_t image_offset, size_t image_size);
+android::base::Result<LoopbackDeviceUniqueFd> CreateLoopDevice(
+ const std::string& target, const int32_t image_offset,
+ const size_t image_size);
using DestroyLoopFn =
std::function<void(const std::string&, const std::string&)>;
diff --git a/apexd/apexd_main.cpp b/apexd/apexd_main.cpp
index fb6b488..26d5732 100644
--- a/apexd/apexd_main.cpp
+++ b/apexd/apexd_main.cpp
@@ -25,6 +25,7 @@
#include "apexd.h"
#include "apexd_checkpoint_vold.h"
#include "apexd_lifecycle.h"
+#include "apexd_prepostinstall.h"
#include "apexservice.h"
#include <android-base/properties.h>
@@ -32,6 +33,16 @@
namespace {
int HandleSubcommand(char** argv) {
+ if (strcmp("--pre-install", argv[1]) == 0) {
+ LOG(INFO) << "Preinstall subcommand detected";
+ return android::apex::RunPreInstall(argv);
+ }
+
+ if (strcmp("--post-install", argv[1]) == 0) {
+ LOG(INFO) << "Postinstall subcommand detected";
+ return android::apex::RunPostInstall(argv);
+ }
+
if (strcmp("--bootstrap", argv[1]) == 0) {
LOG(INFO) << "Bootstrap subcommand detected";
return android::apex::OnBootstrap();
@@ -71,11 +82,6 @@
return result;
}
- if (strcmp("--vm", argv[1]) == 0) {
- LOG(INFO) << "VM subcommand detected";
- return android::apex::OnStartInVmMode();
- }
-
LOG(ERROR) << "Unknown subcommand: " << argv[1];
return 1;
}
@@ -131,11 +137,7 @@
// mark apexd as ready
android::apex::OnAllPackagesReady();
} else if (strcmp("--otachroot-bootstrap", argv[1]) == 0) {
- LOG(INFO) << "OTA chroot bootstrap subcommand detected";
- return android::apex::ActivateFlattenedApex();
- } else if (strcmp("--bootstrap", argv[1]) == 0) {
- LOG(INFO) << "Bootstrap subcommand detected";
- return android::apex::ActivateFlattenedApex();
+ return android::apex::OnOtaChrootBootstrapFlattenedApex();
}
return 0;
}
@@ -183,9 +185,6 @@
lifecycle.WaitForBootStatus(android::apex::RevertActiveSessionsAndReboot);
}
- // Run cleanup routine before AllowServiceShutdown(), to prevent
- // service_manager killing apexd in the middle of the cleanup.
- android::apex::BootCompletedCleanup();
android::apex::binder::AllowServiceShutdown();
android::apex::binder::JoinThreadPool();
diff --git a/apexd/apexd_prepostinstall.cpp b/apexd/apexd_prepostinstall.cpp
new file mode 100644
index 0000000..51b60b4
--- /dev/null
+++ b/apexd/apexd_prepostinstall.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "apexd"
+
+#include "apexd_prepostinstall.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
+#include <android-base/strings.h>
+
+#include "apex_database.h"
+#include "apex_file.h"
+#include "apex_manifest.h"
+#include "apexd.h"
+#include "apexd_private.h"
+#include "apexd_utils.h"
+#include "string_log.h"
+
+using android::base::Error;
+using android::base::Result;
+using ::apex::proto::ApexManifest;
+
+namespace android {
+namespace apex {
+
+namespace {
+
+using MountedApexData = MountedApexDatabase::MountedApexData;
+
+void CloseSTDDescriptors() {
+ // exec()d process will reopen STD* file descriptors as
+ // /dev/null
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+}
+
+template <typename Fn>
+Result<void> StageFnInstall(const std::vector<ApexFile>& apexes,
+ const std::vector<std::string>& mount_points, Fn fn,
+ const char* arg, const char* name) {
+ // TODO(b/158470023): consider supporting a session with more than one
+ // pre-install hook.
+ int hook_idx = -1;
+ for (size_t i = 0; i < apexes.size(); i++) {
+ if (!(apexes[i].GetManifest().*fn)().empty()) {
+ if (hook_idx != -1) {
+ return Error() << "Missing support for multiple " << name << " hooks";
+ }
+ hook_idx = i;
+ }
+ }
+ CHECK(hook_idx != -1);
+ LOG(VERBOSE) << name << " for " << apexes[hook_idx].GetPath();
+
+ // Create invocation args.
+ std::vector<std::string> args{
+ "/system/bin/apexd", arg,
+ mount_points[hook_idx] // Make the APEX with hook first.
+ };
+ for (size_t i = 0; i < mount_points.size(); i++) {
+ if ((int)i != hook_idx) {
+ args.push_back(mount_points[i]);
+ }
+ }
+
+ return ForkAndRun(args);
+}
+
+template <typename Fn>
+int RunFnInstall(char** in_argv, Fn fn, const char* name) {
+ std::vector<std::string> activation_dirs;
+ auto preinstall_guard = android::base::make_scope_guard([&]() {
+ for (const std::string& active_point : activation_dirs) {
+ if (0 != rmdir(active_point.c_str())) {
+ PLOG(ERROR) << "Could not delete temporary active point "
+ << active_point;
+ }
+ }
+ });
+
+ // 1) Unshare.
+ if (unshare(CLONE_NEWNS) != 0) {
+ PLOG(ERROR) << "Failed to unshare() for apex " << name;
+ _exit(200);
+ }
+
+ // 2) Make everything private, so that our (and hook's) changes do not
+ // propagate.
+ if (mount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr) == -1) {
+ PLOG(ERROR) << "Failed to mount private.";
+ _exit(201);
+ }
+
+ std::string hook_path;
+ {
+ auto bind_fn = [&fn, name,
+ activation_dirs](const std::string& mount_point) mutable {
+ std::string hook;
+ std::string active_point;
+ {
+ Result<ApexManifest> manifest_or =
+ ReadManifest(mount_point + "/" + kManifestFilenamePb);
+ if (!manifest_or.ok()) {
+ LOG(ERROR) << "Could not read manifest from " << mount_point << "/"
+ << kManifestFilenamePb << " for " << name << ": "
+ << manifest_or.error();
+ // Fallback to Json manifest if present.
+ LOG(ERROR) << "Trying to find a JSON manifest";
+ manifest_or = ReadManifest(mount_point + "/" + kManifestFilenameJson);
+ if (!manifest_or.ok()) {
+ LOG(ERROR) << "Could not read manifest from " << mount_point << "/"
+ << kManifestFilenameJson << " for " << name << ": "
+ << manifest_or.error();
+ _exit(202);
+ }
+ }
+ const auto& manifest = *manifest_or;
+ hook = (manifest.*fn)();
+ active_point = apexd_private::GetActiveMountPoint(manifest);
+ // Ensure there is an activation point. If not, create one and delete
+ // later.
+ if (0 == mkdir(active_point.c_str(), kMkdirMode)) {
+ activation_dirs.push_back(active_point);
+ } else if (errno != EEXIST) {
+ PLOG(ERROR) << "Unable to create mount point " << active_point;
+ _exit(205);
+ }
+ }
+
+ // 3) Activate the new apex.
+ Result<void> bind_status =
+ apexd_private::BindMount(active_point, mount_point);
+ if (!bind_status.ok()) {
+ LOG(ERROR) << "Failed to bind-mount " << mount_point << " to "
+ << active_point << ": " << bind_status.error();
+ _exit(203);
+ }
+
+ return std::make_pair(active_point, hook);
+ };
+
+ // First/main APEX.
+ auto [active_point, hook] = bind_fn(in_argv[2]);
+ hook_path = active_point + "/" + hook;
+
+ for (size_t i = 3;; ++i) {
+ if (in_argv[i] == nullptr) {
+ break;
+ }
+ bind_fn(in_argv[i]); // Ignore result, hook will be empty.
+ }
+ }
+
+ // 4) Run the hook.
+
+ // For now, just run sh. But this probably needs to run the new linker.
+ std::vector<std::string> args{
+ hook_path,
+ };
+ std::vector<const char*> argv;
+ argv.resize(args.size() + 1, nullptr);
+ std::transform(args.begin(), args.end(), argv.begin(),
+ [](const std::string& in) { return in.c_str(); });
+
+ LOG(ERROR) << "execv of " << android::base::Join(args, " ");
+
+ // Close all file descriptors. They are coming from the caller, we do not
+ // want to pass them on across our fork/exec into a different domain.
+ CloseSTDDescriptors();
+
+ execv(argv[0], const_cast<char**>(argv.data()));
+ PLOG(ERROR) << "execv of " << android::base::Join(args, " ") << " failed";
+ _exit(204);
+}
+
+} // namespace
+
+Result<void> StagePreInstall(const std::vector<ApexFile>& apexes,
+ const std::vector<std::string>& mount_points) {
+ return StageFnInstall(apexes, mount_points, &ApexManifest::preinstallhook,
+ "--pre-install", "pre-install");
+}
+
+int RunPreInstall(char** in_argv) {
+ return RunFnInstall(in_argv, &ApexManifest::preinstallhook, "pre-install");
+}
+
+Result<void> StagePostInstall(const std::vector<ApexFile>& apexes,
+ const std::vector<std::string>& mount_points) {
+ return StageFnInstall(apexes, mount_points, &ApexManifest::postinstallhook,
+ "--post-install", "post-install");
+}
+
+int RunPostInstall(char** in_argv) {
+ return RunFnInstall(in_argv, &ApexManifest::postinstallhook, "post-install");
+}
+
+} // namespace apex
+} // namespace android
diff --git a/apexd/apexd_prepostinstall.h b/apexd/apexd_prepostinstall.h
new file mode 100644
index 0000000..65125ba
--- /dev/null
+++ b/apexd/apexd_prepostinstall.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_APEXD_APEXD_PREPOSTINSTALL_H_
+#define ANDROID_APEXD_APEXD_PREPOSTINSTALL_H_
+
+#include <string>
+#include <vector>
+
+#include <android-base/result.h>
+
+namespace android {
+namespace apex {
+
+class ApexFile;
+
+// Forks into: apexd --pre-install <mount-point-of-apex-with-hook>
+// [<other-mount-points>] The caller must pass the temp mount point for each
+// apex file.
+android::base::Result<void> StagePreInstall(
+ const std::vector<ApexFile>& apexes,
+ const std::vector<std::string>& mount_points);
+int RunPreInstall(char** argv);
+
+// Forks into: apexd --post-install <mount-point-of-apex-with-hook>
+// [<other-mount-points>] The caller must pass the temp mount point for each
+// apex file.
+android::base::Result<void> StagePostInstall(
+ const std::vector<ApexFile>& apexes,
+ const std::vector<std::string>& mount_points);
+int RunPostInstall(char** argv);
+
+} // namespace apex
+} // namespace android
+
+#endif // ANDROID_APEXD_APEXD_PREPOSTINSTALL_H_
diff --git a/apexd/apexd_rollback_utils.h b/apexd/apexd_rollback_utils.h
index b4dffd2..c7fa05e 100644
--- a/apexd/apexd_rollback_utils.h
+++ b/apexd/apexd_rollback_utils.h
@@ -41,7 +41,7 @@
kCpPath,
"-F", /* delete any existing destination file first
(--remove-destination) */
- "--preserve=mode,ownership,timestamps,xattr", /* preserve properties */
+ "-p", /* preserve timestamps, ownership, and permissions */
"-R", /* recurse into subdirectories (DEST must be a directory) */
"-P", /* Do not follow symlinks [default] */
"-d", /* don't dereference symlinks */
diff --git a/apexd/apexd_session_test.cpp b/apexd/apexd_session_test.cpp
index 7ee1eb1..50d0f85 100644
--- a/apexd/apexd_session_test.cpp
+++ b/apexd/apexd_session_test.cpp
@@ -39,7 +39,6 @@
using android::apex::testing::IsOk;
using android::base::Join;
using android::base::make_scope_guard;
-using ::apex::proto::SessionState;
// TODO(b/170329726): add unit tests for apexd_sessions.h
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
index cc6d072..a3ebd03 100644
--- a/apexd/apexd_test.cpp
+++ b/apexd/apexd_test.cpp
@@ -14,36 +14,25 @@
* limitations under the License.
*/
-#include "apexd.h"
+#include <string>
+#include <vector>
#include <android-base/file.h>
#include <android-base/properties.h>
-#include <android-base/result-gmock.h>
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <libdm/dm.h>
-#include <microdroid/metadata.h>
-#include <selinux/selinux.h>
-#include <sys/stat.h>
-
-#include <functional>
-#include <optional>
-#include <string>
-#include <tuple>
-#include <unordered_set>
-#include <vector>
#include "apex_database.h"
-#include "apex_file.h"
#include "apex_file_repository.h"
-#include "apex_manifest.pb.h"
+#include "apexd.h"
#include "apexd_checkpoint.h"
-#include "apexd_loop.h"
#include "apexd_session.h"
#include "apexd_test_utils.h"
#include "apexd_utils.h"
+
+#include "apex_manifest.pb.h"
#include "com_android_apex.h"
#include "gmock/gmock-matchers.h"
@@ -54,30 +43,19 @@
using MountedApexData = MountedApexDatabase::MountedApexData;
using android::apex::testing::ApexFileEq;
+using android::apex::testing::IsOk;
using android::base::GetExecutableDirectory;
using android::base::GetProperty;
-using android::base::Join;
using android::base::make_scope_guard;
-using android::base::ReadFileToString;
-using android::base::ReadFully;
using android::base::RemoveFileIfExists;
using android::base::Result;
-using android::base::Split;
using android::base::StringPrintf;
using android::base::unique_fd;
using android::base::WriteStringToFile;
-using android::base::testing::HasError;
-using android::base::testing::HasValue;
-using android::base::testing::Ok;
-using android::base::testing::WithMessage;
-using android::dm::DeviceMapper;
-using ::apex::proto::SessionState;
using com::android::apex::testing::ApexInfoXmlEq;
using ::testing::ByRef;
-using ::testing::Contains;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
-using ::testing::Not;
using ::testing::StartsWith;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
@@ -124,11 +102,6 @@
};
static constexpr const char* kTestApexdStatusSysprop = "apexd.status.test";
-static constexpr const char* kTestVmPayloadMetadataPartitionProp =
- "apexd.vm.payload_metadata_partition.test";
-
-static constexpr const char* kTestActiveApexSelinuxCtx =
- "u:object_r:shell_data_file:s0";
// A test fixture that provides frequently required temp directories for tests
class ApexdUnitTest : public ::testing::Test {
@@ -140,21 +113,10 @@
ota_reserved_dir_ = StringPrintf("%s/ota-reserved", td_.path);
hash_tree_dir_ = StringPrintf("%s/apex-hash-tree", td_.path);
staged_session_dir_ = StringPrintf("%s/staged-session-dir", td_.path);
- metadata_sepolicy_staged_dir_ =
- StringPrintf("%s/metadata-sepolicy-staged-dir", td_.path);
-
- vm_payload_disk_ = StringPrintf("%s/vm-payload", td_.path);
-
- config_ = {kTestApexdStatusSysprop,
- {built_in_dir_},
- data_dir_.c_str(),
- decompression_dir_.c_str(),
- ota_reserved_dir_.c_str(),
- hash_tree_dir_.c_str(),
- staged_session_dir_.c_str(),
- metadata_sepolicy_staged_dir_.c_str(),
- kTestVmPayloadMetadataPartitionProp,
- kTestActiveApexSelinuxCtx};
+ config_ = {kTestApexdStatusSysprop, {built_in_dir_},
+ data_dir_.c_str(), decompression_dir_.c_str(),
+ ota_reserved_dir_.c_str(), hash_tree_dir_.c_str(),
+ staged_session_dir_.c_str()};
}
const std::string& GetBuiltInDir() { return built_in_dir_; }
@@ -166,9 +128,6 @@
return StringPrintf("%s/session_%d", staged_session_dir_.c_str(),
session_id);
}
- const std::string& GetMetadataSepolicyStagedDir() {
- return metadata_sepolicy_staged_dir_;
- }
std::string GetRootDigest(const ApexFile& apex) {
if (apex.IsCompressed()) {
@@ -197,29 +156,6 @@
return StringPrintf("%s/%s", data_dir_.c_str(), target_name.c_str());
}
- std::string AddDecompressedApex(const std::string& apex_name) {
- auto apex_file = ApexFile::Open(GetTestFile(apex_name));
- CHECK(apex_file.ok());
- std::string target_name =
- apex_file->GetManifest().name() + "@" +
- std::to_string(apex_file->GetManifest().version()) +
- std::string(kDecompressedApexPackageSuffix);
- fs::copy(GetTestFile(apex_name), decompression_dir_ + "/" + target_name);
- return StringPrintf("%s/%s", decompression_dir_.c_str(),
- target_name.c_str());
- }
-
- std::string AddBlockApex(const std::string& apex_name,
- const std::string& public_key = "",
- const std::string& root_digest = "") {
- auto apex_path = vm_payload_disk_ + "2"; // second partition
- auto apex_file = GetTestFile(apex_name);
- WriteMetadata(apex_file, public_key, root_digest);
- // loop_devices_ will be disposed after each test
- loop_devices_.push_back(*WriteBlockApex(apex_file, apex_path));
- return apex_path;
- }
-
// Copies the compressed apex to |built_in_dir| and decompresses it to
// |decompressed_dir| and then hard links to |target_dir|
std::string PrepareCompressedApex(const std::string& name,
@@ -247,12 +183,6 @@
return result;
}
- void SetBlockApexEnabled(bool enabled) {
- // The first partition(1) is "metadata" partition
- base::SetProperty(kTestVmPayloadMetadataPartitionProp,
- enabled ? (vm_payload_disk_ + "1") : "");
- }
-
protected:
void SetUp() override {
SetConfig(config_);
@@ -263,35 +193,11 @@
ASSERT_EQ(mkdir(ota_reserved_dir_.c_str(), 0755), 0);
ASSERT_EQ(mkdir(hash_tree_dir_.c_str(), 0755), 0);
ASSERT_EQ(mkdir(staged_session_dir_.c_str(), 0755), 0);
- ASSERT_EQ(mkdir(metadata_sepolicy_staged_dir_.c_str(), 0755), 0);
DeleteDirContent(ApexSession::GetSessionsDir());
}
- void WriteMetadata(const std::string& apex_file,
- const std::string& public_key,
- const std::string& root_digest) {
- android::microdroid::Metadata metadata;
- auto apex = metadata.add_apexes();
- apex->set_name("apex");
- apex->set_public_key(public_key);
- apex->set_root_digest(root_digest);
- // In this test, block apeses are assumed as "factory".
- // ApexFileRepositoryTestAddBlockApex tests non-factory cases.
- apex->set_is_factory(true);
-
- // The first partition is metadata partition
- auto metadata_partition = vm_payload_disk_ + "1";
- LOG(INFO) << "Writing metadata to " << metadata_partition;
- std::ofstream out(metadata_partition);
-
- android::microdroid::WriteMetadata(metadata, out);
- }
-
- void TearDown() override {
- DeleteDirContent(ApexSession::GetSessionsDir());
- SetBlockApexEnabled(false);
- }
+ void TearDown() override { DeleteDirContent(ApexSession::GetSessionsDir()); }
private:
TemporaryDir td_;
@@ -300,12 +206,8 @@
std::string decompression_dir_;
std::string ota_reserved_dir_;
std::string hash_tree_dir_;
- std::string vm_payload_disk_;
- std::string vm_payload_metadata_path_;
std::string staged_session_dir_;
- std::string metadata_sepolicy_staged_dir_;
ApexdConfig config_;
- std::vector<loop::LoopbackDeviceUniqueFd> loop_devices_; // to be cleaned up
};
// Apex that does not have pre-installed version, does not get selected
@@ -316,7 +218,7 @@
"com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
auto& instance = ApexFileRepository::GetInstance();
// Pre-installed data needs to be present so that we can add data apex
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
auto apexd_test_file = ApexFile::Open(AddDataApex("apex.apexd_test.apex"));
auto shim_v1 = ApexFile::Open(AddDataApex("com.android.apex.cts.shim.apex"));
@@ -324,7 +226,7 @@
// libs apex, but if they are the same version only the data apex will be.
auto shared_lib_2 = ApexFile::Open(
AddDataApex("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
const auto all_apex = instance.AllApexFilesByName();
// Pass a blank instance so that the data apex files are not considered
@@ -346,13 +248,13 @@
ApexFile::Open(AddPreInstalledApex("apex.apexd_test_v2.apex"));
AddPreInstalledApex("com.android.apex.cts.shim.apex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
TemporaryDir data_dir;
AddDataApex("apex.apexd_test.apex");
auto shim_v2 =
ApexFile::Open(AddDataApex("com.android.apex.cts.shim.v2.apex"));
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
auto all_apex = instance.AllApexFilesByName();
auto result = SelectApexForActivation(all_apex, instance);
@@ -369,12 +271,12 @@
AddPreInstalledApex("com.android.apex.cts.shim.apex");
// Initialize pre-installed APEX information
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
auto apexd_test_file = ApexFile::Open(AddDataApex("apex.apexd_test.apex"));
auto shim_v1 = ApexFile::Open(AddDataApex("com.android.apex.cts.shim.apex"));
// Initialize ApexFile repo
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
auto all_apex = instance.AllApexFilesByName();
auto result = SelectApexForActivation(all_apex, instance);
@@ -391,12 +293,12 @@
"com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
// Initialize pre-installed APEX information
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
auto shared_lib_v2 = ApexFile::Open(
AddDataApex("com.android.apex.test.sharedlibs_generated.v2.libvY.apex"));
// Initialize data APEX information
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
auto all_apex = instance.AllApexFilesByName();
auto result = SelectApexForActivation(all_apex, instance);
@@ -413,12 +315,12 @@
"com.android.apex.test.sharedlibs_generated.v2.libvY.apex"));
// Initialize pre-installed APEX information
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
auto shared_lib_v1 = ApexFile::Open(
AddDataApex("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
// Initialize data APEX information
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
auto all_apex = instance.AllApexFilesByName();
auto result = SelectApexForActivation(all_apex, instance);
@@ -427,7 +329,7 @@
ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*shared_lib_v2))));
}
-TEST_F(ApexdUnitTest, DISABLED_ProcessCompressedApex) {
+TEST_F(ApexdUnitTest, ProcessCompressedApex) {
auto compressed_apex = ApexFile::Open(
AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
@@ -441,14 +343,16 @@
kDecompressedApexPackageSuffix);
// Assert output path is not empty
auto exists = PathExists(decompressed_file_path);
- ASSERT_THAT(exists, HasValue(true));
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists) << decompressed_file_path << " does not exist";
// Assert that decompressed apex is same as original apex
const std::string original_apex_file_path =
GetTestFile("com.android.apex.compressed.v1_original.apex");
auto comparison_result =
CompareFiles(original_apex_file_path, decompressed_file_path);
- ASSERT_THAT(comparison_result, HasValue(true));
+ ASSERT_TRUE(IsOk(comparison_result));
+ ASSERT_TRUE(*comparison_result);
// Assert that return value contains decompressed APEX
auto decompressed_apex = ApexFile::Open(decompressed_file_path);
@@ -479,35 +383,37 @@
auto result =
ValidateDecompressedApex(std::cref(*capex), std::cref(*decompressed_v1));
- ASSERT_THAT(result, Ok());
+ ASSERT_TRUE(IsOk(result));
// Validation checks version
auto decompressed_v2 = ApexFile::Open(
AddDataApex("com.android.apex.compressed.v2_original.apex"));
result =
ValidateDecompressedApex(std::cref(*capex), std::cref(*decompressed_v2));
+ ASSERT_FALSE(IsOk(result));
ASSERT_THAT(
- result,
- HasError(WithMessage(HasSubstr(
- "Compressed APEX has different version than decompressed APEX"))));
+ result.error().message(),
+ HasSubstr(
+ "Compressed APEX has different version than decompressed APEX"));
// Validation check root digest
auto decompressed_v1_different_digest = ApexFile::Open(AddDataApex(
"com.android.apex.compressed.v1_different_digest_original.apex"));
result = ValidateDecompressedApex(
std::cref(*capex), std::cref(*decompressed_v1_different_digest));
- ASSERT_THAT(result, HasError(WithMessage(HasSubstr(
- "does not match with expected root digest"))));
+ ASSERT_FALSE(IsOk(result));
+ ASSERT_THAT(result.error().message(),
+ HasSubstr("does not match with expected root digest"));
// Validation checks key
auto capex_different_key = ApexFile::Open(
AddDataApex("com.android.apex.compressed_different_key.capex"));
result = ValidateDecompressedApex(std::cref(*capex_different_key),
std::cref(*decompressed_v1));
+ ASSERT_FALSE(IsOk(result));
ASSERT_THAT(
- result,
- HasError(WithMessage(HasSubstr(
- "Public key of compressed APEX is different than original"))));
+ result.error().message(),
+ HasSubstr("Public key of compressed APEX is different than original"));
}
TEST_F(ApexdUnitTest, ProcessCompressedApexCanBeCalledMultipleTimes) {
@@ -542,7 +448,7 @@
}
// Test behavior of ProcessCompressedApex when is_ota_chroot is true
-TEST_F(ApexdUnitTest, DISABLED_ProcessCompressedApexOnOtaChroot) {
+TEST_F(ApexdUnitTest, ProcessCompressedApexOnOtaChroot) {
auto compressed_apex = ApexFile::Open(
AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
@@ -558,15 +464,16 @@
GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
// Assert output path is not empty
auto exists = PathExists(decompressed_file_path);
- ASSERT_THAT(exists, HasValue(true))
- << decompressed_file_path << " does not exist";
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists) << decompressed_file_path << " does not exist";
// Assert that decompressed apex is same as original apex
const std::string original_apex_file_path =
GetTestFile("com.android.apex.compressed.v1_original.apex");
auto comparison_result =
CompareFiles(original_apex_file_path, decompressed_file_path);
- ASSERT_THAT(comparison_result, HasValue(true));
+ ASSERT_TRUE(IsOk(comparison_result));
+ ASSERT_TRUE(*comparison_result);
// Assert that return value contains the decompressed APEX
auto apex_file = ApexFile::Open(decompressed_file_path);
@@ -603,7 +510,7 @@
ASSERT_EQ(return_value.size(), 1u);
// Ota Apex should be cleaned up
- ASSERT_THAT(PathExists(ota_apex_path), HasValue(false));
+ ASSERT_FALSE(*PathExists(ota_apex_path));
ASSERT_EQ(return_value[0].GetPath(),
StringPrintf("%s/com.android.apex.compressed@1%s",
GetDecompressionDir().c_str(),
@@ -612,12 +519,13 @@
TEST_F(ApexdUnitTest, ShouldAllocateSpaceForDecompressionNewApex) {
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
// A brand new compressed APEX is being introduced: selected
- bool result =
+ auto result =
ShouldAllocateSpaceForDecompression("com.android.brand.new", 1, instance);
- ASSERT_TRUE(result);
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_TRUE(*result);
}
TEST_F(ApexdUnitTest,
@@ -625,30 +533,33 @@
// Prepare fake pre-installed apex
AddPreInstalledApex("apex.apexd_test.apex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
// An existing pre-installed APEX is now compressed in the OTA: selected
{
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.test_package", 1, instance);
- ASSERT_TRUE(result);
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_TRUE(*result);
}
// Even if there is a data apex (lower version)
// Include data apex within calculation now
AddDataApex("apex.apexd_test_v2.apex");
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
{
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.test_package", 3, instance);
- ASSERT_TRUE(result);
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_TRUE(*result);
}
// But not if data apex has equal or higher version
{
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.test_package", 2, instance);
- ASSERT_FALSE(result);
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_FALSE(*result);
}
}
@@ -656,15 +567,16 @@
// Prepare fake pre-installed apex
PrepareCompressedApex("com.android.apex.compressed.v1.capex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
+ ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
+ ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
{
// New Compressed apex has higher version than decompressed data apex:
// selected
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.compressed", 2, instance);
- ASSERT_TRUE(result)
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_TRUE(*result)
<< "Higher version test with decompressed data returned false";
}
@@ -672,79 +584,63 @@
{
// New Compressed apex has same version as decompressed data apex: not
// selected
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.compressed", 1, instance);
- ASSERT_FALSE(result)
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_FALSE(*result)
<< "Same version test with decompressed data returned true";
}
{
// New Compressed apex has lower version than decompressed data apex:
// selected
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.compressed", 0, instance);
- ASSERT_TRUE(result)
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_TRUE(*result)
<< "lower version test with decompressed data returned false";
}
// Replace decompressed data apex with a higher version
ApexFileRepository instance_new(GetDecompressionDir());
- ASSERT_THAT(instance_new.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_TRUE(IsOk(instance_new.AddPreInstalledApex({GetBuiltInDir()})));
TemporaryDir data_dir_new;
fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
data_dir_new.path);
- ASSERT_THAT(instance_new.AddDataApex(data_dir_new.path), Ok());
+ ASSERT_TRUE(IsOk(instance_new.AddDataApex(data_dir_new.path)));
{
// New Compressed apex has higher version as data apex: selected
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.compressed", 3, instance_new);
- ASSERT_TRUE(result) << "Higher version test with new data returned false";
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_TRUE(*result) << "Higher version test with new data returned false";
}
{
// New Compressed apex has same version as data apex: not selected
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.compressed", 2, instance_new);
- ASSERT_FALSE(result) << "Same version test with new data returned true";
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_FALSE(*result) << "Same version test with new data returned true";
}
{
// New Compressed apex has lower version than data apex: not selected
- bool result = ShouldAllocateSpaceForDecompression(
+ auto result = ShouldAllocateSpaceForDecompression(
"com.android.apex.compressed", 1, instance_new);
- ASSERT_FALSE(result) << "lower version test with new data returned true";
+ ASSERT_TRUE(IsOk(result));
+ ASSERT_FALSE(*result) << "lower version test with new data returned true";
}
}
-TEST_F(ApexdUnitTest, CalculateSizeForCompressedApexEmptyList) {
- ApexFileRepository instance;
- int64_t result = CalculateSizeForCompressedApex({}, instance);
- ASSERT_EQ(0LL, result);
-}
-
-TEST_F(ApexdUnitTest, CalculateSizeForCompressedApex) {
- ApexFileRepository instance;
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- std::vector<std::tuple<std::string, int64_t, int64_t>> input = {
- std::make_tuple("new_apex", 1, 1),
- std::make_tuple("new_apex_2", 1, 2),
- std::make_tuple("com.android.apex.compressed", 1, 4), // will be ignored
- std::make_tuple("com.android.apex.compressed", 2, 8),
- };
- int64_t result = CalculateSizeForCompressedApex(input, instance);
- ASSERT_EQ(1 + 2 + 8LL, result);
-}
-
TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexCreatesSingleFile) {
TemporaryDir dest_dir;
// Reserving space should create a single file in dest_dir with exact size
- ASSERT_THAT(ReserveSpaceForCompressedApex(100, dest_dir.path), Ok());
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_THAT(files, Ok());
+ ASSERT_TRUE(IsOk(files));
ASSERT_EQ(files->size(), 1u);
EXPECT_EQ(fs::file_size((*files)[0]), 100u);
}
@@ -753,10 +649,10 @@
TemporaryDir dest_dir;
// Calling ReserveSpaceForCompressedApex multiple times should still create
// a single file
- ASSERT_THAT(ReserveSpaceForCompressedApex(100, dest_dir.path), Ok());
- ASSERT_THAT(ReserveSpaceForCompressedApex(100, dest_dir.path), Ok());
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_THAT(files, Ok());
+ ASSERT_TRUE(IsOk(files));
ASSERT_EQ(files->size(), 1u);
EXPECT_EQ(fs::file_size((*files)[0]), 100u);
}
@@ -765,19 +661,18 @@
TemporaryDir dest_dir;
// Create a 100 byte file
- ASSERT_THAT(ReserveSpaceForCompressedApex(100, dest_dir.path), Ok());
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
// Should be able to shrink and grow the reserved space
- ASSERT_THAT(ReserveSpaceForCompressedApex(1000, dest_dir.path), Ok());
-
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(1000, dest_dir.path)));
auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_THAT(files, Ok());
+ ASSERT_TRUE(IsOk(files));
ASSERT_EQ(files->size(), 1u);
EXPECT_EQ(fs::file_size((*files)[0]), 1000u);
- ASSERT_THAT(ReserveSpaceForCompressedApex(10, dest_dir.path), Ok());
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(10, dest_dir.path)));
files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_THAT(files, Ok());
+ ASSERT_TRUE(IsOk(files));
ASSERT_EQ(files->size(), 1u);
EXPECT_EQ(fs::file_size((*files)[0]), 10u);
}
@@ -786,15 +681,15 @@
TemporaryDir dest_dir;
// Create a file first
- ASSERT_THAT(ReserveSpaceForCompressedApex(100, dest_dir.path), Ok());
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_THAT(files, Ok());
+ ASSERT_TRUE(IsOk(files));
ASSERT_EQ(files->size(), 1u);
// Should delete the reserved file if size passed is 0
- ASSERT_THAT(ReserveSpaceForCompressedApex(0, dest_dir.path), Ok());
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(0, dest_dir.path)));
files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_THAT(files, Ok());
+ ASSERT_TRUE(IsOk(files));
ASSERT_EQ(files->size(), 0u);
}
@@ -807,109 +702,38 @@
// Create an ota_apex first
fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
ota_apex_path);
- ASSERT_THAT(PathExists(ota_apex_path), HasValue(true));
+ auto path_exists = PathExists(ota_apex_path);
+ ASSERT_TRUE(*path_exists);
};
create_ota_apex();
// Should not delete the reserved file if size passed is negative
- ASSERT_THAT(ReserveSpaceForCompressedApex(-1, dest_dir.path), Not(Ok()));
- ASSERT_THAT(PathExists(ota_apex_path), HasValue(true));
+ ASSERT_FALSE(IsOk(ReserveSpaceForCompressedApex(-1, dest_dir.path)));
+ auto path_exists = PathExists(ota_apex_path);
+ ASSERT_TRUE(*path_exists);
// Should delete the reserved file if size passed is 0
- ASSERT_THAT(ReserveSpaceForCompressedApex(0, dest_dir.path), Ok());
- ASSERT_THAT(PathExists(ota_apex_path), HasValue(false));
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(0, dest_dir.path)));
+ path_exists = PathExists(ota_apex_path);
+ ASSERT_FALSE(*path_exists);
create_ota_apex();
// Should delete the reserved file if size passed is positive
- ASSERT_THAT(ReserveSpaceForCompressedApex(10, dest_dir.path), Ok());
- ASSERT_THAT(PathExists(ota_apex_path), HasValue(false));
+ ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(10, dest_dir.path)));
+ path_exists = PathExists(ota_apex_path);
+ ASSERT_FALSE(*path_exists);
}
TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexErrorForNegativeValue) {
TemporaryDir dest_dir;
// Should return error if negative value is passed
- ASSERT_THAT(ReserveSpaceForCompressedApex(-1, dest_dir.path), Not(Ok()));
-}
-
-TEST_F(ApexdUnitTest, GetStagedApexFilesNoChild) {
- // Create staged session
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- // Query for its file
- auto result = GetStagedApexFiles(123, {});
-
- auto apex_file = ApexFile::Open(
- StringPrintf("%s/apex.apexd_test.apex", GetStagedDir(123).c_str()));
- ASSERT_THAT(result,
- HasValue(UnorderedElementsAre(ApexFileEq(ByRef(*apex_file)))));
-}
-
-TEST_F(ApexdUnitTest, GetStagedApexFilesOnlyStaged) {
- // Create staged session
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::VERIFIED);
-
- // Query for its file
- auto result = GetStagedApexFiles(123, {});
-
- ASSERT_THAT(
- result,
- HasError(WithMessage(HasSubstr("Session 123 is not in state STAGED"))));
-}
-
-TEST_F(ApexdUnitTest, GetStagedApexFilesChecksNumberOfApexFiles) {
- // Create staged session
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
- auto staged_dir = GetStagedDir(123);
-
- {
- // Delete the staged apex file
- DeleteDirContent(staged_dir);
-
- // Query for its file
- auto result = GetStagedApexFiles(123, {});
- ASSERT_THAT(result, HasError(WithMessage(HasSubstr(
- "Expected exactly one APEX file in directory"))));
- ASSERT_THAT(result, HasError(WithMessage(HasSubstr("Found: 0"))));
- }
- {
- // Copy multiple files to staged dir
- fs::copy(GetTestFile("apex.apexd_test.apex"), staged_dir);
- fs::copy(GetTestFile("apex.apexd_test_v2.apex"), staged_dir);
-
- // Query for its file
- auto result = GetStagedApexFiles(123, {});
- ASSERT_THAT(result, HasError(WithMessage(HasSubstr(
- "Expected exactly one APEX file in directory"))));
- ASSERT_THAT(result, HasError(WithMessage(HasSubstr("Found: 2"))));
- }
-}
-
-TEST_F(ApexdUnitTest, GetStagedApexFilesWithChildren) {
- // Create staged session
- auto parent_apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- parent_apex_session->UpdateStateAndCommit(SessionState::STAGED);
- auto child_session_1 = CreateStagedSession("apex.apexd_test.apex", 124);
- auto child_session_2 = CreateStagedSession("apex.apexd_test.apex", 125);
-
- // Query for its file
- auto result = GetStagedApexFiles(123, {124, 125});
-
- ASSERT_THAT(result, Ok());
- auto child_apex_file_1 = ApexFile::Open(
- StringPrintf("%s/apex.apexd_test.apex", GetStagedDir(124).c_str()));
- auto child_apex_file_2 = ApexFile::Open(
- StringPrintf("%s/apex.apexd_test.apex", GetStagedDir(125).c_str()));
- ASSERT_THAT(*result,
- UnorderedElementsAre(ApexFileEq(ByRef(*child_apex_file_1)),
- ApexFileEq(ByRef(*child_apex_file_2))));
+ ASSERT_FALSE(IsOk(ReserveSpaceForCompressedApex(-1, dest_dir.path)));
}
// A test fixture to use for tests that mount/unmount apexes.
class ApexdMountTest : public ApexdUnitTest {
public:
+
void UnmountOnTearDown(const std::string& apex_file) {
to_unmount_.push_back(apex_file);
}
@@ -918,8 +742,7 @@
void SetUp() final {
ApexdUnitTest::SetUp();
GetApexDatabaseForTesting().Reset();
- GetChangedActiveApexesForTesting().clear();
- ASSERT_THAT(SetUpApexTestEnvironment(), Ok());
+ ASSERT_TRUE(IsOk(SetUpApexTestEnvironment()));
}
void TearDown() final {
@@ -941,34 +764,35 @@
std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(GetTestFile("apex.apexd_test.apex"));
- ASSERT_THAT(
- ret,
- HasError(WithMessage(HasSubstr("does not support non-staged update"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(),
+ HasSubstr("does not support non-staged update"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsNoPreInstalledApex) {
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
+ ASSERT_FALSE(IsOk(ret));
ASSERT_THAT(
- ret, HasError(WithMessage(HasSubstr(
- "No active version found for package test.apex.rebootless"))));
+ ret.error().message(),
+ HasSubstr("No active version found for package test.apex.rebootless"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsNoHashtree) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret =
InstallPackage(GetTestFile("test.rebootless_apex_v2_no_hashtree.apex"));
- ASSERT_THAT(
- ret,
- HasError(WithMessage(HasSubstr(" does not have an embedded hash tree"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(),
+ HasSubstr(" does not have an embedded hash tree"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsNoActiveApex) {
@@ -976,158 +800,166 @@
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
+ ASSERT_FALSE(IsOk(ret));
ASSERT_THAT(
- ret, HasError(WithMessage(HasSubstr(
- "No active version found for package test.apex.rebootless"))));
+ ret.error().message(),
+ HasSubstr("No active version found for package test.apex.rebootless"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsManifestMismatch) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(
GetTestFile("test.rebootless_apex_manifest_mismatch.apex"));
+ ASSERT_FALSE(IsOk(ret));
ASSERT_THAT(
- ret,
- HasError(WithMessage(HasSubstr(
- "Manifest inside filesystem does not match manifest outside it"))));
+ ret.error().message(),
+ HasSubstr(
+ "Manifest inside filesystem does not match manifest outside it"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsCorrupted) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_corrupted.apex"));
- ASSERT_THAT(ret,
- HasError(WithMessage(HasSubstr("Can't verify /dev/block/dm-"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr("Can't verify /dev/block/dm-"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsProvidesSharedLibs) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(
GetTestFile("test.rebootless_apex_provides_sharedlibs.apex"));
- ASSERT_THAT(ret, HasError(WithMessage(HasSubstr(" is a shared libs APEX"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr(" is a shared libs APEX"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsProvidesNativeLibs) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(
GetTestFile("test.rebootless_apex_provides_native_libs.apex"));
- ASSERT_THAT(ret, HasError(WithMessage(HasSubstr(" provides native libs"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr(" provides native libs"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsRequiresSharedApexLibs) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(
GetTestFile("test.rebootless_apex_requires_shared_apex_libs.apex"));
- ASSERT_THAT(ret,
- HasError(WithMessage(HasSubstr(" requires shared apex libs"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr(" requires shared apex libs"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsJniLibs) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_jni_libs.apex"));
- ASSERT_THAT(ret, HasError(WithMessage(HasSubstr(" requires JNI libs"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr(" requires JNI libs"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsAddRequiredNativeLib) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret =
InstallPackage(GetTestFile("test.rebootless_apex_add_native_lib.apex"));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(),
+ HasSubstr("Set of native libs required by"));
ASSERT_THAT(
- ret, HasError(WithMessage(HasSubstr("Set of native libs required by"))));
- ASSERT_THAT(ret,
- HasError(WithMessage(HasSubstr(
- "differs from the one required by the currently active"))));
+ ret.error().message(),
+ HasSubstr("differs from the one required by the currently active"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsRemovesRequiredNativeLib) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret = InstallPackage(
GetTestFile("test.rebootless_apex_remove_native_lib.apex"));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(),
+ HasSubstr("Set of native libs required by"));
ASSERT_THAT(
- ret, HasError(WithMessage(HasSubstr("Set of native libs required by"))));
- ASSERT_THAT(ret,
- HasError(WithMessage(HasSubstr(
- "differs from the one required by the currently active"))));
+ ret.error().message(),
+ HasSubstr("differs from the one required by the currently active"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsAppInApex) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret =
InstallPackage(GetTestFile("test.rebootless_apex_app_in_apex.apex"));
- ASSERT_THAT(ret, HasError(WithMessage(HasSubstr("contains app inside"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr("contains app inside"));
}
TEST_F(ApexdMountTest, InstallPackageRejectsPrivAppInApex) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto ret =
InstallPackage(GetTestFile("test.rebootless_apex_priv_app_in_apex.apex"));
- ASSERT_THAT(ret,
- HasError(WithMessage(HasSubstr("contains priv-app inside"))));
+ ASSERT_FALSE(IsOk(ret));
+ ASSERT_THAT(ret.error().message(), HasSubstr("contains priv-app inside"));
}
TEST_F(ApexdMountTest, InstallPackagePreInstallVersionActive) {
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_THAT(ret, Ok());
+ ASSERT_TRUE(IsOk(ret));
UnmountOnTearDown(ret->GetPath());
auto apex_mounts = GetApexMounts();
@@ -1138,12 +970,12 @@
// Check that /apex/test.apex.rebootless is a bind mount of
// /apex/test.apex.rebootless@2.
auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
- ASSERT_THAT(manifest, Ok());
+ ASSERT_TRUE(IsOk(manifest));
ASSERT_EQ(2u, manifest->version());
// Check that GetActivePackage correctly reports upgraded version.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
// Check that pre-installed APEX is still around
@@ -1164,17 +996,17 @@
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
- ASSERT_THAT(ret, Ok());
+ ASSERT_TRUE(IsOk(ret));
UnmountOnTearDown(ret->GetPath());
auto apex_mounts = GetApexMounts();
@@ -1184,7 +1016,7 @@
// Check that GetActivePackage correctly reports upgraded version.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
// Check that pre-installed APEX is still around
@@ -1206,17 +1038,17 @@
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
std::string file_path = AddDataApex("test.rebootless_apex_v1.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_THAT(ret, Ok());
+ ASSERT_TRUE(IsOk(ret));
UnmountOnTearDown(ret->GetPath());
auto apex_mounts = GetApexMounts();
@@ -1227,12 +1059,12 @@
// Check that /apex/test.apex.rebootless is a bind mount of
// /apex/test.apex.rebootless@2.
auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
- ASSERT_THAT(manifest, Ok());
+ ASSERT_TRUE(IsOk(manifest));
ASSERT_EQ(2u, manifest->version());
// Check that GetActivePackage correctly reports upgraded version.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
// Check that previously active APEX was deleted.
@@ -1255,17 +1087,17 @@
std::string file_path = AddDataApex("test.rebootless_apex_v1.apex",
"test.apex.rebootless@1_1.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
- ASSERT_THAT(ret, Ok());
+ ASSERT_TRUE(IsOk(ret));
UnmountOnTearDown(ret->GetPath());
auto apex_mounts = GetApexMounts();
@@ -1276,12 +1108,12 @@
// Check that /apex/test.apex.rebootless is a bind mount of
// /apex/test.apex.rebootless@2.
auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
- ASSERT_THAT(manifest, Ok());
+ ASSERT_TRUE(IsOk(manifest));
ASSERT_EQ(1u, manifest->version());
// Check that GetActivePackage correctly reports upgraded version.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
// Check that we correctly resolved active apex path collision.
@@ -1307,17 +1139,17 @@
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
std::string file_path = AddDataApex("test.rebootless_apex_v2.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_THAT(ret, Ok());
+ ASSERT_TRUE(IsOk(ret));
UnmountOnTearDown(ret->GetPath());
auto apex_mounts = GetApexMounts();
@@ -1328,12 +1160,12 @@
// Check that /apex/test.apex.rebootless is a bind mount of
// /apex/test.apex.rebootless@2.
auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
- ASSERT_THAT(manifest, Ok());
+ ASSERT_TRUE(IsOk(manifest));
ASSERT_EQ(2u, manifest->version());
// Check that GetActivePackage correctly reports upgraded version.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
// Check that previously active APEX was deleted.
@@ -1354,12 +1186,12 @@
std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
@@ -1368,7 +1200,7 @@
ASSERT_NE(-1, fd.get());
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_THAT(ret, Not(Ok()));
+ ASSERT_FALSE(IsOk(ret));
auto apex_mounts = GetApexMounts();
ASSERT_THAT(apex_mounts,
@@ -1377,7 +1209,7 @@
// Check that GetActivePackage correctly reports upgraded version.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
// Check that old APEX is still around
@@ -1399,12 +1231,12 @@
std::string file_path = AddDataApex("test.rebootless_apex_v1.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
{
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
}
@@ -1413,7 +1245,7 @@
ASSERT_NE(-1, fd.get());
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_THAT(ret, Not(Ok()));
+ ASSERT_FALSE(IsOk(ret));
auto apex_mounts = GetApexMounts();
ASSERT_THAT(apex_mounts,
@@ -1422,7 +1254,7 @@
// Check that GetActivePackage correctly reports old apex.
auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
// Check that old APEX is still around
@@ -1445,8 +1277,8 @@
UnmountOnTearDown(apex_1);
UnmountOnTearDown(apex_2);
- ASSERT_THAT(ActivatePackage(apex_1), Ok());
- ASSERT_THAT(ActivatePackage(apex_2), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_1)));
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_2)));
// Call OnAllPackagesActivated to create /apex/apex-info-list.xml.
OnAllPackagesActivated(/* is_bootstrap= */ false);
@@ -1454,7 +1286,7 @@
ASSERT_EQ(0, access("/apex/apex-info-list.xml", F_OK));
auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_THAT(ret, Ok());
+ ASSERT_TRUE(IsOk(ret));
UnmountOnTearDown(ret->GetPath());
ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
@@ -1466,81 +1298,33 @@
/* modulePath= */ apex_1,
/* preinstalledModulePath= */ apex_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package",
/* modulePath= */ apex_2, /* preinstalledModulePath= */ apex_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_2));
auto apex_info_xml_3 = com::android::apex::ApexInfo(
/* moduleName= */ "test.apex.rebootless",
/* modulePath= */ ret->GetPath(),
/* preinstalledModulePath= */ apex_1,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(ret->GetPath()),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(ret->GetPath()));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
ApexInfoXmlEq(apex_info_xml_2),
ApexInfoXmlEq(apex_info_xml_3)));
}
-TEST_F(ApexdMountTest, ActivatePackageBannedName) {
- auto status = ActivatePackage(GetTestFile("sharedlibs.apex"));
- ASSERT_THAT(status,
- HasError(WithMessage("Package name sharedlibs is not allowed.")));
-}
-
-TEST_F(ApexdMountTest, ActivatePackageNoCode) {
- std::string file_path = AddPreInstalledApex("apex.apexd_test_nocode.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- std::string mountinfo;
- ASSERT_TRUE(ReadFileToString("/proc/self/mountinfo", &mountinfo));
- bool found_apex_mountpoint = false;
- for (const auto& line : Split(mountinfo, "\n")) {
- std::vector<std::string> tokens = Split(line, " ");
- // line format:
- // mnt_id parent_mnt_id major:minor source target option propagation_type
- // ex) 33 260:19 / /apex rw,nosuid,nodev -
- if (tokens.size() >= 7 &&
- tokens[4] == "/apex/com.android.apex.test_package@1") {
- found_apex_mountpoint = true;
- // Make sure that option contains noexec
- std::vector<std::string> options = Split(tokens[5], ",");
- EXPECT_THAT(options, Contains("noexec"));
- break;
- }
- }
- EXPECT_TRUE(found_apex_mountpoint);
-}
-
-TEST_F(ApexdMountTest, ActivatePackageManifestMissmatch) {
- std::string file_path =
- AddPreInstalledApex("apex.apexd_test_manifest_mismatch.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- auto status = ActivatePackage(file_path);
- ASSERT_THAT(
- status,
- HasError(WithMessage(HasSubstr(
- "Manifest inside filesystem does not match manifest outside it"))));
-}
-
TEST_F(ApexdMountTest, ActivatePackage) {
std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
UnmountOnTearDown(file_path);
auto active_apex = GetActivePackage("com.android.apex.test_package");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
auto apex_mounts = GetApexMounts();
@@ -1548,235 +1332,13 @@
UnorderedElementsAre("/apex/com.android.apex.test_package",
"/apex/com.android.apex.test_package@1"));
- ASSERT_THAT(DeactivatePackage(file_path), Ok());
- ASSERT_THAT(GetActivePackage("com.android.apex.test_package"), Not(Ok()));
+ ASSERT_TRUE(IsOk(DeactivatePackage(file_path)));
+ ASSERT_FALSE(IsOk(GetActivePackage("com.android.apex.test_package")));
auto new_apex_mounts = GetApexMounts();
ASSERT_EQ(new_apex_mounts.size(), 0u);
}
-TEST_F(ApexdMountTest, ActivatePackageShowsUpInMountedApexDatabase) {
- std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- auto active_apex = GetActivePackage("com.android.apex.test_package");
- ASSERT_THAT(active_apex, Ok());
- ASSERT_EQ(active_apex->GetPath(), file_path);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1"));
-
- // Check that mounted apex database contains information about our APEX.
- auto& db = GetApexDatabaseForTesting();
- std::optional<MountedApexData> mounted_apex;
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& d, bool active) {
- if (active) {
- mounted_apex.emplace(d);
- }
- });
- ASSERT_TRUE(mounted_apex)
- << "Haven't found com.android.apex.test_package in the database of "
- << "mounted apexes";
-}
-
-TEST_F(ApexdMountTest, ActivatePackageNoHashtree) {
- AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("apex.apexd_test_no_hashtree.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- // Check that hashtree was generated
- std::string hashtree_path =
- GetHashTreeDir() + "/com.android.apex.test_package@1";
- ASSERT_EQ(0, access(hashtree_path.c_str(), F_OK));
-
- // Check that block device can be read.
- auto block_device = GetBlockDeviceForApex("com.android.apex.test_package@1");
- ASSERT_THAT(block_device, Ok());
- ASSERT_THAT(ReadDevice(*block_device), Ok());
-}
-
-TEST_F(ApexdMountTest, ActivatePackageNoHashtreeShowsUpInMountedDatabase) {
- AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("apex.apexd_test_no_hashtree.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- // Get loop devices that were used to mount APEX.
- auto children = ListChildLoopDevices("com.android.apex.test_package@1");
- ASSERT_THAT(children, Ok());
- ASSERT_EQ(2u, children->size())
- << "Unexpected number of children: " << Join(*children, ",");
-
- auto& db = GetApexDatabaseForTesting();
- std::optional<MountedApexData> mounted_apex;
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& d, bool active) {
- if (active) {
- mounted_apex.emplace(d);
- }
- });
- ASSERT_TRUE(mounted_apex)
- << "Haven't found com.android.apex.test_package@1 in the database of "
- << "mounted apexes";
-
- ASSERT_EQ(file_path, mounted_apex->full_path);
- ASSERT_EQ("/apex/com.android.apex.test_package@1", mounted_apex->mount_point);
- ASSERT_EQ("com.android.apex.test_package@1", mounted_apex->device_name);
- // For loops we only check that both loop_name and hashtree_loop_name are
- // children of the top device mapper device.
- ASSERT_THAT(*children, Contains(mounted_apex->loop_name));
- ASSERT_THAT(*children, Contains(mounted_apex->hashtree_loop_name));
- ASSERT_NE(mounted_apex->loop_name, mounted_apex->hashtree_loop_name);
-}
-
-TEST_F(ApexdMountTest, DeactivePackageFreesLoopDevices) {
- AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("apex.apexd_test_no_hashtree.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- // Get loop devices that were used to mount APEX.
- auto children = ListChildLoopDevices("com.android.apex.test_package@1");
- ASSERT_THAT(children, Ok());
- ASSERT_EQ(2u, children->size())
- << "Unexpected number of children: " << Join(*children, ",");
-
- ASSERT_THAT(DeactivatePackage(file_path), Ok());
- for (const auto& loop : *children) {
- struct loop_info li;
- unique_fd fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CLOEXEC)));
- EXPECT_NE(-1, fd.get())
- << "Failed to open " << loop << " : " << strerror(errno);
- EXPECT_EQ(-1, ioctl(fd.get(), LOOP_GET_STATUS, &li))
- << loop << " is still alive";
- EXPECT_EQ(ENXIO, errno) << "Unexpected errno : " << strerror(errno);
- }
-}
-
-TEST_F(ApexdMountTest, NoHashtreeApexNewSessionDoesNotImpactActivePackage) {
- MockCheckpointInterface checkpoint_interface;
- checkpoint_interface.SetSupportsCheckpoint(true);
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("apex.apexd_test_no_hashtree.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("apex.apexd_test_no_hashtree.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- ASSERT_THAT(CreateStagedSession("apex.apexd_test_no_hashtree_2.apex", 239),
- Ok());
- auto status =
- SubmitStagedSession(239, {}, /* has_rollback_enabled= */ false,
- /* is_rollback= */ false, /* rollback_id= */ -1);
- ASSERT_THAT(status, Ok());
-
- // Check that new hashtree file was created.
- {
- std::string hashtree_path =
- GetHashTreeDir() + "/com.android.apex.test_package@1.new";
- ASSERT_THAT(PathExists(hashtree_path), HasValue(true))
- << hashtree_path << " does not exist";
- }
- // Check that active hashtree is still there.
- {
- std::string hashtree_path =
- GetHashTreeDir() + "/com.android.apex.test_package@1";
- ASSERT_THAT(PathExists(hashtree_path), HasValue(true))
- << hashtree_path << " does not exist";
- }
-
- // Check that block device of active APEX can still be read.
- auto block_device = GetBlockDeviceForApex("com.android.apex.test_package@1");
- ASSERT_THAT(block_device, Ok());
- ASSERT_THAT(ReadDevice(*block_device), Ok());
-}
-
-TEST_F(ApexdMountTest, NoHashtreeApexStagePackagesMovesHashtree) {
- MockCheckpointInterface checkpoint_interface;
- checkpoint_interface.SetSupportsCheckpoint(true);
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("apex.apexd_test_no_hashtree.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- auto read_fn = [](const std::string& path) -> std::vector<uint8_t> {
- static constexpr size_t kBufSize = 4096;
- std::vector<uint8_t> buffer(kBufSize);
- unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd.get() == -1) {
- PLOG(ERROR) << "Failed to open " << path;
- ADD_FAILURE();
- return buffer;
- }
- if (!ReadFully(fd.get(), buffer.data(), kBufSize)) {
- PLOG(ERROR) << "Failed to read " << path;
- ADD_FAILURE();
- }
- return buffer;
- };
-
- ASSERT_THAT(CreateStagedSession("apex.apexd_test_no_hashtree_2.apex", 37),
- Ok());
- auto status =
- SubmitStagedSession(37, {}, /* has_rollback_enabled= */ false,
- /* is_rollback= */ false, /* rollback_id= */ -1);
- ASSERT_THAT(status, Ok());
- auto staged_apex = std::move((*status)[0]);
-
- // Check that new hashtree file was created.
- std::vector<uint8_t> original_hashtree_data;
- {
- std::string hashtree_path =
- GetHashTreeDir() + "/com.android.apex.test_package@1.new";
- ASSERT_THAT(PathExists(hashtree_path), HasValue(true));
- original_hashtree_data = read_fn(hashtree_path);
- }
-
- ASSERT_THAT(StagePackages({staged_apex.GetPath()}), Ok());
- // Check that hashtree file was moved.
- {
- std::string hashtree_path =
- GetHashTreeDir() + "/com.android.apex.test_package@1.new";
- ASSERT_THAT(PathExists(hashtree_path), HasValue(false));
- }
- {
- std::string hashtree_path =
- GetHashTreeDir() + "/com.android.apex.test_package@1";
- ASSERT_THAT(PathExists(hashtree_path), HasValue(true));
- std::vector<uint8_t> moved_hashtree_data = read_fn(hashtree_path);
- ASSERT_EQ(moved_hashtree_data, original_hashtree_data);
- }
-}
-
-TEST_F(ApexdMountTest, DeactivePackageTearsDownVerityDevice) {
- AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("apex.apexd_test_v2.apex");
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
-
- ASSERT_THAT(DeactivatePackage(file_path), Ok());
- auto& dm = DeviceMapper::Instance();
- ASSERT_EQ(dm::DmDeviceState::INVALID,
- dm.GetState("com.android.apex.test_package@2"));
-}
-
TEST_F(ApexdMountTest, ActivateDeactivateSharedLibsApex) {
ASSERT_EQ(mkdir("/apex/sharedlibs", 0755), 0);
ASSERT_EQ(mkdir("/apex/sharedlibs/lib", 0755), 0);
@@ -1794,18 +1356,18 @@
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
UnmountOnTearDown(file_path);
- ASSERT_THAT(ActivatePackage(file_path), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
auto active_apex = GetActivePackage("com.android.apex.test.sharedlibs");
- ASSERT_THAT(active_apex, Ok());
+ ASSERT_TRUE(IsOk(active_apex));
ASSERT_EQ(active_apex->GetPath(), file_path);
auto apex_mounts = GetApexMounts();
ASSERT_THAT(apex_mounts,
UnorderedElementsAre("/apex/com.android.apex.test.sharedlibs@1"));
- ASSERT_THAT(DeactivatePackage(file_path), Ok());
- ASSERT_THAT(GetActivePackage("com.android.apex.test.sharedlibs"), Not(Ok()));
+ ASSERT_TRUE(IsOk(DeactivatePackage(file_path)));
+ ASSERT_FALSE(IsOk(GetActivePackage("com.android.apex.test.sharedlibs")));
auto new_apex_mounts = GetApexMounts();
ASSERT_EQ(new_apex_mounts.size(), 0u);
@@ -1841,8 +1403,8 @@
ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
UnmountOnTearDown(active_decompressed_apex);
UnmountOnTearDown(active_data_apex);
- ASSERT_THAT(ActivatePackage(active_decompressed_apex), Ok());
- ASSERT_THAT(ActivatePackage(active_data_apex), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(active_decompressed_apex)));
+ ASSERT_TRUE(IsOk(ActivatePackage(active_data_apex)));
// Clean up inactive apex packages
RemoveInactiveDataApex();
@@ -1879,14 +1441,12 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
ApexInfoXmlEq(apex_info_xml_2)));
@@ -1926,21 +1486,18 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
auto apex_info_xml_3 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package",
/* modulePath= */ apex_path_3,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
ApexInfoXmlEq(apex_info_xml_2),
@@ -1974,21 +1531,18 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
auto apex_info_xml_3 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package",
/* modulePath= */ apex_path_3,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
ApexInfoXmlEq(apex_info_xml_2),
@@ -2022,14 +1576,12 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -2063,14 +1615,12 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -2087,7 +1637,7 @@
{
auto apex = ApexFile::Open(apex_path_3);
- ASSERT_THAT(apex, Ok());
+ ASSERT_TRUE(IsOk(apex));
ASSERT_EQ(static_cast<uint64_t>(apex->GetManifest().version()), 2ULL);
}
@@ -2112,14 +1662,12 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -2148,8 +1696,7 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1)));
@@ -2181,22 +1728,19 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test.sharedlibs",
/* modulePath= */ apex_path_2,
/* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_2));
auto apex_info_xml_3 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package",
/* modulePath= */ apex_path_3,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -2265,29 +1809,25 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test.sharedlibs",
/* modulePath= */ apex_path_2,
/* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_2));
auto apex_info_xml_3 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package",
/* modulePath= */ apex_path_3,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
auto apex_info_xml_4 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test.sharedlibs",
/* modulePath= */ apex_path_4,
/* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_4),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_4));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -2362,8 +1902,7 @@
/* modulePath= */ decompressed_apex,
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(decompressed_apex),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(decompressed_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
auto& db = GetApexDatabaseForTesting();
@@ -2442,8 +1981,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 2, /* versionName= */ "2",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_active_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
auto& db = GetApexDatabaseForTesting();
@@ -2491,8 +2029,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_active_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
auto& db = GetApexDatabaseForTesting();
@@ -2540,8 +2077,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_ota_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_ota_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
auto& db = GetApexDatabaseForTesting();
@@ -2605,8 +2141,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_active_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
auto& db = GetApexDatabaseForTesting();
@@ -2649,8 +2184,7 @@
/* modulePath= */ apex_path,
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_uncompressed)));
}
@@ -2690,8 +2224,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_active_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
}
@@ -2722,15 +2255,13 @@
/* modulePath= */ data_apex_path,
/* preinstalledModulePath= */ system_apex_path,
/* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(data_apex_path),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(data_apex_path));
auto apex_info_xml_system = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.compressed",
/* modulePath= */ system_apex_path,
/* preinstalledModulePath= */ system_apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(system_apex_path),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(system_apex_path));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_data),
ApexInfoXmlEq(apex_info_xml_system)));
@@ -2774,8 +2305,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 2, /* versionName= */ "2",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_active_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml)));
auto& db = GetApexDatabaseForTesting();
@@ -2816,15 +2346,13 @@
/* modulePath= */ data_apex_path,
/* preinstalledModulePath= */ system_apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ false, /* isActive= */ true, GetMTime(data_apex_path),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ false, /* isActive= */ true, GetMTime(data_apex_path));
auto apex_info_xml_system = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.compressed",
/* modulePath= */ system_apex_path,
/* preinstalledModulePath= */ system_apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(system_apex_path),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(system_apex_path));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_data),
ApexInfoXmlEq(apex_info_xml_system)));
@@ -2868,8 +2396,7 @@
/* preinstalledModulePath= */ apex_path,
/* versionCode= */ 1, /* versionName= */ "1",
/* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex),
- /* provideSharedApexLibs= */ false);
+ GetMTime(decompressed_active_apex));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
auto& db = GetApexDatabaseForTesting();
@@ -2970,14 +2497,12 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 137, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -3012,21 +2537,19 @@
/* modulePath= */ apex_path_1,
/* preinstalledModulePath= */ apex_path_1,
/* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1),
- /* provideSharedApexLibs= */ false);
+ /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
/* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
- /* isActive= */ true, GetMTime(apex_path_2),
- /* provideSharedApexLibs= */ false);
+ /* isActive= */ true, GetMTime(apex_path_2));
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
ApexInfoXmlEq(apex_info_xml_2)));
}
-TEST_F(ApexdMountTest, ActivateFlattenedApex) {
+TEST_F(ApexdMountTest, OnOtaChrootBootstrapFlattenedApex) {
std::string apex_dir_1 = GetBuiltInDir() + "/com.android.apex.test_package";
std::string apex_dir_2 = GetBuiltInDir() + "/com.android.apex.test_package_2";
@@ -3050,7 +2573,7 @@
write_manifest_fn(apex_dir_1, "com.android.apex.test_package", 2);
write_manifest_fn(apex_dir_2, "com.android.apex.test_package_2", 1);
- ASSERT_EQ(ActivateFlattenedApex(), 0);
+ ASSERT_EQ(OnOtaChrootBootstrapFlattenedApex(), 0);
auto apex_mounts = GetApexMounts();
ASSERT_THAT(apex_mounts,
@@ -3070,16 +2593,14 @@
/* preinstalledModulePath= */ apex_dir_1,
/* versionCode= */ 2, /* versionName= */ "2",
/* isFactory= */ true, /* isActive= */ true,
- /* lastUpdateMillis= */ 0,
- /* provideSharedApexLibs= */ false);
+ /* lastUpdateMillis= */ 0);
auto apex_info_xml_2 = com::android::apex::ApexInfo(
/* moduleName= */ "com.android.apex.test_package_2",
/* modulePath= */ apex_dir_2,
/* preinstalledModulePath= */ apex_dir_2,
/* versionCode= */ 1, /* versionName= */ "1",
/* isFactory= */ true, /* isActive= */ true,
- /* lastUpdateMillis= */ 0,
- /* provideSharedApexLibs= */ false);
+ /* lastUpdateMillis= */ 0);
ASSERT_THAT(info_list->getApexInfo(),
UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
@@ -3095,9 +2616,8 @@
std::string apex_path_2 =
AddPreInstalledApex("apex.apexd_test_different_app.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3123,9 +2643,8 @@
AddPreInstalledApex("apex.apexd_test_different_app.apex");
std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3149,9 +2668,8 @@
std::string apex_path = AddPreInstalledApex("com.android.apex.cts.shim.apex");
AddDataApex("com.android.apex.cts.shim.v2_wrong_sha.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
UnmountOnTearDown(apex_path);
OnStart();
@@ -3173,9 +2691,8 @@
AddPreInstalledApex("apex.apexd_test_different_app.apex");
std::string apex_path_3 = AddDataApex("apex.apexd_test.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3209,9 +2726,8 @@
AddPreInstalledApex("apex.apexd_test_different_app.apex");
AddDataApex("apex.apexd_test.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3245,9 +2761,8 @@
AddPreInstalledApex("apex.apexd_test_different_app.apex");
AddDataApex("apex.apexd_test_manifest_mismatch.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3284,13 +2799,12 @@
{
auto apex = ApexFile::Open(apex_path_3);
- ASSERT_THAT(apex, Ok());
+ ASSERT_TRUE(IsOk(apex));
ASSERT_EQ(static_cast<uint64_t>(apex->GetManifest().version()), 2ULL);
}
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3322,9 +2836,8 @@
std::string apex_path_1 =
AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3346,7 +2859,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, decompressed_active_apex);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@1");
});
}
@@ -3359,9 +2872,8 @@
std::string apex_path_2 =
AddDataApex("com.android.apex.compressed.v2_original.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3379,7 +2891,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, apex_path_2);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@2");
});
}
@@ -3392,9 +2904,8 @@
std::string apex_path_2 =
AddDataApex("com.android.apex.compressed.v1_original.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3414,7 +2925,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, apex_path_2);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@1");
});
}
@@ -3427,9 +2938,8 @@
AddPreInstalledApex("com.android.apex.compressed.v2.capex");
AddDataApex("com.android.apex.compressed.v1_original.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3452,7 +2962,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, decompressed_active_apex);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@2");
});
}
@@ -3464,9 +2974,8 @@
AddPreInstalledApex("com.android.apex.compressed.v1.capex");
AddDataApex("com.android.apex.compressed.v2_manifest_mismatch.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3489,7 +2998,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, decompressed_active_apex);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@1");
});
}
@@ -3503,9 +3012,8 @@
PrepareCompressedApex("com.android.apex.compressed.v1.capex");
AddDataApex("com.android.apex.compressed.v2_manifest_mismatch.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3527,7 +3035,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, decompressed_active_apex);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@1");
});
}
@@ -3544,9 +3052,8 @@
fs::copy(GetTestFile("com.android.apex.compressed.v2_manifest_mismatch.apex"),
GetDataDir() + "/com.android.apex.compressed@2.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3568,7 +3075,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, decompressed_active_apex);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@2");
});
}
@@ -3583,9 +3090,8 @@
auto apex_path =
AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3624,9 +3130,8 @@
auto apex_path =
AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3654,9 +3159,8 @@
previous_built_in_dir.path);
auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3679,7 +3183,7 @@
ASSERT_TRUE(latest);
ASSERT_EQ(data.full_path, decompressed_active_apex);
ASSERT_EQ(data.device_name,
- "com.android.apex.compressed");
+ "com.android.apex.compressed@1");
});
}
@@ -3697,9 +3201,8 @@
fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
ota_apex_path.c_str());
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
// When we call OnStart for the first time, it will decompress v1 capex and
// activate it, while after second call it will decompress v2 capex and
@@ -3725,9 +3228,8 @@
RemoveFileIfExists(old_capex);
AddPreInstalledApex("com.android.apex.compressed.v2.capex");
ApexFileRepository::GetInstance().Reset(GetDecompressionDir());
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
path_exists = PathExists(ota_apex_path);
ASSERT_FALSE(*path_exists);
@@ -3757,9 +3259,8 @@
pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
different_digest);
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3788,9 +3289,8 @@
// Place a same version capex in current built_in_dir, which has different key
auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
+ ASSERT_RESULT_OK(
+ ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
OnStart();
@@ -3831,11 +3331,11 @@
StringPrintf("%s/apex.apexd_test_different_app.apex", td.path);
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
- ASSERT_THAT(ActivatePackage(apex_path), Ok());
- ASSERT_THAT(ActivatePackage(decompressed_apex), Ok());
- ASSERT_THAT(ActivatePackage(other_apex), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_path)));
+ ASSERT_TRUE(IsOk(ActivatePackage(decompressed_apex)));
+ ASSERT_TRUE(IsOk(ActivatePackage(other_apex)));
auto& db = GetApexDatabaseForTesting();
// Remember mount information for |other_apex|, since it won't be available in
@@ -3905,11 +3405,11 @@
GetDecompressionDir().c_str());
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
- ASSERT_THAT(ActivatePackage(apex_path_2), Ok());
- ASSERT_THAT(ActivatePackage(apex_path_3), Ok());
- ASSERT_THAT(ActivatePackage(decompressed_apex), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_path_2)));
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_path_3)));
+ ASSERT_TRUE(IsOk(ActivatePackage(decompressed_apex)));
UnmountOnTearDown(apex_path_2);
UnmountOnTearDown(apex_path_3);
UnmountOnTearDown(decompressed_apex);
@@ -3951,10 +3451,10 @@
AddDataApex("com.android.apex.test.sharedlibs_generated.v2.libvY.apex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
- ASSERT_THAT(ActivatePackage(apex_path_1), Ok());
- ASSERT_THAT(ActivatePackage(apex_path_2), Ok());
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_path_1)));
+ ASSERT_TRUE(IsOk(ActivatePackage(apex_path_2)));
UnmountOnTearDown(apex_path_1);
UnmountOnTearDown(apex_path_2);
@@ -3973,368 +3473,6 @@
ASSERT_EQ(new_apex_mounts.size(), 0u);
}
-TEST_F(ApexdMountTest, OnStartInVmModeActivatesPreInstalled) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- auto path1 = AddPreInstalledApex("apex.apexd_test.apex");
- auto path2 = AddPreInstalledApex("apex.apexd_test_different_app.apex");
- // In VM mode, we don't scan /data/apex
- AddDataApex("apex.apexd_test_v2.apex");
-
- ASSERT_EQ(0, OnStartInVmMode());
- UnmountOnTearDown(path1);
- UnmountOnTearDown(path2);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1",
- // Emits apex-info-list as well
- "/apex/apex-info-list.xml"));
-
- ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "ready");
-}
-
-TEST_F(ApexdMountTest, OnStartInVmModeFailsWithCapex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-
- ASSERT_EQ(1, OnStartInVmMode());
-}
-
-TEST_F(ApexdMountTest, OnStartInVmModeActivatesBlockDevicesAsWell) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto path1 = AddBlockApex("apex.apexd_test.apex");
-
- ASSERT_EQ(0, OnStartInVmMode());
- UnmountOnTearDown(path1);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1",
- // Emits apex-info-list as well
- "/apex/apex-info-list.xml"));
-
- ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
- auto info_list =
- com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
- ASSERT_TRUE(info_list.has_value());
- auto apex_info_xml_1 = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.test_package",
- /* modulePath= */ path1,
- /* preinstalledModulePath= */ path1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(path1),
- /* provideSharedApexLibs= */ false);
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1)));
-}
-
-TEST_F(ApexdMountTest, OnStartInVmModeFailsWithDuplicateNames) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- AddPreInstalledApex("apex.apexd_test.apex");
- AddBlockApex("apex.apexd_test_v2.apex");
-
- ASSERT_EQ(1, OnStartInVmMode());
-}
-
-TEST_F(ApexdMountTest, OnStartInVmModeFailsWithWrongPubkey) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- AddBlockApex("apex.apexd_test.apex", /*public_key=*/"wrong pubkey");
-
- ASSERT_EQ(1, OnStartInVmMode());
-}
-
-TEST_F(ApexdMountTest, GetActivePackagesReturningBlockApexesAsWell) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto path1 = AddBlockApex("apex.apexd_test.apex");
-
- ASSERT_EQ(0, OnStartInVmMode());
- UnmountOnTearDown(path1);
-
- auto active_apexes = GetActivePackages();
- ASSERT_EQ(1u, active_apexes.size());
- ASSERT_EQ(path1, active_apexes[0].GetPath());
-}
-
-TEST_F(ApexdMountTest, OnStartInVmModeFailsWithWrongRootDigest) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- AddBlockApex("apex.apexd_test.apex", /*public_key=*/"",
- /*root_digest=*/"wrong root digest");
-
- ASSERT_EQ(1, OnStartInVmMode());
-}
-
-// Test that OnStart works with only block devices
-TEST_F(ApexdMountTest, OnStartOnlyBlockDevices) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto path1 = AddBlockApex("apex.apexd_test.apex");
-
- ASSERT_THAT(android::apex::AddBlockApex(ApexFileRepository::GetInstance()),
- Ok());
-
- OnStart();
- UnmountOnTearDown(path1);
-
- ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
- auto apex_mounts = GetApexMounts();
-
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1"));
-}
-
-// Test that we can have a mix of both block and system apexes
-TEST_F(ApexdMountTest, OnStartBlockAndSystemInstalled) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto path1 = AddPreInstalledApex("apex.apexd_test.apex");
- auto path2 = AddBlockApex("apex.apexd_test_different_app.apex");
-
- auto& instance = ApexFileRepository::GetInstance();
-
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
- ASSERT_THAT(android::apex::AddBlockApex(instance), Ok());
-
- OnStart();
- UnmountOnTearDown(path1);
- UnmountOnTearDown(path2);
-
- ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
- auto apex_mounts = GetApexMounts();
-
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-}
-
-TEST_F(ApexdMountTest, OnStartBlockAndCompressedInstalled) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto path1 = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- auto path2 = AddBlockApex("apex.apexd_test.apex");
-
- auto& instance = ApexFileRepository::GetInstance();
-
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
- ASSERT_THAT(android::apex::AddBlockApex(instance), Ok());
-
- OnStart();
- UnmountOnTearDown(path1);
- UnmountOnTearDown(path2);
-
- // Decompressed APEX should be mounted
- std::string decompressed_active_apex = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1",
- "/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1"));
-}
-
-// Test that data version of apex is used if newer
-TEST_F(ApexdMountTest, BlockAndNewerData) {
- // MockCheckpointInterface checkpoint_interface;
- //// Need to call InitializeVold before calling OnStart
- // InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto& instance = ApexFileRepository::GetInstance();
- AddBlockApex("apex.apexd_test.apex");
- ASSERT_THAT(android::apex::AddBlockApex(instance), Ok());
-
- TemporaryDir data_dir;
- auto apexd_test_file_v2 =
- ApexFile::Open(AddDataApex("apex.apexd_test_v2.apex"));
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
-
- auto all_apex = instance.AllApexFilesByName();
- auto result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 1u);
-
- ASSERT_THAT(result,
- UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file_v2))));
-}
-
-// Test that data version of apex not is used if older
-TEST_F(ApexdMountTest, BlockApexAndOlderData) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto& instance = ApexFileRepository::GetInstance();
- auto apexd_test_file_v2 =
- ApexFile::Open(AddBlockApex("apex.apexd_test_v2.apex"));
- ASSERT_THAT(android::apex::AddBlockApex(instance), Ok());
-
- TemporaryDir data_dir;
- AddDataApex("apex.apexd_test.apex");
- ASSERT_THAT(instance.AddDataApex(GetDataDir()), Ok());
-
- auto all_apex = instance.AllApexFilesByName();
- auto result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 1u);
-
- ASSERT_THAT(result,
- UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file_v2))));
-}
-
-// Test that AddBlockApex does nothing if system property not set.
-TEST_F(ApexdMountTest, AddBlockApexWithoutSystemProp) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- auto& instance = ApexFileRepository::GetInstance();
- AddBlockApex("apex.apexd_test.apex");
- ASSERT_THAT(android::apex::AddBlockApex(instance), Ok());
- ASSERT_EQ(instance.AllApexFilesByName().size(), 0ul);
-}
-
-// Test that adding block apex fails if preinstalled version exists
-TEST_F(ApexdMountTest, AddBlockApexFailsWithDuplicate) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- AddPreInstalledApex("apex.apexd_test.apex");
- AddBlockApex("apex.apexd_test_v2.apex");
-
- auto& instance = ApexFileRepository::GetInstance();
-
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
- ASSERT_THAT(android::apex::AddBlockApex(instance),
- HasError(WithMessage(HasSubstr(
- "duplicate of com.android.apex.test_package found"))));
-}
-
-// Test that adding block apex fails if preinstalled compressed version exists
-TEST_F(ApexdMountTest, AddBlockApexFailsWithCompressedDuplicate) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Set system property to enable block apexes
- SetBlockApexEnabled(true);
-
- auto path1 = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- auto path2 = AddBlockApex("com.android.apex.compressed.v1_original.apex");
-
- auto& instance = ApexFileRepository::GetInstance();
-
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
- ASSERT_THAT(android::apex::AddBlockApex(instance),
- HasError(WithMessage(HasSubstr(
- "duplicate of com.android.apex.compressed found"))));
-}
-
-TEST_F(ApexdMountTest, CopySepolicyToMetadata) {
- std::string file_path = AddPreInstalledApex("com.android.sepolicy.apex");
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
- ASSERT_THAT(ActivatePackage(file_path), Ok());
- UnmountOnTearDown(file_path);
- ASSERT_THAT(CreateStagedSession("com.android.sepolicy.apex", 666), Ok());
-
- ASSERT_THAT(
- SubmitStagedSession(666, {}, /* has_rollback_enabled= */ false,
- /* is_rollback= */ false, /* rollback_id= */ -1),
- Ok());
-
- auto staged_dir = GetMetadataSepolicyStagedDir();
- ASSERT_THAT(PathExists(staged_dir + "/SEPolicy.zip"), HasValue(true));
- ASSERT_THAT(PathExists(staged_dir + "/SEPolicy.zip.sig"), HasValue(true));
- ASSERT_THAT(PathExists(staged_dir + "/SEPolicy.zip.fsv_sig"), HasValue(true));
-}
-
-TEST_F(ApexdMountTest, AbortSepolicyApexInstall) {
- std::string file_path = AddPreInstalledApex("com.android.sepolicy.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- ASSERT_THAT(CreateStagedSession("com.android.sepolicy.apex", 666), Ok());
- ASSERT_THAT(
- SubmitStagedSession(666, {}, /* has_rollback_enabled= */ false,
- /* is_rollback= */ false, /* rollback_id= */ -1),
- Ok());
-
- auto staged_dir = GetMetadataSepolicyStagedDir();
- ASSERT_THAT(PathExists(staged_dir), HasValue(true));
- ASSERT_FALSE(IsEmptyDirectory(staged_dir));
-
- ASSERT_THAT(AbortStagedSession(666), Ok());
- ASSERT_THAT(PathExists(staged_dir), HasValue(false));
-}
-
class ApexActivationFailureTests : public ApexdMountTest {};
TEST_F(ApexActivationFailureTests, BuildFingerprintDifferent) {
@@ -4374,7 +3512,7 @@
HasSubstr("More than one APEX package found"));
}
-TEST_F(ApexActivationFailureTests, CorruptedSuperblockApexCannotBeStaged) {
+TEST_F(ApexActivationFailureTests, PostInstallFailsForApex) {
auto apex_session =
CreateStagedSession("apex.apexd_test_corrupt_superblock_apex.apex", 123);
apex_session->UpdateStateAndCommit(SessionState::STAGED);
@@ -4383,7 +3521,7 @@
apex_session = ApexSession::GetSession(123);
ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("Couldn't find filesystem magic"));
+ HasSubstr("Postinstall failed for session"));
}
TEST_F(ApexActivationFailureTests, CorruptedApexCannotBeStaged) {
@@ -4400,7 +3538,7 @@
TEST_F(ApexActivationFailureTests, ActivatePackageImplFails) {
auto shim_path = AddPreInstalledApex("com.android.apex.cts.shim.apex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
auto apex_session =
CreateStagedSession("com.android.apex.cts.shim.v2_wrong_sha.apex", 123);
@@ -4425,7 +3563,7 @@
auto pre_installed_apex = AddPreInstalledApex("apex.apexd_test.apex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
apex_session->UpdateStateAndCommit(SessionState::STAGED);
@@ -4449,7 +3587,7 @@
auto pre_installed_apex = AddPreInstalledApex("apex.apexd_test.apex");
auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
+ ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
apex_session->UpdateStateAndCommit(SessionState::STAGED);
@@ -4461,403 +3599,5 @@
ASSERT_EQ(apex_session->GetState(), SessionState::REVERTED);
}
-TEST_F(ApexdMountTest, OnBootstrapCreatesEmptyDmDevices) {
- AddPreInstalledApex("apex.apexd_test.apex");
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- DeviceMapper& dm = DeviceMapper::Instance();
-
- auto cleaner = make_scope_guard([&]() {
- dm.DeleteDeviceIfExists("com.android.apex.test_package", 1s);
- dm.DeleteDeviceIfExists("com.android.apex.compressed", 1s);
- });
-
- ASSERT_EQ(0, OnBootstrap());
-
- ASSERT_EQ(dm::DmDeviceState::SUSPENDED,
- dm.GetState("com.android.apex.test_package"));
- ASSERT_EQ(dm::DmDeviceState::SUSPENDED,
- dm.GetState("com.android.apex.compressed"));
-}
-
-TEST_F(ApexdUnitTest, StagePackagesFailKey) {
- auto status =
- StagePackages({GetTestFile("apex.apexd_test_no_inst_key.apex")});
-
- ASSERT_THAT(
- status,
- HasError(WithMessage(("No preinstalled apex found for package "
- "com.android.apex.test_package.no_inst_key"))));
-}
-
-TEST_F(ApexdUnitTest, StagePackagesSuccess) {
- AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- auto status = StagePackages({GetTestFile("apex.apexd_test.apex")});
- ASSERT_THAT(status, Ok());
-
- auto staged_path = StringPrintf("%s/com.android.apex.test_package@1.apex",
- GetDataDir().c_str());
- ASSERT_EQ(0, access(staged_path.c_str(), F_OK));
-}
-
-TEST_F(ApexdUnitTest, StagePackagesClearsPreviouslyActivePackage) {
- AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- auto current_apex = AddDataApex("apex.apexd_test.apex");
- ASSERT_EQ(0, access(current_apex.c_str(), F_OK));
-
- auto status = StagePackages({GetTestFile("apex.apexd_test_v2.apex")});
- ASSERT_THAT(status, Ok());
-
- auto staged_path = StringPrintf("%s/com.android.apex.test_package@2.apex",
- GetDataDir().c_str());
- ASSERT_EQ(0, access(staged_path.c_str(), F_OK));
- ASSERT_EQ(-1, access(current_apex.c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-}
-
-TEST_F(ApexdUnitTest, StagePackagesClearsPreviouslyActivePackageDowngrade) {
- AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- auto current_apex = AddDataApex("apex.apexd_test_v2.apex");
- ASSERT_EQ(0, access(current_apex.c_str(), F_OK));
-
- auto status = StagePackages({GetTestFile("apex.apexd_test.apex")});
- ASSERT_THAT(status, Ok());
-
- auto staged_path = StringPrintf("%s/com.android.apex.test_package@1.apex",
- GetDataDir().c_str());
- ASSERT_EQ(0, access(staged_path.c_str(), F_OK));
- ASSERT_EQ(-1, access(current_apex.c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-}
-
-TEST_F(ApexdUnitTest, StagePackagesAlreadyStagedPackage) {
- AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- auto status = StagePackages({GetTestFile("apex.apexd_test.apex")});
- ASSERT_THAT(status, Ok());
-
- auto staged_path = StringPrintf("%s/com.android.apex.test_package@1.apex",
- GetDataDir().c_str());
- struct stat stat1;
- ASSERT_EQ(0, stat(staged_path.c_str(), &stat1));
- ASSERT_TRUE(S_ISREG(stat1.st_mode));
-
- {
- auto apex = ApexFile::Open(staged_path);
- ASSERT_THAT(apex, Ok());
- ASSERT_FALSE(apex->GetManifest().nocode());
- }
-
- auto status2 = StagePackages({GetTestFile("apex.apexd_test_nocode.apex")});
- ASSERT_THAT(status2, Ok());
-
- struct stat stat2;
- ASSERT_EQ(0, stat(staged_path.c_str(), &stat2));
- ASSERT_TRUE(S_ISREG(stat2.st_mode));
-
- ASSERT_NE(stat1.st_ino, stat2.st_ino);
-
- {
- auto apex = ApexFile::Open(staged_path);
- ASSERT_THAT(apex, Ok());
- ASSERT_TRUE(apex->GetManifest().nocode());
- }
-}
-
-TEST_F(ApexdUnitTest, StagePackagesMultiplePackages) {
- AddPreInstalledApex("apex.apexd_test.apex");
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- auto status =
- StagePackages({GetTestFile("apex.apexd_test_v2.apex"),
- GetTestFile("apex.apexd_test_different_app.apex")});
- ASSERT_THAT(status, Ok());
-
- auto staged_path1 = StringPrintf("%s/com.android.apex.test_package@2.apex",
- GetDataDir().c_str());
- auto staged_path2 = StringPrintf("%s/com.android.apex.test_package_2@1.apex",
- GetDataDir().c_str());
- ASSERT_EQ(0, access(staged_path1.c_str(), F_OK));
- ASSERT_EQ(0, access(staged_path2.c_str(), F_OK));
-}
-
-TEST_F(ApexdUnitTest, UnstagePackages) {
- auto file_path1 = AddDataApex("apex.apexd_test.apex");
- auto file_path2 = AddDataApex("apex.apexd_test_different_app.apex");
-
- ASSERT_THAT(UnstagePackages({file_path1}), Ok());
- ASSERT_EQ(-1, access(file_path1.c_str(), F_OK));
- ASSERT_EQ(errno, ENOENT);
- ASSERT_EQ(0, access(file_path2.c_str(), F_OK));
-}
-
-TEST_F(ApexdUnitTest, UnstagePackagesEmptyInput) {
- auto file_path1 = AddDataApex("apex.apexd_test.apex");
- auto file_path2 = AddDataApex("apex.apexd_test_different_app.apex");
-
- ASSERT_THAT(UnstagePackages({}),
- HasError(WithMessage("Empty set of inputs")));
- ASSERT_EQ(0, access(file_path1.c_str(), F_OK));
- ASSERT_EQ(0, access(file_path2.c_str(), F_OK));
-}
-
-TEST_F(ApexdUnitTest, UnstagePackagesFail) {
- auto file_path1 = AddDataApex("apex.apexd_test.apex");
- auto bad_path = GetDataDir() + "/missing.apex";
-
- ASSERT_THAT(UnstagePackages({file_path1, bad_path}), Not(Ok()));
- ASSERT_EQ(0, access(file_path1.c_str(), F_OK));
-}
-
-TEST_F(ApexdUnitTest, UnstagePackagesFailPreInstalledApex) {
- auto file_path1 = AddPreInstalledApex("apex.apexd_test.apex");
- auto file_path2 = AddDataApex("apex.apexd_test_different_app.apex");
-
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_THAT(instance.AddPreInstalledApex({GetBuiltInDir()}), Ok());
-
- ASSERT_THAT(UnstagePackages({file_path1, file_path2}),
- HasError(WithMessage("Can't uninstall pre-installed apex " +
- file_path1)));
- ASSERT_EQ(0, access(file_path1.c_str(), F_OK));
- ASSERT_EQ(0, access(file_path2.c_str(), F_OK));
-}
-
-TEST_F(ApexdUnitTest, RevertStoresCrashingNativeProcess) {
- MockCheckpointInterface checkpoint_interface;
- checkpoint_interface.SetSupportsCheckpoint(true);
- InitializeVold(&checkpoint_interface);
-
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 1543);
- ASSERT_THAT(apex_session, Ok());
- ASSERT_THAT(apex_session->UpdateStateAndCommit(SessionState::ACTIVATED),
- Ok());
-
- ASSERT_THAT(RevertActiveSessions("test_process", ""), Ok());
- apex_session = ApexSession::GetSession(1543);
- ASSERT_THAT(apex_session, Ok());
- ASSERT_EQ(apex_session->GetCrashingNativeProcess(), "test_process");
-}
-
-TEST_F(ApexdUnitTest, MountAndDeriveClasspathNoJar) {
- AddPreInstalledApex("apex.apexd_test_classpath.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- // Call MountAndDeriveClassPath
- auto apex_file = ApexFile::Open(GetTestFile("apex.apexd_test.apex"));
- auto package_name = apex_file->GetManifest().name();
- std::vector<ApexFile> apex_files;
- apex_files.emplace_back(std::move(*apex_file));
- auto class_path = MountAndDeriveClassPath(apex_files);
- ASSERT_THAT(class_path, Ok());
- ASSERT_THAT(class_path->HasClassPathJars(package_name), false);
-}
-
-TEST_F(ApexdUnitTest, MountAndDeriveClassPathJarsPresent) {
- AddPreInstalledApex("apex.apexd_test_classpath.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- // Call MountAndDeriveClassPath
- auto apex_file =
- ApexFile::Open(GetTestFile("apex.apexd_test_classpath.apex"));
- auto package_name = apex_file->GetManifest().name();
- std::vector<ApexFile> apex_files;
- apex_files.emplace_back(std::move(*apex_file));
- auto class_path = MountAndDeriveClassPath(apex_files);
- ASSERT_THAT(class_path, Ok());
- ASSERT_THAT(class_path->HasClassPathJars(package_name), true);
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApexWrongSELinuxContext) {
- auto compressed_apex = ApexFile::Open(
- AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
-
- std::vector<ApexFileRef> compressed_apex_list;
- compressed_apex_list.emplace_back(std::cref(*compressed_apex));
- auto return_value =
- ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
- ASSERT_EQ(return_value.size(), 1u);
-
- auto decompressed_apex_path = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- // Verify that so far it has correct context.
- ASSERT_EQ(kTestActiveApexSelinuxCtx,
- GetSelinuxContext(decompressed_apex_path));
-
- // Manually mess up the context
- ASSERT_EQ(0, setfilecon(decompressed_apex_path.c_str(),
- "u:object_r:apex_data_file:s0"));
- ASSERT_EQ("u:object_r:apex_data_file:s0",
- GetSelinuxContext(decompressed_apex_path));
-
- auto attempt_2 =
- ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
- ASSERT_EQ(attempt_2.size(), 1u);
- // Verify that it again has correct context.
- ASSERT_EQ(kTestActiveApexSelinuxCtx,
- GetSelinuxContext(decompressed_apex_path));
-}
-
-TEST_F(ApexdMountTest, OnStartNoApexUpdated) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
- std::string apex_path_4 =
- AddDecompressedApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
-
- OnStart();
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
- UnmountOnTearDown(apex_path_4);
-
- auto updated_apexes = GetChangedActiveApexesForTesting();
- ASSERT_EQ(updated_apexes.size(), 0u);
- // Quick check that all apexes were mounted
- auto apex_mounts = GetApexMounts();
- ASSERT_EQ(apex_mounts.size(), 6u);
-}
-
-TEST_F(ApexdMountTest, OnStartDecompressingConsideredApexUpdate) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string decompressed_active_apex = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
-
- OnStart();
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto updated_apexes = GetChangedActiveApexesForTesting();
- ASSERT_EQ(updated_apexes.size(), 1u);
- auto apex_file = ApexFile::Open(decompressed_active_apex);
- ASSERT_THAT(apex_file, Ok());
- ASSERT_TRUE(IsActiveApexChanged(*apex_file));
-}
-
-TEST_F(ApexdMountTest, ActivatesStagedSession) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string preinstalled_apex = AddPreInstalledApex("apex.apexd_test.apex");
- auto apex_session = CreateStagedSession("apex.apexd_test_v2.apex", 37);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
-
- std::string active_apex =
- GetDataDir() + "/" + "com.android.apex.test_package@2.apex";
-
- UnmountOnTearDown(preinstalled_apex);
- UnmountOnTearDown(active_apex);
- OnStart();
-
- // Quick check that session was activated
- {
- auto session = ApexSession::GetSession(37);
- ASSERT_THAT(session, Ok());
- ASSERT_EQ(session->GetState(), SessionState::ACTIVATED);
- }
-
- auto updated_apexes = GetChangedActiveApexesForTesting();
- ASSERT_EQ(updated_apexes.size(), 1u);
- auto apex_file = ApexFile::Open(active_apex);
- ASSERT_THAT(apex_file, Ok());
- ASSERT_TRUE(IsActiveApexChanged(*apex_file));
-}
-
-TEST_F(ApexdMountTest, FailsToActivateStagedSession) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string preinstalled_apex = AddPreInstalledApex("apex.apexd_test.apex");
- auto apex_session =
- CreateStagedSession("apex.apexd_test_manifest_mismatch.apex", 73);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
-
- UnmountOnTearDown(preinstalled_apex);
- OnStart();
-
- // Quick check that session was activated
- {
- auto session = ApexSession::GetSession(73);
- ASSERT_THAT(session, Ok());
- ASSERT_NE(session->GetState(), SessionState::ACTIVATED);
- }
-
- auto updated_apexes = GetChangedActiveApexesForTesting();
- ASSERT_EQ(updated_apexes.size(), 1u);
-
- auto apex_file = ApexFile::Open(preinstalled_apex);
- ASSERT_THAT(apex_file, Ok());
- ASSERT_TRUE(IsActiveApexChanged(*apex_file));
-}
-
-TEST_F(ApexdMountTest, FailsToActivateApexFallbacksToSystemOne) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string preinstalled_apex = AddPreInstalledApex("apex.apexd_test.apex");
- AddDataApex("apex.apexd_test_manifest_mismatch.apex");
-
- ASSERT_THAT(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}),
- Ok());
-
- UnmountOnTearDown(preinstalled_apex);
- OnStart();
-
- auto updated_apexes = GetChangedActiveApexesForTesting();
- ASSERT_EQ(updated_apexes.size(), 1u);
-
- auto apex_file = ApexFile::Open(preinstalled_apex);
- ASSERT_THAT(apex_file, Ok());
- ASSERT_TRUE(IsActiveApexChanged(*apex_file));
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_test_utils.h b/apexd/apexd_test_utils.h
index 2ba7660..5e3689d 100644
--- a/apexd/apexd_test_utils.h
+++ b/apexd/apexd_test_utils.h
@@ -17,9 +17,9 @@
#include <filesystem>
#include <fstream>
+#include <asm-generic/errno-base.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <linux/loop.h>
#include <sched.h>
#include <sys/mount.h>
@@ -33,21 +33,27 @@
#include <android/apex/ApexInfo.h>
#include <android/apex/ApexSessionInfo.h>
#include <binder/IServiceManager.h>
-#include <fstab/fstab.h>
-#include <libdm/dm.h>
#include <selinux/android.h>
#include "apex_file.h"
-#include "apexd_loop.h"
-#include "apexd_utils.h"
#include "session_state.pb.h"
#include "com_android_apex.h"
+using android::base::Error;
+using android::base::Result;
+using apex::proto::SessionState;
+
namespace android {
namespace apex {
namespace testing {
+using ::testing::AllOf;
+using ::testing::Eq;
+using ::testing::ExplainMatchResult;
+using ::testing::Field;
+using ::testing::Property;
+
template <typename T>
inline ::testing::AssertionResult IsOk(const android::base::Result<T>& result) {
if (result.ok()) {
@@ -67,10 +73,6 @@
}
MATCHER_P(SessionInfoEq, other, "") {
- using ::testing::AllOf;
- using ::testing::Eq;
- using ::testing::Field;
-
return ExplainMatchResult(
AllOf(
Field("sessionId", &ApexSessionInfo::sessionId, Eq(other.sessionId)),
@@ -93,10 +95,6 @@
}
MATCHER_P(ApexInfoEq, other, "") {
- using ::testing::AllOf;
- using ::testing::Eq;
- using ::testing::Field;
-
return ExplainMatchResult(
AllOf(Field("moduleName", &ApexInfo::moduleName, Eq(other.moduleName)),
Field("modulePath", &ApexInfo::modulePath, Eq(other.modulePath)),
@@ -109,10 +107,6 @@
}
MATCHER_P(ApexFileEq, other, "") {
- using ::testing::AllOf;
- using ::testing::Eq;
- using ::testing::Property;
-
return ExplainMatchResult(
AllOf(Property("path", &ApexFile::GetPath, Eq(other.get().GetPath())),
Property("image_offset", &ApexFile::GetImageOffset,
@@ -171,13 +165,13 @@
*os << "}";
}
-inline android::base::Result<bool> CompareFiles(const std::string& filename1,
- const std::string& filename2) {
+inline Result<bool> CompareFiles(const std::string& filename1,
+ const std::string& filename2) {
std::ifstream file1(filename1, std::ios::binary);
std::ifstream file2(filename2, std::ios::binary);
if (file1.bad() || file2.bad()) {
- return android::base::Error() << "Could not open one of the file";
+ return Error() << "Could not open one of the file";
}
std::istreambuf_iterator<char> begin1(file1);
@@ -304,138 +298,12 @@
// Just in case, run restorecon -R on /apex.
if (selinux_android_restorecon("/apex", SELINUX_ANDROID_RESTORECON_RECURSE) <
0) {
- return ErrnoError() << "Failed to restorecon /apex";
+ return android::base::ErrnoError() << "Failed to restorecon /apex";
}
return {};
}
-// Simpler version of loop::CreateLoopDevice. Uses LOOP_SET_FD/LOOP_SET_STATUS64
-// instead of LOOP_CONFIGURE.
-// TODO(b/191244059) use loop::CreateLoopDevice
-inline base::Result<loop::LoopbackDeviceUniqueFd> CreateLoopDeviceForTest(
- const std::string& filepath) {
- base::unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
- if (ctl_fd.get() == -1) {
- return base::ErrnoError() << "Failed to open loop-control";
- }
- int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
- if (num == -1) {
- return base::ErrnoError() << "Failed LOOP_CTL_GET_FREE";
- }
- auto loop_device = loop::WaitForDevice(num);
- if (!loop_device.ok()) {
- return loop_device.error();
- }
- base::unique_fd target_fd(open(filepath.c_str(), O_RDONLY | O_CLOEXEC));
- if (target_fd.get() == -1) {
- return base::ErrnoError() << "Failed to open " << filepath;
- }
- struct loop_info64 li = {};
- strlcpy((char*)li.lo_crypt_name, filepath.c_str(), LO_NAME_SIZE);
- li.lo_flags |= LO_FLAGS_AUTOCLEAR;
- if (ioctl(loop_device->device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {
- return base::ErrnoError() << "Failed to LOOP_SET_FD";
- }
- if (ioctl(loop_device->device_fd.get(), LOOP_SET_STATUS64, &li) == -1) {
- return base::ErrnoError() << "Failed to LOOP_SET_STATUS64";
- }
- return loop_device;
-}
-
-inline base::Result<loop::LoopbackDeviceUniqueFd> MountViaLoopDevice(
- const std::string& filepath, const std::string& mount_point) {
- auto loop_device = CreateLoopDeviceForTest(filepath);
- if (loop_device.ok()) {
- close(open(mount_point.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
- 0644));
- if (0 != mount(loop_device->name.c_str(), mount_point.c_str(), nullptr,
- MS_BIND, nullptr)) {
- return base::ErrnoError() << "can't mount.";
- }
- }
- return loop_device;
-}
-
-inline base::Result<loop::LoopbackDeviceUniqueFd> WriteBlockApex(
- const std::string& apex_file, const std::string& apex_path) {
- std::string intermediate_path = apex_path + ".intermediate";
- std::filesystem::copy(apex_file, intermediate_path);
- return MountViaLoopDevice(intermediate_path, apex_path);
-}
-
-inline android::base::Result<std::string> GetBlockDeviceForApex(
- const std::string& package_id) {
- using android::fs_mgr::Fstab;
- using android::fs_mgr::GetEntryForMountPoint;
- using android::fs_mgr::ReadFstabFromFile;
-
- std::string mount_point = std::string(kApexRoot) + "/" + package_id;
- Fstab fstab;
- if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
- return android::base::Error() << "Failed to read /proc/mounts";
- }
- auto entry = GetEntryForMountPoint(&fstab, mount_point);
- if (entry == nullptr) {
- return android::base::Error()
- << "Can't find " << mount_point << " in /proc/mounts";
- }
- return entry->blk_device;
-}
-
-inline android::base::Result<void> ReadDevice(const std::string& block_device) {
- static constexpr int kBlockSize = 4096;
- static constexpr size_t kBufSize = 1024 * kBlockSize;
- std::vector<uint8_t> buffer(kBufSize);
-
- android::base::unique_fd fd(
- TEMP_FAILURE_RETRY(open(block_device.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd.get() == -1) {
- return android::base::ErrnoError() << "Can't open " << block_device;
- }
-
- while (true) {
- int n = read(fd.get(), buffer.data(), kBufSize);
- if (n < 0) {
- return android::base::ErrnoError() << "Failed to read " << block_device;
- }
- if (n == 0) {
- break;
- }
- }
- return {};
-}
-
-inline android::base::Result<std::vector<std::string>> ListChildLoopDevices(
- const std::string& name) {
- using android::base::Error;
- using android::dm::DeviceMapper;
-
- DeviceMapper& dm = DeviceMapper::Instance();
- std::string dm_path;
- if (!dm.GetDmDevicePathByName(name, &dm_path)) {
- return Error() << "Failed to get path of dm device " << name;
- }
- // It's a little bit sad we can't use ConsumePrefix here :(
- constexpr std::string_view kDevPrefix = "/dev/";
- if (!android::base::StartsWith(dm_path, kDevPrefix)) {
- return Error() << "Illegal path " << dm_path;
- }
- dm_path = dm_path.substr(kDevPrefix.length());
- std::vector<std::string> children;
- std::string dir = "/sys/" + dm_path + "/slaves";
- auto status = WalkDir(dir, [&](const auto& entry) {
- std::error_code ec;
- if (entry.is_symlink(ec)) {
- children.push_back("/dev/block/" + entry.path().filename().string());
- }
- });
- if (!status.ok()) {
- return status.error();
- }
- return children;
-}
-
} // namespace apex
} // namespace android
@@ -444,25 +312,12 @@
namespace apex {
namespace testing {
-
-// "preinstalledModulePath" is an optional in ApexInfoList.xsd.
-// getPreinstalledModulePath() should be called when hasPreinstalledModulePath()
-// returns true. Introducing a simple wrapper which returns optional<string>.
-inline std::optional<std::string> getPreinstalledModulePath(
- const ApexInfo& obj) {
- if (obj.hasPreinstalledModulePath()) {
- return obj.getPreinstalledModulePath();
- }
- return std::nullopt;
-}
-
MATCHER_P(ApexInfoXmlEq, other, "") {
using ::testing::AllOf;
using ::testing::Eq;
using ::testing::ExplainMatchResult;
using ::testing::Field;
using ::testing::Property;
- using ::testing::ResultOf;
return ExplainMatchResult(
AllOf(
@@ -470,8 +325,9 @@
Eq(other.getModuleName())),
Property("modulePath", &ApexInfo::getModulePath,
Eq(other.getModulePath())),
- ResultOf(&getPreinstalledModulePath,
- Eq(getPreinstalledModulePath(other))),
+ Property("preinstalledModulePath",
+ &ApexInfo::getPreinstalledModulePath,
+ Eq(other.getPreinstalledModulePath())),
Property("versionCode", &ApexInfo::getVersionCode,
Eq(other.getVersionCode())),
Property("isFactory", &ApexInfo::getIsFactory,
@@ -489,10 +345,8 @@
*os << "apex_info: {\n";
*os << " moduleName : " << apex.getModuleName() << "\n";
*os << " modulePath : " << apex.getModulePath() << "\n";
- if (apex.hasPreinstalledModulePath()) {
- *os << " preinstalledModulePath : " << apex.getPreinstalledModulePath()
- << "\n";
- }
+ *os << " preinstalledModulePath : " << apex.getPreinstalledModulePath()
+ << "\n";
*os << " versionCode : " << apex.getVersionCode() << "\n";
*os << " isFactory : " << apex.getIsFactory() << "\n";
*os << " isActive : " << apex.getIsActive() << "\n";
diff --git a/apexd/apexd_testdata/Android.bp b/apexd/apexd_testdata/Android.bp
index 0307690..0e7039a 100644
--- a/apexd/apexd_testdata/Android.bp
+++ b/apexd/apexd_testdata/Android.bp
@@ -105,7 +105,7 @@
name: "gen_key_mismatch_capex",
out: ["com.android.apex.compressed_different_key.capex"],
srcs: [":apex.apexd_test_no_inst_key"],
- tools: ["soong_zip", "zipalign", "conv_apex_manifest", "apex_compression_tool", "avbtool"],
+ tools: ["soong_zip", "zipalign", "conv_apex_manifest", "apex_compression_tool"],
cmd: "unzip -q $(in) -d $(genDir) && " +
"$(location conv_apex_manifest) setprop name com.android.apex.compressed $(genDir)/apex_manifest.pb && " +
"$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
@@ -113,9 +113,8 @@
"-o $(genDir)/unaligned.apex && " +
"$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
"$(genDir)/com.android.apex.compressed_different_key.apex && " +
- "HOST_OUT_BIN=$$(dirname $(location apex_compression_tool)) && " +
"$(location apex_compression_tool) compress " +
- "--apex_compression_tool_path=\"$$HOST_OUT_BIN\" " +
+ "--apex_compression_tool_path='out/soong/host/linux-x86/bin:prebuilts/sdk/tools/linux/bin' " +
"--input=$(genDir)/com.android.apex.compressed_different_key.apex " +
"--output=$(genDir)/com.android.apex.compressed_different_key.capex"
}
@@ -204,17 +203,6 @@
}
apex {
- name: "apex.apexd_test_erofs",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.test_package.key",
- installable: false,
- min_sdk_version: "current",
- payload_fs_type: "erofs",
-}
-
-apex {
name: "apex.apexd_test_no_hashtree",
manifest: "manifest.json",
file_contexts: ":apex.test-file_contexts",
@@ -281,6 +269,60 @@
}
apex_key {
+ name: "com.android.apex.test_package.preinstall.key",
+ public_key: "com.android.apex.test_package.preinstall.avbpubkey",
+ private_key: "com.android.apex.test_package.preinstall.pem",
+ installable: false,
+}
+
+apex {
+ name: "apex.apexd_test_preinstall",
+ manifest: "manifest_preinstall.json",
+ file_contexts: ":apex.test-file_contexts",
+ prebuilts: ["sample_prebuilt_file"],
+ key: "com.android.apex.test_package.preinstall.key",
+ binaries: ["apex_test_preInstallHook"],
+ installable: false,
+ updatable: false,
+}
+
+apex_key {
+ name: "com.android.apex.test_package.postinstall.key",
+ public_key: "com.android.apex.test_package.postinstall.avbpubkey",
+ private_key: "com.android.apex.test_package.postinstall.pem",
+ installable: false,
+}
+
+apex {
+ name: "apex.apexd_test_postinstall",
+ manifest: "manifest_postinstall.json",
+ file_contexts: ":apex.test-file_contexts",
+ prebuilts: ["sample_prebuilt_file"],
+ key: "com.android.apex.test_package.postinstall.key",
+ binaries: ["apex_test_postInstallHook"],
+ installable: false,
+ updatable: false,
+}
+
+apex_key {
+ name: "com.android.apex.test_package.prepostinstall.fail.key",
+ public_key: "com.android.apex.test_package.prepostinstall.fail.avbpubkey",
+ private_key: "com.android.apex.test_package.prepostinstall.fail.pem",
+ installable: false,
+}
+
+apex {
+ name: "apex.apexd_test_prepostinstall.fail",
+ manifest: "manifest_prepostinstall.fail.json",
+ file_contexts: ":apex.test-file_contexts",
+ prebuilts: ["sample_prebuilt_file"],
+ key: "com.android.apex.test_package.prepostinstall.fail.key",
+ binaries: ["apex_test_prePostInstallHookFail"],
+ installable: false,
+ updatable: false,
+}
+
+apex_key {
name: "com.android.apex.test_package.no_inst_key.key",
public_key: "com.android.apex.test_package.no_inst_key.avbpubkey",
private_key: "com.android.apex.test_package.no_inst_key.pem",
@@ -308,17 +350,6 @@
updatable: false,
}
-apex {
- name: "apex.apexd_test_erofs_no_inst_key",
- manifest: "manifest_no_inst_key.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.test_package.no_inst_key.key",
- installable: false,
- payload_fs_type: "erofs",
- updatable: false,
-}
-
apex_key {
name: "com.android.apex.test_package_2.key",
public_key: "com.android.apex.test_package_2.avbpubkey",
@@ -336,6 +367,21 @@
updatable: false,
}
+sh_binary {
+ name: "apex_test_preInstallHook",
+ src: "preInstallHook.sh",
+}
+
+sh_binary {
+ name: "apex_test_postInstallHook",
+ src: "postInstallHook.sh",
+}
+
+sh_binary {
+ name: "apex_test_prePostInstallHookFail",
+ src: "fail.sh",
+}
+
apex {
name: "apex.apexd_test_nocode",
manifest: "manifest_nocode.json",
@@ -510,57 +556,3 @@
"test.rebootless_apex_priv_app_in_apex",
],
}
-
-apex_test {
- name: "apex.apexd_test_classpath",
- bootclasspath_fragments: ["apex.apexd_test_bootclasspath-fragment"],
- systemserverclasspath_fragments: ["apex.apexd_test_systemserverclasspath-fragment"],
- manifest: "manifest.json",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.test_package.key",
- file_contexts: ":apex.test-file_contexts",
- installable: false, // Should never be installed on the systemimage
- updatable: false,
-}
-
-bootclasspath_fragment {
- name: "apex.apexd_test_bootclasspath-fragment",
- contents: ["test_framework-apexd"],
-}
-
-systemserverclasspath_fragment {
- name: "apex.apexd_test_systemserverclasspath-fragment",
- contents: ["test_service-apexd"],
-}
-
-java_sdk_library {
- name: "test_framework-apexd",
- defaults: ["framework-module-defaults"],
- srcs: ["src/com/android/apex/test/Test.java"],
- permitted_packages: ["com.android.apex.test"],
- min_sdk_version: "30",
-
- // Test only SDK, don't check against released APIs.
- unsafe_ignore_missing_latest_api: true,
- // Output the api files to a special directory that won't trigger an API
- // review as it is a test only API.
- api_dir: "apis_for_tests",
- // Testing only.
- no_dist: true,
-}
-
-java_sdk_library {
- name: "test_service-apexd",
- defaults: ["framework-system-server-module-defaults"],
- srcs: ["src/com/android/apex/test/Test.java"],
- permitted_packages: ["com.android.apex.test"],
- min_sdk_version: "30",
-
- // Test only SDK, don't check against released APIs.
- unsafe_ignore_missing_latest_api: true,
- // Output the api files to a special directory that won't trigger an API
- // review as it is a test only API.
- api_dir: "apis_for_tests",
- // Testing only.
- no_dist: true,
-}
diff --git a/apexd/apexd_testdata/apis_for_tests/current.txt b/apexd/apexd_testdata/apis_for_tests/current.txt
deleted file mode 100644
index 7ceb448..0000000
--- a/apexd/apexd_testdata/apis_for_tests/current.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-// Signature format: 2.0
-package com.android.apex.test {
-
- public class Test {
- ctor public Test();
- }
-
-}
-
diff --git a/apexd/apexd_testdata/apis_for_tests/module-lib-current.txt b/apexd/apexd_testdata/apis_for_tests/module-lib-current.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/module-lib-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/apis_for_tests/module-lib-removed.txt b/apexd/apexd_testdata/apis_for_tests/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/apis_for_tests/removed.txt b/apexd/apexd_testdata/apis_for_tests/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/apis_for_tests/system-current.txt b/apexd/apexd_testdata/apis_for_tests/system-current.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/system-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/apis_for_tests/system-removed.txt b/apexd/apexd_testdata/apis_for_tests/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/apis_for_tests/system-server-current.txt b/apexd/apexd_testdata/apis_for_tests/system-server-current.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/system-server-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/apis_for_tests/system-server-removed.txt b/apexd/apexd_testdata/apis_for_tests/system-server-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apexd_testdata/apis_for_tests/system-server-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apexd_testdata/com.android.apex.test_package.postinstall.avbpubkey b/apexd/apexd_testdata/com.android.apex.test_package.postinstall.avbpubkey
new file mode 100644
index 0000000..97f26a2
--- /dev/null
+++ b/apexd/apexd_testdata/com.android.apex.test_package.postinstall.avbpubkey
Binary files differ
diff --git a/apexd/apexd_testdata/com.android.apex.test_package.postinstall.pem b/apexd/apexd_testdata/com.android.apex.test_package.postinstall.pem
new file mode 100644
index 0000000..af1efd9
--- /dev/null
+++ b/apexd/apexd_testdata/com.android.apex.test_package.postinstall.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAqxHLv23c1mE6rgPsLORpH5iEZYR9QUxFPDXDTqNK43mUSnJ8
+XwScbQ8JXJNsTnpCshk1AlE/1vXTURMI2Fa1ns8G8QEZZaEmEhteRm1kH5QjR0YU
+Z6kJjGfVP4G7YCD0q0Pq5r3jXfHrUDDPexvt7yuprnYJB89Sniv2atTZwC7RG/PW
+iVK3ZF/lX9ZL9ko0xOUlJSIkIfN69kzF/8aeYLwPohTeYdBP6Wq/if0YKuB5h5xE
++OVBJpi0a2IymOTLq0zg91BjTJKVvn4Nx7UTdPNp7kk6Pt82SFOFIi/1H7Hlnslp
+pDXdc5nqwod4eVXE2ag7pMIjwPP+aairJ1aXcKdtwqXnOQ3bJOjAJJQHj8eHe1RX
+lG5VovGipex5ImBqRfj3jrZSZNiJzPCOIDUTHxImY6/81UAWxWGrnT3niW0jKjTa
+Sfi+izV8b+2CLrpE4oUCDQjHZ6nDp82xkSlm0lhTGDK417NuVNvsD1eNFnpsyRmr
+xpaBg8gcYTGgNvQ5uSrFXN9b6O5Z6nYnjLLUjvqbt1gTVqJH+FaKsMN6Xk4M46h6
+nqGEQHUIsPUx+dAbrb+Ard5CIJvey2m3DDpoHzriyZh8P3pNdOt0+OIzrUCAxyp2
+i9khNCE2lDOczWvKDwGczmmFlB0wj5YP4sDG906oTlcTC2IeVwtEOxjyePsCAwEA
+AQKCAgEApsnmBhE+ZEJN7QXkCez01ZplU3k2iiirxEWC07P/uwN54o/21MlxHh+v
+9/PAgE9RocVT2puPC62Hx58wW4VG9LxSvz1cHqtcrADFDRNwsB1FvCMGl/7GUX+W
++aEqKFJZWnYQm8H94UWSMRA16ojTlgHTIUbyDQxFN/QTABvg5jB/LqqxvBfKuHGK
++MK+MzYsduAXNDoyUmvKskMuNO/Y0OXqtBN2spVgpGqwrv/1xTAxLVfeI3GZ8OCn
+357RSCKitLRzDo3xEuJEX4MVOmZAvyDoYixBPrVwfln4DtoFO06+Wu9zMWhXLnOd
+4OYmPt6x26jb5gpmw6TgovGRVfxmDxa3uDr9LNfobRnSHru1qCrq9SBcHi61sj9O
+OqGNQUWXBzUKwfFRwar4KOb/kKgcgsTkkRPEStNenDSq0VHIIkrNQVIa0gkc7Bgw
+jktRX/q0zefJmxZATX3VPQQlU4bOd8dxYvRAByOVTp8AYSxMI0fHpB/+nTtMZhYm
+6CckK2RgJ4MdJ3lONCTf+fFwv0WyQmSE7vsXMv0cyjD0NoGw+M4timns7Ut8NZI2
+tji6X0HDTAtuNg31+nhCd9QHL/sqd3J7JHFjF9e6Zqe0OhRiN6CyBuZuOBjLAI86
+HdOv0QYz/+lt6cnr5keuxtqek/Eqr2jb4pcufUzjMQvN8a7sM6kCggEBANnclYiX
+Fs+chM/6oj5JQu5Ft+TiIVbfBx0RqW6ZVxnXC5ilXV/aAHCFrepma7UjYiY53/Lb
+bJtnmTyprqM8JmVAskpxV8YZJ++ZgOIHOzCXrMs7KHstbVCN750aqAdPwCOU11/V
+vKhsxyaEPQDEOO17bTHFIBkGD6u3VQ3GGgAauomNwKfzOqBAmqqiK5DSNQzk5Qs5
+UCi7ASNSK0RQRt8Q2Wr54iOn3G7c+x1L4VmrYNFg01Acwog7bVDYRLQx8lemoN/q
+uaoDvzs/GtkD3PZAY7H4vAba5mqZW9qUT6xfv11L8ijQSY/EF2K/SYc7g664xlY4
+8bm109ndgRApTXcCggEBAMkEO82lrhufs5ppSVcDCAL2qIr3UQBg7xq2nXe3fGKl
+p406vz7wB1+p0P1lJ0H654hUi9CADPsrcjZTy7zXuM4a/7iFZjmOrawat7VSrF3v
+YL6bTZpO8TOCn7V4UJM6bPjzReCa87OD9m2LwDHxsFaPQevnivptxiUNfDt06oWy
+efifjBGQtyvIfYfr5MA6zUFLnGa/pYJvD26eZ1IP2fAedP+JrH4D38Dn+LiiVaYJ
+fOFkEtZPWnQ0sGhapY5iCyIuk9ffaDoKiNXxkPclARKp1wLC8eh/fHayUmT9ZgR3
+YCu14MjjegvqQPpdjqD17cBJW6fbPXlWqfzH105TgZ0CggEALBbvEDB7hlKHsktn
+sDFFYVEssR5uXtVN7D0Zy+8uaGVTzHWS2wYUVrFHDAvkOklJ4LCPuOddKGoj4dn5
+JMHUh2M7ccNUXxvSMDQhmBychu37Izn6rEr6N3YyCtpNLQWfvdOubo+j2XYCK7JR
+YilT2APFim/5WfcXDspQZTQ1KNY/7/yHA7Y+pBXO9z9Qj8Nqxww/qjDUHxoRVeOY
+LAAPB6+yQGsHr+2Vt73y9+/WUD5Vnqn4udrIJ6fXLKhH5yvAfqqTHh2zq0uM1OGl
+fkvA2PkY8/iBnOWKAgK9SxP+t8S8xpXLESVt7bFihjJuH/cUZDSyttpZWRsKH6or
+J2kkawKCAQA1xkgpT3UwNpzZZekUud7ezBVyd47Xxxav0sJ1UESaLy6PfXPD5npS
+gR9DalgCMpjVw6hTcq4GUy0Ok4QhVKQ/nsFiH22lYCHdtJgIjcFGr871rp4n9Y5Y
+9Uy8Qx9rA2o7fvjmiQ1ArMCztXsI4VsHDPPZo+tt6wfiyaS+UxyZ/5DZjfTujgQy
+VkQepGBhfFmEajHA2uvv5L4AHagOL+dhcQRjh/T5ERg+hs/mtKas8ETUFu1jH39X
+LvEyOW2olVndHxC14zICtOa+NQ1O0DtlPsIiHvyP8erd5f5cvd0YvMahatpjY1c2
+8MfJMlYBgUjE89rtIJ1lZGW9FcjnTzeRAoIBAHV5uS9s5sscmJT4igPazfMEl3qI
+6UJUH0Lhwr6CGPc078KSebXDFeqAzDKkCgP6tmaeLFrzQDYWPcXRzKo7KcMDpLsT
+rKNAmldhTmBAzC4bC0d9WFu/hg8A04p10zwsAD458S68KJz9hy1YuXyzwMYhcH6G
+V7fqir7VbieRsXmTtaAtEDz4FqPsL4X+5mGi6cUio+ttTrYs5udYBXs3MvyZgvT9
+b6nntwV/tWpleurt3dm8dFU6aRJWvEysnXiNhQeUxO/z4aTkdFgVBidqFIfmJ3v5
+XzJf+c4/NURzKP4XFBsAIDjSEVTH00g5fs5LUeSXU3h2rQmXezMdMzMTx9U=
+-----END RSA PRIVATE KEY-----
diff --git a/apexd/apexd_testdata/com.android.apex.test_package.preinstall.avbpubkey b/apexd/apexd_testdata/com.android.apex.test_package.preinstall.avbpubkey
new file mode 100644
index 0000000..f3593c4
--- /dev/null
+++ b/apexd/apexd_testdata/com.android.apex.test_package.preinstall.avbpubkey
Binary files differ
diff --git a/apexd/apexd_testdata/com.android.apex.test_package.preinstall.pem b/apexd/apexd_testdata/com.android.apex.test_package.preinstall.pem
new file mode 100644
index 0000000..09f861b
--- /dev/null
+++ b/apexd/apexd_testdata/com.android.apex.test_package.preinstall.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEA43h4SU45Am/C2YlZllyBFQiOVCn2Z+ngoTewe9o/4++Z7/uS
+3sWyHahm9PJ3KDihmxI1gQxUMuoj1QH0oPzM19obw+Ubx0S5JeZLP3C86AuLwrxn
+ftkH1m/E8qbkIZ+bT7rWC121ZglXhYH+LPHGtocYAChsPIczHYltyyQXiSFBDKse
+b32NFJ1TOTcDkrIowajZzEFb587wCkDGOvwQlj51NmSAM32rL9vIxevzx4OKQHJx
+4IMy70c1dAi/zTiUfXIbEQRbr8KYAORnUPhtJ28olvVDcHgeQlVYu2CTWzftCvs/
+9RnrpKZOvohBV0Lx6pNG7At56oyNVhdmL4PyoLfhpATXGSAplxAsn8yHdYyImOcP
+ZioZmXfggQUVXabDH+8tDnTOu6no0p5kcyxqL+965RCnpLpo1XSi3fDVbq037Qq2
+F+XubJ30CGNYqR4HjpfqoniJIyrVz43JYTiGhvCaMEgcjHMi+CzHFa67Amu/kogK
+aOVnFe3t1YVe7sW5H+xz+tqH0foYdpGXKwF1y0BLWOlcvypNQqtiPO0uCJmgfu0q
+blJ+KAa/AGg3Iob5y9HqR87Ee7S+/c3J+jtQBzis0VA1m9ajSpy2WwaNe7yHuRmu
+v4iQsJFW8phOHLoKnUeuGqWj77pePIzO101sqPtTv/T3NOx7sjLpX4X9YgECAwEA
+AQKCAgAbHGmhuwv6aV2c1czyqdXMrvdfupyep/ZY4K1NJacFwLHlM2O+32sqM78J
+pLhk99LzC4mK9vA2HUfmBFSmt1qmw10ZzP2xk1RJ2xfO2N36/h1LOW9QZAeWHD4p
++ZApHb/CEe+e7S1ImwZuaB7mNm7LpHBM3ISB9k82TwHh+0w+0NLS8rYu7ZTaByI7
+KH5phohrBHfo60VL7JMZdbzqnM5RSeJoeDP7bxfvHU/hnwywE9JvefRuoNR6Rk9t
+o/lQOVUhWm81aQKQgS3itVZHBUTlNU9uJo9CIV7h4xAvTQRjE9hRvb5StSMrvZKX
+DOBUySrSHXmPepKuTNAvmZxZP220Voalt0WdHFI6xzuv1e3wO/3/jvVYLfKKhHw8
+WMRyZKhBAYzYCbeRJIKP0z+BrHbF+V+oX/cWjtEU9BDZ6KcQ401FgDLyPyGVfBbb
+GgqC0heOvIkaoK40XS/OEDb9BCIjgWlTZjGbeJzNmZFap9ZzRWw18W5QZdTC6X4x
+wfZiTf7k1DngcxN+kGF6ox42UycPnVKARVrBa9p7eS1NYugxXXJZgd0Oqq9DuEgt
+A1iXwkgMqcdCUMMOb/Fng7p3hUY0ANTVqnKnvtaxnq7h3SBXLfSHi1ySHzRZPb2Z
+nDM0+8UeF+W33q3DVV/YGh5MA4lMHoWmrxAoCs3YbVxz6Ano/QKCAQEA+kB38OFl
+IP0N1OWOEGJoOobLGi/XCz8qYjC5RC2CJ7V5yPR9gcVS1F8fQjsNnaYAigF0HcKS
+bkeeuXqr6KKQlhc2sKEFjVyaejT9cMMtObVlgVYkSv60cFQ/lKqnH9hGFspG2tTu
+6IjS5O7+AiRrpVvkMOGv9vvUE0TnU8cVM9f9euCP8HCGs8hE4+45tQmMK5iX0Tqm
+qKgXfhvKpAOdgbP3RKrboql+EtjF1ks7lYuyI6dfchLbaoQtU5oe09tqtjUG9iF5
+toUq/Pu+WTbWGyovcFHDS8QEKrdUe5IofIonodMZ76DJSCGrO8zp5nPDjrrhTiMN
+vx/3OZ9xM9gOSwKCAQEA6LILAugGENQCamyxIP+mtNBcuvtQerIr/q/quT5HKAyU
+GNqdpbwyp9w3Hm/Uy2q60Dt5J50MmQewrewvwQvp+bD1XIaWU1TOxkurxkDEVgkL
+8uTiA/SnDgJsNznCFt99/VhTG2BnW7nU1yKD/KcBXHJzQpnly2krCO8GxPEV5RY8
+Ebh++UzThYAszuXjY+jL3dzyuCLsJJHBbOW+aeNjNOfgoieGHCbqAjE9TlIv74Cv
+Zjnb39gphBThJ7HU7F1EWH1HvK+bs6+X9XM2MQ04+U7v0pbqFoDzQYc42KKdD7Z5
+4BGcxOdj0/a1wz7iGb7uBFmCoX3jPMQTfYl4teqxYwKCAQEA7GQHqJgRYlcIQMpT
+JzD+CgMYSfVU6n/Rdo1WBIwEfaQUlXo2MGaINqpgKb0EwJ11tudmm1IX5mprCgRR
+7V/aupzVAYYpa35FQhlaKrGDwBaU+ta3U8xEADPlF3cYhaFTm+WZhs9LmobcyHrl
+oHps4Pfrly0pfmIl08nrxpyxb5ahD/ien158L8mHIdP/2P5a1TfAeVkw4vJdtrdj
+9QihOUsZ0VigPohi2kTApQvODha2wK0zINulPnn7IxTb9/41UEbI+6llgr9Ke00G
+YtnE6EYyJ6RkmeZglUU2XcAT1IjgpSF3R3+XgzaivMt1S0ahPOtVNu0v6BG3BEyT
+r4hw/wKCAQEAu6Nua66LzaAYPpddEf31ANMQI5sqH3ZzMZHLlgrZODtEZPJMs2uZ
+8XALZljJYCq1b9q1bLMgiHoCB41wSJwB1V3TzQOeTp4RiydT4a8yYyoyX3AfrQ7o
+csyTVMkXcHhR0Swa//VyAy5LqhtkESTeXRzRQsB049zvXenZLJA3lp6iW6vJf+Bq
+pLlh6IjKHzOGyWY0tzU59JcwQU7Vh+9bfTsKEdgLNcJPausnw3NUwi2jwqwfWFan
+y6FGmkq1JtBin3SOl2GIDZIn2D5KUa2W5rq3erpFE1ZyUcHnnhEq05PSnVO2dbUc
+87x6f3HCwv4KUqmXRAAOcF6wVMe49gDFfwKCAQEAo00/8sbxTMU9lUz2muJ6Xzy2
+MlGRnYK01u4zXerojWxNowwjNXUhKU8tsEcV2OdQz07CxkKLps+5fSZ7MJfqXU/m
+HTRryb9rPMxuwK77Mnx4dWqeMnHtC+6bA0ScZHC7DbAXbkUVc36DVFssIjRkOQDw
+MMUU0qyIrvoVq/J5wZxWquEh2jt0MtKotLPXDIzJM2G0cc7e7yw09fmkSpc7xQmC
+ISgkR6C4+W2eoo3+Iq/lPoV1igg+07UZkdZS5b96asETDVHEL9Ba33J8WoOpOoEE
+gSgpS/5XubFhK4KMFR8HkIpS860+Scl3VbsFUwvwGAzkEmucseq9XaavUcfXbw==
+-----END RSA PRIVATE KEY-----
diff --git a/apexd/apexd_testdata/manifest_postinstall.json b/apexd/apexd_testdata/manifest_postinstall.json
new file mode 100644
index 0000000..80e2eeb
--- /dev/null
+++ b/apexd/apexd_testdata/manifest_postinstall.json
@@ -0,0 +1,5 @@
+{
+ "name": "com.android.apex.test_package.postinstall",
+ "version": 1,
+ "postInstallHook": "bin/apex_test_postInstallHook"
+}
diff --git a/apexd/apexd_testdata/manifest_preinstall.json b/apexd/apexd_testdata/manifest_preinstall.json
new file mode 100644
index 0000000..91a3f23
--- /dev/null
+++ b/apexd/apexd_testdata/manifest_preinstall.json
@@ -0,0 +1,5 @@
+{
+ "name": "com.android.apex.test_package.preinstall",
+ "version": 1,
+ "preInstallHook": "bin/apex_test_preInstallHook"
+}
diff --git a/apexd/apexd_testdata/manifest_prepostinstall.fail.json b/apexd/apexd_testdata/manifest_prepostinstall.fail.json
new file mode 100644
index 0000000..218c3f8
--- /dev/null
+++ b/apexd/apexd_testdata/manifest_prepostinstall.fail.json
@@ -0,0 +1,6 @@
+{
+ "name": "com.android.apex.test_package.prepostinstall.fail",
+ "version": 1,
+ "preInstallHook": "bin/apex_test_prePostInstallHookFail",
+ "postInstallHook": "bin/apex_test_prePostInstallHookFail"
+}
diff --git a/apexd/apexd_testdata/postInstallHook.sh b/apexd/apexd_testdata/postInstallHook.sh
new file mode 100644
index 0000000..3bee5a8
--- /dev/null
+++ b/apexd/apexd_testdata/postInstallHook.sh
@@ -0,0 +1,15 @@
+#!/system/bin/sh
+
+# Side test for b/124769206.
+if [ -z "$BOOTCLASSPATH" ] ; then
+ log -t apex_tests -p f "BOOTCLASSPATH is perceived as empty"
+ exit 1
+fi
+
+# Look for the session data, but do not fail and instead print a literal
+# otherwise. Sleep is an attempt to ensure that the message always reaches
+# logcat.
+/system/bin/logwrapper \
+ /system/bin/sh -c \
+ 'ls /apex/com.android.apex.test_package/etc/sample_prebuilt_file \
+ || echo "PostInstall Test" ; sleep 5s'
diff --git a/apexd/apexd_testdata/preInstallHook.sh b/apexd/apexd_testdata/preInstallHook.sh
new file mode 100644
index 0000000..2d341a8
--- /dev/null
+++ b/apexd/apexd_testdata/preInstallHook.sh
@@ -0,0 +1,15 @@
+#!/system/bin/sh
+
+# Side test for b/124769206.
+if [ -z "$BOOTCLASSPATH" ] ; then
+ log -t apex_tests -p f "BOOTCLASSPATH is perceived as empty"
+ exit 1
+fi
+
+# Look for the session data, but do not fail and instead print a literal
+# otherwise. Sleep is an attempt to ensure that the message always reaches
+# logcat.
+/system/bin/logwrapper \
+ /system/bin/sh -c \
+ 'ls /apex/com.android.apex.test_package/etc/sample_prebuilt_file \
+ || echo "PreInstall Test" ; sleep 5s'
diff --git a/apexd/apexd_testdata/src/com/android/apex/test/Test.java b/apexd/apexd_testdata/src/com/android/apex/test/Test.java
deleted file mode 100644
index b24fabf..0000000
--- a/apexd/apexd_testdata/src/com/android/apex/test/Test.java
+++ /dev/null
@@ -1,22 +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 com.android.apex.test;
-
-public class Test {
-
- public Test() {}
-}
diff --git a/apexd/apexd_utils.h b/apexd/apexd_utils.h
index 782bd2f..23194eb 100644
--- a/apexd/apexd_utils.h
+++ b/apexd/apexd_utils.h
@@ -44,6 +44,49 @@
namespace android {
namespace apex {
+inline int WaitChild(pid_t pid) {
+ int status;
+ pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+
+ if (got_pid != pid) {
+ PLOG(WARNING) << "waitpid failed: wanted " << pid << ", got " << got_pid;
+ return 1;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return 0;
+ } else {
+ return status;
+ }
+}
+
+inline android::base::Result<void> ForkAndRun(
+ const std::vector<std::string>& args) {
+ LOG(DEBUG) << "Forking : " << android::base::Join(args, " ");
+ std::vector<const char*> argv;
+ argv.resize(args.size() + 1, nullptr);
+ std::transform(args.begin(), args.end(), argv.begin(),
+ [](const std::string& in) { return in.c_str(); });
+
+ pid_t pid = fork();
+ if (pid == -1) {
+ // Fork failed.
+ return android::base::ErrnoError() << "Unable to fork";
+ }
+
+ if (pid == 0) {
+ execv(argv[0], const_cast<char**>(argv.data()));
+ PLOG(ERROR) << "execv failed";
+ _exit(1);
+ }
+
+ int rc = WaitChild(pid);
+ if (rc != 0) {
+ return android::base::Error() << "Failed run: status=" << rc;
+ }
+ return {};
+}
+
template <typename Fn>
android::base::Result<void> WalkDir(const std::string& path, Fn fn) {
namespace fs = std::filesystem;
@@ -159,11 +202,6 @@
if (android_reboot(ANDROID_RB_RESTART2, 0, nullptr) != 0) {
LOG(ERROR) << "Failed to reboot device";
}
- // Wait for reboot to complete as we expect this to be a terminal
- // command. Crash apexd if reboot does not complete even after
- // waiting an arbitrary significant amount of time.
- std::this_thread::sleep_for(std::chrono::seconds(120));
- LOG(FATAL) << "Device did not reboot within 120 seconds";
}
inline android::base::Result<void> WaitForFile(
@@ -334,17 +372,6 @@
return {};
}
-inline android::base::Result<std::string> GetfileconPath(
- const std::string& path) {
- char* ctx;
- if (getfilecon(path.c_str(), &ctx) < 0) {
- return android::base::ErrnoError() << "Failed to getfilecon " << path;
- }
- std::string ret(ctx);
- freecon(ctx);
- return ret;
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_verity.cpp b/apexd/apexd_verity.cpp
index 5db78bf..0008f6d 100644
--- a/apexd/apexd_verity.cpp
+++ b/apexd/apexd_verity.cpp
@@ -17,17 +17,14 @@
#include "apexd_verity.h"
+#include <filesystem>
+#include <vector>
+
#include <android-base/file.h>
#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <verity/hash_tree_builder.h>
-#include <filesystem>
-#include <iomanip>
-#include <sstream>
-#include <string>
-#include <vector>
-
#include "apex_constants.h"
#include "apex_file.h"
#include "apexd_utils.h"
@@ -202,15 +199,5 @@
// TODO(b/120058143): on boot complete, remove unused hashtree files
}
-std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
- std::ostringstream s;
-
- s << std::hex << std::setfill('0');
- for (size_t i = 0; i < bytes_len; i++) {
- s << std::setw(2) << static_cast<int>(bytes[i]);
- }
- return s.str();
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_verity.h b/apexd/apexd_verity.h
index deb3ac0..e3c8427 100644
--- a/apexd/apexd_verity.h
+++ b/apexd/apexd_verity.h
@@ -23,8 +23,6 @@
namespace android {
namespace apex {
-std::string BytesToHex(const uint8_t* bytes, size_t len);
-
enum PrepareHashTreeResult {
kReuse = 0,
KRegenerate = 1,
diff --git a/apexd/apexservice.cpp b/apexd/apexservice.cpp
index 801f634..4f3d2fc 100644
--- a/apexd/apexservice.cpp
+++ b/apexd/apexservice.cpp
@@ -63,16 +63,6 @@
return BinderStatus::ok();
}
-BinderStatus CheckCallerSystemOrRoot(const std::string& name) {
- uid_t uid = IPCThreadState::self()->getCallingUid();
- if (uid != AID_ROOT && uid != AID_SYSTEM) {
- std::string msg = "Only root and system_server are allowed to call " + name;
- return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
- String8(name.c_str()));
- }
- return BinderStatus::ok();
-}
-
class ApexService : public BnApexService {
public:
using BinderStatus = ::android::binder::Status;
@@ -89,12 +79,16 @@
BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
BinderStatus getStagedSessionInfo(
int session_id, ApexSessionInfo* apex_session_info) override;
- BinderStatus getStagedApexInfos(const ApexSessionParams& params,
- std::vector<ApexInfo>* aidl_return) override;
+ BinderStatus activatePackage(const std::string& package_path) override;
+ BinderStatus deactivatePackage(const std::string& package_path) override;
BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
BinderStatus getActivePackage(const std::string& package_name,
ApexInfo* aidl_return) override;
BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
+ BinderStatus preinstallPackages(
+ const std::vector<std::string>& paths) override;
+ BinderStatus postinstallPackages(
+ const std::vector<std::string>& paths) override;
BinderStatus abortStagedSession(int session_id) override;
BinderStatus revertActiveSessions() override;
BinderStatus resumeRevertIfNeeded() override;
@@ -143,9 +137,6 @@
if (!debug_check.isOk()) {
return debug_check;
}
- if (auto is_root = CheckCallerIsRoot("stagePackages"); !is_root.isOk()) {
- return is_root;
- }
LOG(DEBUG) << "stagePackages() received by ApexService, paths "
<< android::base::Join(paths, ',');
@@ -164,10 +155,6 @@
BinderStatus ApexService::unstagePackages(
const std::vector<std::string>& paths) {
- if (auto check = CheckCallerSystemOrRoot("unstagePackages"); !check.isOk()) {
- return check;
- }
-
Result<void> res = ::android::apex::UnstagePackages(paths);
if (res.ok()) {
return BinderStatus::ok();
@@ -182,11 +169,6 @@
BinderStatus ApexService::submitStagedSession(const ApexSessionParams& params,
ApexInfoList* apex_info_list) {
- auto check = CheckCallerSystemOrRoot("submitStagedSession");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "submitStagedSession() received by ApexService, session id "
<< params.sessionId << " child sessions: ["
<< android::base::Join(params.childSessionIds, ',') << "]";
@@ -213,11 +195,6 @@
}
BinderStatus ApexService::markStagedSessionReady(int session_id) {
- auto check = CheckCallerSystemOrRoot("markStagedSessionReady");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "markStagedSessionReady() received by ApexService, session id "
<< session_id;
Result<void> success = ::android::apex::MarkStagedSessionReady(session_id);
@@ -232,11 +209,6 @@
}
BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
- auto check = CheckCallerSystemOrRoot("markStagedSessionSuccessful");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG)
<< "markStagedSessionSuccessful() received by ApexService, session id "
<< session_id;
@@ -252,11 +224,6 @@
}
BinderStatus ApexService::markBootCompleted() {
- auto check = CheckCallerSystemOrRoot("markBootCompleted");
- if (!check.isOk()) {
- return check;
- }
-
::android::apex::OnBootCompleted();
return BinderStatus::ok();
}
@@ -264,15 +231,15 @@
BinderStatus ApexService::calculateSizeForCompressedApex(
const CompressedApexInfoList& compressed_apex_info_list,
int64_t* required_size) {
- std::vector<std::tuple<std::string, int64_t, int64_t>> compressed_apexes;
- compressed_apexes.reserve(compressed_apex_info_list.apexInfos.size());
- for (const auto& apex_info : compressed_apex_info_list.apexInfos) {
- compressed_apexes.emplace_back(apex_info.moduleName, apex_info.versionCode,
- apex_info.decompressedSize);
- }
+ *required_size = 0;
const auto& instance = ApexFileRepository::GetInstance();
- *required_size = ::android::apex::CalculateSizeForCompressedApex(
- compressed_apexes, instance);
+ for (const auto& apex_info : compressed_apex_info_list.apexInfos) {
+ auto should_allocate_space = ShouldAllocateSpaceForDecompression(
+ apex_info.moduleName, apex_info.versionCode, instance);
+ if (!should_allocate_space.ok() || *should_allocate_space) {
+ *required_size += apex_info.decompressedSize;
+ }
+ }
return BinderStatus::ok();
}
@@ -359,19 +326,8 @@
Result<std::string> preinstalled_path =
instance.GetPreinstalledPath(package.GetManifest().name());
if (preinstalled_path.ok()) {
- // We replace the preinstalled paths for block devices to /system/apex
- // because PackageManager will not resolve them if they aren't in one of
- // the SYSTEM_PARTITIONS defined in PackagePartitions.java.
- // b/195363518 for more context.
- const std::string block_path = "/dev/block/";
- const std::string sys_apex_path =
- std::string(kApexPackageSystemDir) + "/" +
- preinstalled_path->substr(block_path.length());
- out.preinstalledModulePath = preinstalled_path->starts_with(block_path)
- ? sys_apex_path
- : *preinstalled_path;
+ out.preinstalledModulePath = *preinstalled_path;
}
- out.activeApexChanged = ::android::apex::IsActiveApexChanged(package);
return out;
}
@@ -389,11 +345,6 @@
BinderStatus ApexService::getSessions(
std::vector<ApexSessionInfo>* aidl_return) {
- auto check = CheckCallerSystemOrRoot("getSessions");
- if (!check.isOk()) {
- return check;
- }
-
auto sessions = ApexSession::GetSessions();
for (const auto& session : sessions) {
ApexSessionInfo session_info;
@@ -406,11 +357,6 @@
BinderStatus ApexService::getStagedSessionInfo(
int session_id, ApexSessionInfo* apex_session_info) {
- auto check = CheckCallerSystemOrRoot("getStagedSessionInfo");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "getStagedSessionInfo() received by ApexService, session id "
<< session_id;
auto session = ApexSession::GetSession(session_id);
@@ -426,45 +372,50 @@
return BinderStatus::ok();
}
-BinderStatus ApexService::getStagedApexInfos(
- const ApexSessionParams& params, std::vector<ApexInfo>* aidl_return) {
- auto check = CheckCallerSystemOrRoot("getStagedApexInfos");
- if (!check.isOk()) {
- return check;
+BinderStatus ApexService::activatePackage(const std::string& package_path) {
+ BinderStatus debug_check = CheckDebuggable("activatePackage");
+ if (!debug_check.isOk()) {
+ return debug_check;
}
- LOG(DEBUG) << "getStagedApexInfos() received by ApexService, session id "
- << params.sessionId << " child sessions: ["
- << android::base::Join(params.childSessionIds, ',') << "]";
- Result<std::vector<ApexFile>> files = ::android::apex::GetStagedApexFiles(
- params.sessionId, params.childSessionIds);
- if (!files.ok()) {
- LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
- << ": " << files.error();
- return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
- String8(files.error().message().c_str()));
+ LOG(DEBUG) << "activatePackage() received by ApexService, path "
+ << package_path;
+
+ Result<void> res = ::android::apex::ActivatePackage(package_path);
+
+ if (res.ok()) {
+ return BinderStatus::ok();
}
- // Retrieve classpath information
- auto class_path = ::android::apex::MountAndDeriveClassPath(*files);
- for (const auto& apex_file : *files) {
- ApexInfo apex_info = GetApexInfo(apex_file);
- auto package_name = apex_info.moduleName;
- apex_info.hasClassPathJars = class_path->HasClassPathJars(package_name);
- aidl_return->push_back(std::move(apex_info));
+ LOG(ERROR) << "Failed to activate " << package_path << ": " << res.error();
+ return BinderStatus::fromExceptionCode(
+ BinderStatus::EX_SERVICE_SPECIFIC,
+ String8(res.error().message().c_str()));
+}
+
+BinderStatus ApexService::deactivatePackage(const std::string& package_path) {
+ BinderStatus debug_check = CheckDebuggable("deactivatePackage");
+ if (!debug_check.isOk()) {
+ return debug_check;
}
- return BinderStatus::ok();
+ LOG(DEBUG) << "deactivatePackage() received by ApexService, path "
+ << package_path;
+
+ Result<void> res = ::android::apex::DeactivatePackage(package_path);
+
+ if (res.ok()) {
+ return BinderStatus::ok();
+ }
+
+ LOG(ERROR) << "Failed to deactivate " << package_path << ": " << res.error();
+ return BinderStatus::fromExceptionCode(
+ BinderStatus::EX_SERVICE_SPECIFIC,
+ String8(res.error().message().c_str()));
}
BinderStatus ApexService::getActivePackages(
std::vector<ApexInfo>* aidl_return) {
- auto check = CheckCallerSystemOrRoot("getActivePackages");
- if (!check.isOk()) {
- return check;
- }
-
auto packages = ::android::apex::GetActivePackages();
for (const auto& package : packages) {
ApexInfo apex_info = GetApexInfo(package);
@@ -477,11 +428,6 @@
BinderStatus ApexService::getActivePackage(const std::string& package_name,
ApexInfo* aidl_return) {
- auto check = CheckCallerSystemOrRoot("getActivePackage");
- if (!check.isOk()) {
- return check;
- }
-
Result<ApexFile> apex = ::android::apex::GetActivePackage(package_name);
if (apex.ok()) {
*aidl_return = GetApexInfo(*apex);
@@ -491,11 +437,6 @@
}
BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
- auto check = CheckCallerSystemOrRoot("getAllPackages");
- if (!check.isOk()) {
- return check;
- }
-
const auto& active = ::android::apex::GetActivePackages();
const auto& factory = ::android::apex::GetFactoryPackages();
for (const ApexFile& pkg : active) {
@@ -516,11 +457,6 @@
BinderStatus ApexService::installAndActivatePackage(
const std::string& package_path, ApexInfo* aidl_return) {
- auto check = CheckCallerSystemOrRoot("installAndActivatePackage");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "installAndActivatePackage() received by ApexService, path: "
<< package_path;
auto res = InstallPackage(package_path);
@@ -536,12 +472,45 @@
return BinderStatus::ok();
}
-BinderStatus ApexService::abortStagedSession(int session_id) {
- auto check = CheckCallerSystemOrRoot("abortStagedSession");
- if (!check.isOk()) {
- return check;
+BinderStatus ApexService::preinstallPackages(
+ const std::vector<std::string>& paths) {
+ BinderStatus debug_check = CheckDebuggable("preinstallPackages");
+ if (!debug_check.isOk()) {
+ return debug_check;
}
+ Result<void> res = ::android::apex::PreinstallPackages(paths);
+ if (res.ok()) {
+ return BinderStatus::ok();
+ }
+
+ LOG(ERROR) << "Failed to preinstall packages "
+ << android::base::Join(paths, ',') << ": " << res.error();
+ return BinderStatus::fromExceptionCode(
+ BinderStatus::EX_SERVICE_SPECIFIC,
+ String8(res.error().message().c_str()));
+}
+
+BinderStatus ApexService::postinstallPackages(
+ const std::vector<std::string>& paths) {
+ BinderStatus debug_check = CheckDebuggable("postinstallPackages");
+ if (!debug_check.isOk()) {
+ return debug_check;
+ }
+
+ Result<void> res = ::android::apex::PostinstallPackages(paths);
+ if (res.ok()) {
+ return BinderStatus::ok();
+ }
+
+ LOG(ERROR) << "Failed to postinstall packages "
+ << android::base::Join(paths, ',') << ": " << res.error();
+ return BinderStatus::fromExceptionCode(
+ BinderStatus::EX_SERVICE_SPECIFIC,
+ String8(res.error().message().c_str()));
+}
+
+BinderStatus ApexService::abortStagedSession(int session_id) {
LOG(DEBUG) << "abortStagedSession() received by ApexService.";
Result<void> res = ::android::apex::AbortStagedSession(session_id);
if (!res.ok()) {
@@ -553,11 +522,6 @@
}
BinderStatus ApexService::revertActiveSessions() {
- auto check = CheckCallerSystemOrRoot("revertActiveSessions");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "revertActiveSessions() received by ApexService.";
Result<void> res = ::android::apex::RevertActiveSessions("", "");
if (!res.ok()) {
@@ -574,11 +538,6 @@
return debug_check;
}
- auto root_check = CheckCallerIsRoot("resumeRevertIfNeeded");
- if (!root_check.isOk()) {
- return root_check;
- }
-
LOG(DEBUG) << "resumeRevertIfNeeded() received by ApexService.";
Result<void> res = ::android::apex::ResumeRevertIfNeeded();
if (!res.ok()) {
@@ -591,11 +550,6 @@
BinderStatus ApexService::snapshotCeData(int user_id, int rollback_id,
const std::string& apex_name) {
- auto check = CheckCallerSystemOrRoot("snapshotCeData");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "snapshotCeData() received by ApexService.";
Result<void> res =
::android::apex::SnapshotCeData(user_id, rollback_id, apex_name);
@@ -609,11 +563,6 @@
BinderStatus ApexService::restoreCeData(int user_id, int rollback_id,
const std::string& apex_name) {
- auto check = CheckCallerSystemOrRoot("restoreCeData");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "restoreCeData() received by ApexService.";
Result<void> res =
::android::apex::RestoreCeData(user_id, rollback_id, apex_name);
@@ -626,11 +575,6 @@
}
BinderStatus ApexService::destroyDeSnapshots(int rollback_id) {
- auto check = CheckCallerSystemOrRoot("destroyDeSnapshots");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "destroyDeSnapshots() received by ApexService.";
Result<void> res = ::android::apex::DestroyDeSnapshots(rollback_id);
if (!res.ok()) {
@@ -642,11 +586,6 @@
}
BinderStatus ApexService::destroyCeSnapshots(int user_id, int rollback_id) {
- auto check = CheckCallerSystemOrRoot("destroyCeSnapshots");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "destroyCeSnapshots() received by ApexService.";
Result<void> res = ::android::apex::DestroyCeSnapshots(user_id, rollback_id);
if (!res.ok()) {
@@ -659,11 +598,6 @@
BinderStatus ApexService::destroyCeSnapshotsNotSpecified(
int user_id, const std::vector<int>& retain_rollback_ids) {
- auto check = CheckCallerSystemOrRoot("destroyCeSnapshotsNotSpecified");
- if (!check.isOk()) {
- return check;
- }
-
LOG(DEBUG) << "destroyCeSnapshotsNotSpecified() received by ApexService.";
Result<void> res = ::android::apex::DestroyCeSnapshotsNotSpecified(
user_id, retain_rollback_ids);
@@ -837,6 +771,12 @@
<< " deactivatePackage [package_path] - deactivate package from the "
"given path"
<< std::endl
+ << " preinstallPackages [package_path1] ([package_path2]...) - run "
+ "pre-install hooks of the given packages"
+ << std::endl
+ << " postinstallPackages [package_path1] ([package_path2]...) - run "
+ "post-install hooks of the given packages"
+ << std::endl
<< " getStagedSessionInfo [sessionId] - displays information about a "
"given session previously submitted"
<< std::endl
@@ -950,13 +890,12 @@
print_help(err, "activatePackage requires one package_path");
return BAD_VALUE;
}
- std::string path = String8(args[1]).string();
- auto status = ::android::apex::ActivatePackage(path);
- if (status.ok()) {
+ BinderStatus status = activatePackage(String8(args[1]).string());
+ if (status.isOk()) {
return OK;
}
std::string msg = StringLog() << "Failed to activate package: "
- << status.error().message() << std::endl;
+ << status.toString8().string() << std::endl;
dprintf(err, "%s", msg.c_str());
return BAD_VALUE;
}
@@ -966,13 +905,12 @@
print_help(err, "deactivatePackage requires one package_path");
return BAD_VALUE;
}
- std::string path = String8(args[1]).string();
- auto status = ::android::apex::DeactivatePackage(path);
- if (status.ok()) {
+ BinderStatus status = deactivatePackage(String8(args[1]).string());
+ if (status.isOk()) {
return OK;
}
std::string msg = StringLog() << "Failed to deactivate package: "
- << status.error().message() << std::endl;
+ << status.toString8().string() << std::endl;
dprintf(err, "%s", msg.c_str());
return BAD_VALUE;
}
@@ -1048,6 +986,31 @@
return BAD_VALUE;
}
+ if (cmd == String16("preinstallPackages") ||
+ cmd == String16("postinstallPackages")) {
+ if (args.size() < 2) {
+ print_help(err,
+ "preinstallPackages/postinstallPackages requires at least"
+ " one package_path");
+ return BAD_VALUE;
+ }
+ std::vector<std::string> pkgs;
+ pkgs.reserve(args.size() - 1);
+ for (size_t i = 1; i != args.size(); ++i) {
+ pkgs.emplace_back(String8(args[i]).string());
+ }
+ BinderStatus status = cmd == String16("preinstallPackages")
+ ? preinstallPackages(pkgs)
+ : postinstallPackages(pkgs);
+ if (status.isOk()) {
+ return OK;
+ }
+ std::string msg = StringLog() << "Failed to pre/postinstall package(s): "
+ << status.toString8().string() << std::endl;
+ dprintf(err, "%s", msg.c_str());
+ return BAD_VALUE;
+ }
+
if (cmd == String16("remountPackages")) {
BinderStatus status = remountPackages();
if (status.isOk()) {
diff --git a/apexd/apexservice_test.cpp b/apexd/apexservice_test.cpp
index 29cf1d7..545bb38 100644
--- a/apexd/apexservice_test.cpp
+++ b/apexd/apexservice_test.cpp
@@ -14,31 +14,6 @@
* limitations under the License.
*/
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/properties.h>
-#include <android-base/scopeguard.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android/apex/ApexInfo.h>
-#include <android/apex/IApexService.h>
-#include <android/os/IVold.h>
-#include <binder/IServiceManager.h>
-#include <fs_mgr_overlayfs.h>
-#include <fstab/fstab.h>
-#include <gmock/gmock.h>
-#include <grp.h>
-#include <gtest/gtest.h>
-#include <libdm/dm.h>
-#include <linux/loop.h>
-#include <selinux/selinux.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/xattr.h>
-
#include <algorithm>
#include <filesystem>
#include <fstream>
@@ -49,6 +24,32 @@
#include <unordered_set>
#include <vector>
+#include <grp.h>
+#include <linux/loop.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android/os/IVold.h>
+#include <binder/IServiceManager.h>
+#include <fs_mgr_overlayfs.h>
+#include <fstab/fstab.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <libdm/dm.h>
+#include <selinux/selinux.h>
+
+#include <android/apex/ApexInfo.h>
+#include <android/apex/IApexService.h>
+
#include "apex_constants.h"
#include "apex_database.h"
#include "apex_file.h"
@@ -68,21 +69,25 @@
using android::sp;
using android::String16;
+using android::apex::testing::ApexInfoEq;
using android::apex::testing::CreateSessionInfo;
using android::apex::testing::IsOk;
using android::apex::testing::SessionInfoEq;
using android::base::EndsWith;
-using android::base::Error;
+using android::base::ErrnoError;
using android::base::Join;
-using android::base::Result;
-using android::base::SetProperty;
+using android::base::ReadFully;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
using android::dm::DeviceMapper;
+using android::fs_mgr::Fstab;
+using android::fs_mgr::GetEntryForMountPoint;
+using android::fs_mgr::ReadFstabFromFile;
using ::apex::proto::ApexManifest;
-using ::apex::proto::SessionState;
+using ::testing::Contains;
using ::testing::EndsWith;
+using ::testing::HasSubstr;
using ::testing::Not;
using ::testing::SizeIs;
using ::testing::UnorderedElementsAre;
@@ -94,18 +99,7 @@
class ApexServiceTest : public ::testing::Test {
public:
- ApexServiceTest() {}
-
- protected:
- void SetUp() override {
- // TODO(b/136647373): Move this check to environment setup
- if (!android::base::GetBoolProperty("ro.apex.updatable", false)) {
- GTEST_SKIP() << "Skipping test because device doesn't support APEX";
- }
-
- // Enable VERBOSE logging to simplifying debugging
- SetProperty("log.tag.apexd", "VERBOSE");
-
+ ApexServiceTest() {
using android::IBinder;
using android::IServiceManager;
@@ -118,7 +112,14 @@
if (binder != nullptr) {
vold_service_ = android::interface_cast<android::os::IVold>(binder);
}
+ }
+ protected:
+ void SetUp() override {
+ // TODO(b/136647373): Move this check to environment setup
+ if (!android::base::GetBoolProperty("ro.apex.updatable", false)) {
+ GTEST_SKIP() << "Skipping test because device doesn't support APEX";
+ }
ASSERT_NE(nullptr, service_.get());
ASSERT_NE(nullptr, vold_service_.get());
android::binder::Status status =
@@ -141,6 +142,37 @@
static bool IsSelinuxEnforced() { return 0 != security_getenforce(); }
+ Result<bool> IsActive(const std::string& name) {
+ std::vector<ApexInfo> list;
+ android::binder::Status status = service_->getActivePackages(&list);
+ if (!status.isOk()) {
+ return Error() << "Failed to check if " << name
+ << " is active : " << status.exceptionMessage().c_str();
+ }
+ for (const ApexInfo& apex : list) {
+ if (apex.moduleName == name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Result<bool> IsActive(const std::string& name, int64_t version,
+ const std::string& path) {
+ std::vector<ApexInfo> list;
+ android::binder::Status status = service_->getActivePackages(&list);
+ if (status.isOk()) {
+ for (const ApexInfo& p : list) {
+ if (p.moduleName == name && p.versionCode == version &&
+ p.modulePath == path) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return Error() << status.exceptionMessage().c_str();
+ }
+
Result<std::vector<ApexInfo>> GetAllPackages() {
std::vector<ApexInfo> list;
android::binder::Status status = service_->getAllPackages(&list);
@@ -175,6 +207,16 @@
return Error() << status.toString8().c_str();
}
+ Result<ApexInfo> GetActivePackage(const std::string& name) {
+ ApexInfo package;
+ android::binder::Status status = service_->getActivePackage(name, &package);
+ if (status.isOk()) {
+ return package;
+ }
+
+ return Error() << status.exceptionMessage().c_str();
+ }
+
std::string GetPackageString(const ApexInfo& p) {
return p.moduleName + "@" + std::to_string(p.versionCode) +
" [path=" + p.moduleName + "]";
@@ -249,6 +291,26 @@
return ret;
}
+ static std::string GetLogcat() {
+ // For simplicity, log to file and read it.
+ std::string file = GetTestFile("logcat.tmp.txt");
+ std::vector<std::string> args{
+ "/system/bin/logcat",
+ "-d",
+ "-f",
+ file,
+ };
+ auto res = ForkAndRun(args);
+ CHECK(res.ok()) << res.error();
+
+ std::string data;
+ CHECK(android::base::ReadFileToString(file, &data));
+
+ unlink(file.c_str());
+
+ return data;
+ }
+
static void DeleteIfExists(const std::string& path) {
if (fs::exists(path)) {
std::error_code ec;
@@ -433,46 +495,83 @@
ofs.close();
}
-void CreateFileWithExpectedProperties(const std::string& path) {
- CreateFile(path);
- std::error_code ec;
- fs::permissions(
- path,
- fs::perms::owner_read | fs::perms::group_write | fs::perms::others_exec,
- fs::perm_options::replace, ec);
- ASSERT_FALSE(ec) << "Failed to set permissions: " << ec.message();
- ASSERT_EQ(0, chown(path.c_str(), 1007 /* log */, 3001 /* net_bt_admin */))
- << "chown failed: " << strerror(errno);
- ASSERT_TRUE(RegularFileExists(path));
- char buf[65536]; // 64kB is max possible xattr list size. See "man 7 xattr".
- ASSERT_EQ(0, setxattr(path.c_str(), "user.foo", "bar", 4, 0));
- ASSERT_GE(listxattr(path.c_str(), buf, sizeof(buf)), 9);
- ASSERT_TRUE(memmem(buf, sizeof(buf), "user.foo", 9) != nullptr);
- ASSERT_EQ(4, getxattr(path.c_str(), "user.foo", buf, sizeof(buf)));
- ASSERT_STREQ("bar", buf);
-}
-
-void ExpectFileWithExpectedProperties(const std::string& path) {
- EXPECT_TRUE(RegularFileExists(path));
- EXPECT_EQ(fs::status(path).permissions(), fs::perms::owner_read |
- fs::perms::group_write |
- fs::perms::others_exec);
- struct stat sd;
- ASSERT_EQ(0, stat(path.c_str(), &sd));
- EXPECT_EQ(1007u, sd.st_uid);
- EXPECT_EQ(3001u, sd.st_gid);
- char buf[65536]; // 64kB is max possible xattr list size. See "man 7 xattr".
- EXPECT_GE(listxattr(path.c_str(), buf, sizeof(buf)), 9);
- EXPECT_TRUE(memmem(buf, sizeof(buf), "user.foo", 9) != nullptr);
- EXPECT_EQ(4, getxattr(path.c_str(), "user.foo", buf, sizeof(buf)));
- EXPECT_STREQ("bar", buf);
-}
-
Result<std::vector<std::string>> ReadEntireDir(const std::string& path) {
static const auto kAcceptAll = [](auto /*entry*/) { return true; };
return ReadDir(path, kAcceptAll);
}
+Result<std::string> GetBlockDeviceForApex(const std::string& package_id) {
+ std::string mount_point = std::string(kApexRoot) + "/" + package_id;
+ Fstab fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+ return Error() << "Failed to read /proc/mounts";
+ }
+ auto entry = GetEntryForMountPoint(&fstab, mount_point);
+ if (entry == nullptr) {
+ return Error() << "Can't find " << mount_point << " in /proc/mounts";
+ }
+ return entry->blk_device;
+}
+
+Result<void> ReadDevice(const std::string& block_device) {
+ static constexpr int kBlockSize = 4096;
+ static constexpr size_t kBufSize = 1024 * kBlockSize;
+ std::vector<uint8_t> buffer(kBufSize);
+
+ unique_fd fd(
+ TEMP_FAILURE_RETRY(open(block_device.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd.get() == -1) {
+ return ErrnoError() << "Can't open " << block_device;
+ }
+
+ while (true) {
+ int n = read(fd.get(), buffer.data(), kBufSize);
+ if (n < 0) {
+ return ErrnoError() << "Failed to read " << block_device;
+ }
+ if (n == 0) {
+ break;
+ }
+ }
+ return {};
+}
+
+std::vector<std::string> ListSlavesOfDmDevice(const std::string& name) {
+ DeviceMapper& dm = DeviceMapper::Instance();
+ std::string dm_path;
+ EXPECT_TRUE(dm.GetDmDevicePathByName(name, &dm_path))
+ << "Failed to get path of dm device " << name;
+ // It's a little bit sad we can't use ConsumePrefix here :(
+ constexpr std::string_view kDevPrefix = "/dev/";
+ EXPECT_TRUE(StartsWith(dm_path, kDevPrefix)) << "Illegal path " << dm_path;
+ dm_path = dm_path.substr(kDevPrefix.length());
+ std::vector<std::string> slaves;
+ {
+ std::string slaves_dir = "/sys/" + dm_path + "/slaves";
+ auto st = WalkDir(slaves_dir, [&](const auto& entry) {
+ std::error_code ec;
+ if (entry.is_symlink(ec)) {
+ slaves.push_back("/dev/block/" + entry.path().filename().string());
+ }
+ if (ec) {
+ ADD_FAILURE() << "Failed to scan " << slaves_dir << " : " << ec;
+ }
+ });
+ EXPECT_TRUE(IsOk(st));
+ }
+ return slaves;
+}
+
+Result<void> CopyFile(const std::string& from, const std::string& to,
+ const fs::copy_options& options) {
+ std::error_code ec;
+ if (!fs::copy_file(from, to, options)) {
+ return Error() << "Failed to copy file " << from << " to " << to << " : "
+ << ec.message();
+ }
+ return {};
+}
+
} // namespace
TEST_F(ApexServiceTest, HaveSelinux) {
@@ -491,6 +590,66 @@
EXPECT_TRUE(IsSelinuxEnforced() || kIsX86);
}
+TEST_F(ApexServiceTest, StageFailAccess) {
+ if (!IsSelinuxEnforced()) {
+ LOG(WARNING) << "Skipping InstallFailAccess because of selinux";
+ return;
+ }
+
+ // Use an extra copy, so that even if this test fails (incorrectly installs),
+ // we have the testdata file still around.
+ std::string orig_test_file = GetTestFile("apex.apexd_test.apex");
+ std::string test_file = orig_test_file + ".2";
+ ASSERT_EQ(0, link(orig_test_file.c_str(), test_file.c_str()))
+ << strerror(errno);
+ struct Deleter {
+ std::string to_delete;
+ explicit Deleter(std::string t) : to_delete(std::move(t)) {}
+ ~Deleter() {
+ if (unlink(to_delete.c_str()) != 0) {
+ PLOG(ERROR) << "Could not unlink " << to_delete;
+ }
+ }
+ };
+ Deleter del(test_file);
+
+ android::binder::Status st = service_->stagePackages({test_file});
+ ASSERT_FALSE(IsOk(st));
+ std::string error = st.exceptionMessage().c_str();
+ EXPECT_NE(std::string::npos, error.find("Failed to open package")) << error;
+ EXPECT_NE(std::string::npos, error.find("I/O error")) << error;
+}
+
+TEST_F(ApexServiceTest, StageFailKey) {
+ PrepareTestApexForInstall installer(
+ GetTestFile("apex.apexd_test_no_inst_key.apex"));
+ if (!installer.Prepare()) {
+ return;
+ }
+ ASSERT_EQ(std::string("com.android.apex.test_package.no_inst_key"),
+ installer.package);
+
+ android::binder::Status st = service_->stagePackages({installer.test_file});
+ ASSERT_FALSE(IsOk(st));
+
+ // May contain one of two errors.
+ std::string error = st.exceptionMessage().c_str();
+
+ ASSERT_THAT(error, HasSubstr("No preinstalled apex found for package "
+ "com.android.apex.test_package.no_inst_key"));
+}
+
+TEST_F(ApexServiceTest, StageSuccess) {
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
+ if (!installer.Prepare()) {
+ return;
+ }
+ ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
+
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ EXPECT_TRUE(RegularFileExists(installer.test_installed_file));
+}
+
TEST_F(ApexServiceTest,
SubmitStagegSessionSuccessDoesNotLeakTempVerityDevices) {
PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
@@ -552,6 +711,85 @@
}
}
+TEST_F(ApexServiceTest, StageSuccessClearsPreviouslyActivePackage) {
+ PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test_v2.apex"));
+ PrepareTestApexForInstall installer2(
+ GetTestFile("apex.apexd_test_different_app.apex"));
+ PrepareTestApexForInstall installer3(GetTestFile("apex.apexd_test.apex"));
+ auto install_fn = [&](PrepareTestApexForInstall& installer) {
+ if (!installer.Prepare()) {
+ return;
+ }
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ EXPECT_TRUE(RegularFileExists(installer.test_installed_file));
+ };
+ install_fn(installer1);
+ install_fn(installer2);
+ // Simulating a revert. After this call test_v2_apex_path should be removed.
+ install_fn(installer3);
+
+ EXPECT_FALSE(RegularFileExists(installer1.test_installed_file));
+ EXPECT_TRUE(RegularFileExists(installer2.test_installed_file));
+ EXPECT_TRUE(RegularFileExists(installer3.test_installed_file));
+}
+
+TEST_F(ApexServiceTest, StageAlreadyStagedPackageSuccess) {
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
+ if (!installer.Prepare()) {
+ return;
+ }
+ ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
+
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ ASSERT_TRUE(RegularFileExists(installer.test_installed_file));
+
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ ASSERT_TRUE(RegularFileExists(installer.test_installed_file));
+}
+
+TEST_F(ApexServiceTest, StageAlreadyStagedPackageSuccessNewWins) {
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
+ PrepareTestApexForInstall installer2(
+ GetTestFile("apex.apexd_test_nocode.apex"));
+ if (!installer.Prepare() || !installer2.Prepare()) {
+ return;
+ }
+ ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
+ ASSERT_EQ(installer.test_installed_file, installer2.test_installed_file);
+
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ const auto& apex = ApexFile::Open(installer.test_installed_file);
+ ASSERT_TRUE(IsOk(apex));
+ ASSERT_FALSE(apex->GetManifest().nocode());
+
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer2.test_file})));
+ const auto& new_apex = ApexFile::Open(installer.test_installed_file);
+ ASSERT_TRUE(IsOk(new_apex));
+ ASSERT_TRUE(new_apex->GetManifest().nocode());
+}
+
+TEST_F(ApexServiceTest, MultiStageSuccess) {
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"));
+ if (!installer.Prepare()) {
+ return;
+ }
+ ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
+
+ PrepareTestApexForInstall installer2(GetTestFile("apex.apexd_test_v2.apex"));
+ if (!installer2.Prepare()) {
+ return;
+ }
+ ASSERT_EQ(std::string("com.android.apex.test_package"), installer2.package);
+
+ std::vector<std::string> packages;
+ packages.push_back(installer.test_file);
+ packages.push_back(installer2.test_file);
+
+ ASSERT_TRUE(IsOk(service_->stagePackages(packages)));
+ EXPECT_TRUE(RegularFileExists(installer.test_installed_file));
+ EXPECT_TRUE(RegularFileExists(installer2.test_installed_file));
+}
+
TEST_F(ApexServiceTest, CannotBeRollbackAndHaveRollbackEnabled) {
PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
"/data/app-staging/session_1543",
@@ -589,13 +827,15 @@
TEST_F(ApexServiceTest, SnapshotCeData) {
CreateDir("/data/misc_ce/0/apexdata/apex.apexd_test");
- CreateFileWithExpectedProperties(
- "/data/misc_ce/0/apexdata/apex.apexd_test/hello.txt");
+ CreateFile("/data/misc_ce/0/apexdata/apex.apexd_test/hello.txt");
+
+ ASSERT_TRUE(
+ RegularFileExists("/data/misc_ce/0/apexdata/apex.apexd_test/hello.txt"));
service_->snapshotCeData(0, 123456, "apex.apexd_test");
- ExpectFileWithExpectedProperties(
- "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/hello.txt");
+ ASSERT_TRUE(RegularFileExists(
+ "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/hello.txt"));
}
TEST_F(ApexServiceTest, RestoreCeData) {
@@ -604,22 +844,21 @@
CreateDir("/data/misc_ce/0/apexrollback/123456/apex.apexd_test");
CreateFile("/data/misc_ce/0/apexdata/apex.apexd_test/newfile.txt");
- CreateFileWithExpectedProperties(
- "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/oldfile.txt");
+ CreateFile("/data/misc_ce/0/apexrollback/123456/apex.apexd_test/oldfile.txt");
ASSERT_TRUE(RegularFileExists(
"/data/misc_ce/0/apexdata/apex.apexd_test/newfile.txt"));
- ExpectFileWithExpectedProperties(
- "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/oldfile.txt");
+ ASSERT_TRUE(RegularFileExists(
+ "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/oldfile.txt"));
service_->restoreCeData(0, 123456, "apex.apexd_test");
- ExpectFileWithExpectedProperties(
- "/data/misc_ce/0/apexdata/apex.apexd_test/oldfile.txt");
- EXPECT_FALSE(RegularFileExists(
+ ASSERT_TRUE(RegularFileExists(
+ "/data/misc_ce/0/apexdata/apex.apexd_test/oldfile.txt"));
+ ASSERT_FALSE(RegularFileExists(
"/data/misc_ce/0/apexdata/apex.apexd_test/newfile.txt"));
// The snapshot should be deleted after restoration.
- EXPECT_FALSE(
+ ASSERT_FALSE(
DirExists("/data/misc_ce/0/apexrollback/123456/apex.apexd_test"));
}
@@ -740,6 +979,441 @@
}
}
+template <typename NameProvider>
+class ApexServiceActivationTest : public ApexServiceTest {
+ public:
+ ApexServiceActivationTest() : stage_package(true) {}
+
+ explicit ApexServiceActivationTest(bool stage_package)
+ : stage_package(stage_package) {}
+
+ void SetUp() override {
+ // TODO(b/136647373): Move this check to environment setup
+ if (!android::base::GetBoolProperty("ro.apex.updatable", false)) {
+ GTEST_SKIP() << "Skipping test because device doesn't support APEX";
+ }
+ ApexServiceTest::SetUp();
+ ASSERT_NE(nullptr, service_.get());
+
+ installer_ = std::make_unique<PrepareTestApexForInstall>(
+ GetTestFile(NameProvider::GetTestName()));
+ if (!installer_->Prepare()) {
+ return;
+ }
+ ASSERT_EQ(NameProvider::GetPackageName(), installer_->package);
+
+ {
+ // Check package is not active.
+ std::string path = stage_package ? installer_->test_installed_file
+ : installer_->test_file;
+ Result<bool> active =
+ IsActive(installer_->package, installer_->version, path);
+ ASSERT_TRUE(IsOk(active));
+ ASSERT_FALSE(*active);
+ }
+
+ if (stage_package) {
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer_->test_file})));
+ }
+ }
+
+ void TearDown() override {
+ // Attempt to deactivate.
+ if (installer_ != nullptr) {
+ if (stage_package) {
+ service_->deactivatePackage(installer_->test_installed_file);
+ } else {
+ service_->deactivatePackage(installer_->test_file);
+ }
+ }
+
+ installer_.reset();
+ // ApexServiceTest::TearDown will wipe out everything under /data/apex.
+ // Since some of that information is required for deactivatePackage binder
+ // call, it's required to be called after deactivating package.
+ ApexServiceTest::TearDown();
+ }
+
+ std::unique_ptr<PrepareTestApexForInstall> installer_;
+
+ private:
+ bool stage_package;
+};
+
+struct SuccessNameProvider {
+ static std::string GetTestName() { return "apex.apexd_test.apex"; }
+ static std::string GetPackageName() {
+ return "com.android.apex.test_package";
+ }
+};
+
+struct ManifestMismatchNameProvider {
+ static std::string GetTestName() {
+ return "apex.apexd_test_manifest_mismatch.apex";
+ }
+ static std::string GetPackageName() {
+ return "com.android.apex.test_package";
+ }
+};
+
+class ApexServiceActivationManifestMismatchFailure
+ : public ApexServiceActivationTest<ManifestMismatchNameProvider> {
+ public:
+ ApexServiceActivationManifestMismatchFailure()
+ : ApexServiceActivationTest(false) {}
+};
+
+TEST_F(ApexServiceActivationManifestMismatchFailure,
+ ActivateFailsWithManifestMismatch) {
+ android::binder::Status st = service_->activatePackage(installer_->test_file);
+ ASSERT_FALSE(IsOk(st));
+
+ std::string error = st.exceptionMessage().c_str();
+ ASSERT_THAT(
+ error,
+ HasSubstr(
+ "Manifest inside filesystem does not match manifest outside it"));
+}
+
+class ApexServiceActivationSuccessTest
+ : public ApexServiceActivationTest<SuccessNameProvider> {};
+
+TEST_F(ApexServiceActivationSuccessTest, Activate) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ {
+ // Check package is active.
+ Result<bool> active = IsActive(installer_->package, installer_->version,
+ installer_->test_installed_file);
+ ASSERT_TRUE(IsOk(active));
+ ASSERT_TRUE(*active) << Join(GetActivePackagesStrings(), ',');
+ }
+
+ {
+ // Check that the "latest" view exists.
+ std::string latest_path =
+ std::string(kApexRoot) + "/" + installer_->package;
+ struct stat buf;
+ ASSERT_EQ(0, stat(latest_path.c_str(), &buf)) << strerror(errno);
+ // Check that it is a folder.
+ EXPECT_TRUE(S_ISDIR(buf.st_mode));
+
+ // Collect direct entries of a folder.
+ auto collect_entries_fn = [&](const std::string& path) {
+ std::vector<std::string> ret;
+ auto status = WalkDir(path, [&](const fs::directory_entry& entry) {
+ if (!entry.is_directory()) {
+ return;
+ }
+ ret.emplace_back(entry.path().filename());
+ });
+ CHECK(status.has_value())
+ << "Failed to list " << path << " : " << status.error();
+ std::sort(ret.begin(), ret.end());
+ return ret;
+ };
+
+ std::string versioned_path = std::string(kApexRoot) + "/" +
+ installer_->package + "@" +
+ std::to_string(installer_->version);
+ std::vector<std::string> versioned_folder_entries =
+ collect_entries_fn(versioned_path);
+ std::vector<std::string> latest_folder_entries =
+ collect_entries_fn(latest_path);
+
+ EXPECT_TRUE(versioned_folder_entries == latest_folder_entries)
+ << "Versioned: " << Join(versioned_folder_entries, ',')
+ << " Latest: " << Join(latest_folder_entries, ',');
+ }
+}
+
+TEST_F(ApexServiceActivationSuccessTest, GetActivePackages) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ Result<std::vector<ApexInfo>> active = GetActivePackages();
+ ASSERT_TRUE(IsOk(active));
+ ApexInfo match;
+
+ for (const ApexInfo& info : *active) {
+ if (info.moduleName == installer_->package) {
+ match = info;
+ break;
+ }
+ }
+
+ ASSERT_EQ(installer_->package, match.moduleName);
+ ASSERT_EQ(installer_->version, static_cast<uint64_t>(match.versionCode));
+ ASSERT_EQ(installer_->test_installed_file, match.modulePath);
+}
+
+TEST_F(ApexServiceActivationSuccessTest, GetActivePackage) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ Result<ApexInfo> active = GetActivePackage(installer_->package);
+ ASSERT_TRUE(IsOk(active));
+
+ ASSERT_EQ(installer_->package, active->moduleName);
+ ASSERT_EQ(installer_->version, static_cast<uint64_t>(active->versionCode));
+ ASSERT_EQ(installer_->test_installed_file, active->modulePath);
+}
+
+TEST_F(ApexServiceActivationSuccessTest, ShowsUpInMountedApexDatabase) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ MountedApexDatabase db;
+ db.PopulateFromMounts(kActiveApexPackagesDataDir, kApexDecompressedDir,
+ kApexHashTreeDir);
+
+ std::optional<MountedApexData> mounted_apex;
+ db.ForallMountedApexes(installer_->package,
+ [&](const MountedApexData& d, bool active) {
+ if (active) {
+ mounted_apex.emplace(d);
+ }
+ });
+ ASSERT_TRUE(mounted_apex)
+ << "Haven't found " << installer_->test_installed_file
+ << " in the database of mounted apexes";
+
+ // Get all necessary data for assertions on mounted_apex.
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+ DeviceMapper& dm = DeviceMapper::Instance();
+ std::string dm_path;
+ ASSERT_TRUE(dm.GetDmDevicePathByName(package_id, &dm_path))
+ << "Failed to get path of dm device " << package_id;
+ auto loop_device = dm.GetParentBlockDeviceByPath(dm_path);
+ ASSERT_TRUE(loop_device) << "Failed to find parent block device of "
+ << dm_path;
+
+ // Now we are ready to assert on mounted_apex.
+ ASSERT_EQ(*loop_device, mounted_apex->loop_name);
+ ASSERT_EQ(installer_->test_installed_file, mounted_apex->full_path);
+ std::string expected_mount = std::string(kApexRoot) + "/" + package_id;
+ ASSERT_EQ(expected_mount, mounted_apex->mount_point);
+ ASSERT_EQ(package_id, mounted_apex->device_name);
+ ASSERT_EQ("", mounted_apex->hashtree_loop_name);
+}
+
+struct NoHashtreeApexNameProvider {
+ static std::string GetTestName() {
+ return "apex.apexd_test_no_hashtree.apex";
+ }
+ static std::string GetPackageName() {
+ return "com.android.apex.test_package";
+ }
+};
+
+class ApexServiceNoHashtreeApexActivationTest
+ : public ApexServiceActivationTest<NoHashtreeApexNameProvider> {};
+
+TEST_F(ApexServiceNoHashtreeApexActivationTest, Activate) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+ {
+ // Check package is active.
+ Result<bool> active = IsActive(installer_->package, installer_->version,
+ installer_->test_installed_file);
+ ASSERT_TRUE(IsOk(active));
+ ASSERT_TRUE(*active) << Join(GetActivePackagesStrings(), ',');
+ }
+
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+ // Check that hashtree file was created.
+ {
+ std::string hashtree_path =
+ std::string(kApexHashTreeDir) + "/" + package_id;
+ auto exists = PathExists(hashtree_path);
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists);
+ }
+
+ // Check that block device can be read.
+ auto block_device = GetBlockDeviceForApex(package_id);
+ ASSERT_TRUE(IsOk(block_device));
+ ASSERT_TRUE(IsOk(ReadDevice(*block_device)));
+}
+
+TEST_F(ApexServiceNoHashtreeApexActivationTest,
+ NewSessionDoesNotImpactActivePackage) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+ {
+ // Check package is active.
+ Result<bool> active = IsActive(installer_->package, installer_->version,
+ installer_->test_installed_file);
+ ASSERT_TRUE(IsOk(active));
+ ASSERT_TRUE(*active) << Join(GetActivePackagesStrings(), ',');
+ }
+
+ PrepareTestApexForInstall installer2(
+ GetTestFile("apex.apexd_test_no_hashtree_2.apex"),
+ "/data/app-staging/session_123", "staging_data_file");
+ if (!installer2.Prepare()) {
+ FAIL();
+ }
+
+ ApexInfoList list;
+ ApexSessionParams params;
+ params.sessionId = 123;
+ ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
+
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+ // Check that new hashtree file was created.
+ {
+ std::string hashtree_path =
+ std::string(kApexHashTreeDir) + "/" + package_id + ".new";
+ auto exists = PathExists(hashtree_path);
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists) << hashtree_path << " does not exist";
+ }
+ // Check that active hashtree is still there.
+ {
+ std::string hashtree_path =
+ std::string(kApexHashTreeDir) + "/" + package_id;
+ auto exists = PathExists(hashtree_path);
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists) << hashtree_path << " does not exist";
+ }
+
+ // Check that block device of active APEX can still be read.
+ auto block_device = GetBlockDeviceForApex(package_id);
+ ASSERT_TRUE(IsOk(block_device));
+}
+
+TEST_F(ApexServiceNoHashtreeApexActivationTest, ShowsUpInMountedApexDatabase) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ MountedApexDatabase db;
+ db.PopulateFromMounts(kActiveApexPackagesDataDir, kApexDecompressedDir,
+ kApexHashTreeDir);
+
+ std::optional<MountedApexData> mounted_apex;
+ db.ForallMountedApexes(installer_->package,
+ [&](const MountedApexData& d, bool active) {
+ if (active) {
+ mounted_apex.emplace(d);
+ }
+ });
+ ASSERT_TRUE(mounted_apex)
+ << "Haven't found " << installer_->test_installed_file
+ << " in the database of mounted apexes";
+
+ // Get all necessary data for assertions on mounted_apex.
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+ std::vector<std::string> slaves = ListSlavesOfDmDevice(package_id);
+ ASSERT_EQ(2u, slaves.size())
+ << "Unexpected number of slaves: " << Join(slaves, ",");
+
+ // Now we are ready to assert on mounted_apex.
+ ASSERT_EQ(installer_->test_installed_file, mounted_apex->full_path);
+ std::string expected_mount = std::string(kApexRoot) + "/" + package_id;
+ ASSERT_EQ(expected_mount, mounted_apex->mount_point);
+ ASSERT_EQ(package_id, mounted_apex->device_name);
+ // For loops we only check that both loop_name and hashtree_loop_name are
+ // slaves of the top device mapper device.
+ ASSERT_THAT(slaves, Contains(mounted_apex->loop_name));
+ ASSERT_THAT(slaves, Contains(mounted_apex->hashtree_loop_name));
+ ASSERT_NE(mounted_apex->loop_name, mounted_apex->hashtree_loop_name);
+}
+
+TEST_F(ApexServiceNoHashtreeApexActivationTest, DeactivateFreesLoopDevices) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+ std::vector<std::string> slaves = ListSlavesOfDmDevice(package_id);
+ ASSERT_EQ(2u, slaves.size())
+ << "Unexpected number of slaves: " << Join(slaves, ",");
+
+ ASSERT_TRUE(
+ IsOk(service_->deactivatePackage(installer_->test_installed_file)));
+
+ for (const auto& loop : slaves) {
+ struct loop_info li;
+ unique_fd fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CLOEXEC)));
+ ASSERT_NE(-1, fd.get())
+ << "Failed to open " << loop << " : " << strerror(errno);
+ ASSERT_EQ(-1, ioctl(fd.get(), LOOP_GET_STATUS, &li))
+ << loop << " is still alive";
+ ASSERT_EQ(ENXIO, errno) << "Unexpected errno : " << strerror(errno);
+ }
+
+ // Skip deactivatePackage on TearDown.
+ installer_.reset();
+}
+
+TEST_F(ApexServiceTest, NoHashtreeApexStagePackagesMovesHashtree) {
+ PrepareTestApexForInstall installer(
+ GetTestFile("apex.apexd_test_no_hashtree.apex"),
+ "/data/app-staging/session_239", "staging_data_file");
+ if (!installer.Prepare()) {
+ FAIL();
+ }
+
+ auto read_fn = [](const std::string& path) -> std::vector<uint8_t> {
+ static constexpr size_t kBufSize = 4096;
+ std::vector<uint8_t> buffer(kBufSize);
+ unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd.get() == -1) {
+ PLOG(ERROR) << "Failed to open " << path;
+ ADD_FAILURE();
+ return buffer;
+ }
+ if (!ReadFully(fd.get(), buffer.data(), kBufSize)) {
+ PLOG(ERROR) << "Failed to read " << path;
+ ADD_FAILURE();
+ }
+ return buffer;
+ };
+
+ ApexInfoList list;
+ ApexSessionParams params;
+ params.sessionId = 239;
+ ASSERT_TRUE(IsOk(service_->submitStagedSession(params, &list)));
+
+ std::string package_id =
+ installer.package + "@" + std::to_string(installer.version);
+ // Check that new hashtree file was created.
+ std::vector<uint8_t> original_hashtree_data;
+ {
+ std::string hashtree_path =
+ std::string(kApexHashTreeDir) + "/" + package_id + ".new";
+ auto exists = PathExists(hashtree_path);
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists);
+ original_hashtree_data = read_fn(hashtree_path);
+ }
+
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ // Check that hashtree file was moved.
+ {
+ std::string hashtree_path =
+ std::string(kApexHashTreeDir) + "/" + package_id + ".new";
+ auto exists = PathExists(hashtree_path);
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_FALSE(*exists);
+ }
+ {
+ std::string hashtree_path =
+ std::string(kApexHashTreeDir) + "/" + package_id;
+ auto exists = PathExists(hashtree_path);
+ ASSERT_TRUE(IsOk(exists));
+ ASSERT_TRUE(*exists);
+ std::vector<uint8_t> moved_hashtree_data = read_fn(hashtree_path);
+ ASSERT_EQ(moved_hashtree_data, original_hashtree_data);
+ }
+}
+
TEST_F(ApexServiceTest, GetFactoryPackages) {
Result<std::vector<ApexInfo>> factory_packages = GetFactoryPackages();
ASSERT_TRUE(IsOk(factory_packages));
@@ -769,7 +1443,7 @@
}
}
-TEST_F(ApexServiceTest, DISABLED_NoPackagesAreBothActiveAndInactive) {
+TEST_F(ApexServiceTest, NoPackagesAreBothActiveAndInactive) {
Result<std::vector<ApexInfo>> active_packages = GetActivePackages();
ASSERT_TRUE(IsOk(active_packages));
ASSERT_TRUE(active_packages->size() > 0);
@@ -789,7 +1463,7 @@
ASSERT_THAT(intersection, SizeIs(0));
}
-TEST_F(ApexServiceTest, DISABLED_GetAllPackages) {
+TEST_F(ApexServiceTest, GetAllPackages) {
Result<std::vector<ApexInfo>> all_packages = GetAllPackages();
ASSERT_TRUE(IsOk(all_packages));
ASSERT_TRUE(all_packages->size() > 0);
@@ -816,6 +1490,247 @@
}
}
+class ApexSameGradeOfPreInstalledVersionTest : public ApexServiceTest {
+ public:
+ void SetUp() override {
+ // TODO(b/136647373): Move this check to environment setup
+ if (!android::base::GetBoolProperty("ro.apex.updatable", false)) {
+ GTEST_SKIP() << "Skipping test because device doesn't support APEX";
+ }
+ ApexServiceTest::SetUp();
+ ASSERT_NE(nullptr, service_.get());
+
+ installer_ = std::make_unique<PrepareTestApexForInstall>(
+ GetTestFile("com.android.apex.cts.shim.apex"));
+ if (!installer_->Prepare()) {
+ return;
+ }
+ ASSERT_EQ("com.android.apex.cts.shim", installer_->package);
+ // First deactivate currently active shim, otherwise activatePackage will be
+ // no-op.
+ {
+ ApexInfo system_shim;
+ ASSERT_TRUE(IsOk(service_->getActivePackage("com.android.apex.cts.shim",
+ &system_shim)));
+ ASSERT_TRUE(IsOk(service_->deactivatePackage(system_shim.modulePath)));
+ }
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer_->test_file})));
+ ASSERT_TRUE(
+ IsOk(service_->activatePackage(installer_->test_installed_file)));
+ }
+
+ void TearDown() override {
+ // Attempt to deactivate.
+ service_->deactivatePackage(installer_->test_installed_file);
+ installer_.reset();
+ // ApexServiceTest::TearDown will wipe out everything under /data/apex.
+ // Since some of that information is required for deactivatePackage binder
+ // call, it's required to be called after deactivating package.
+ ApexServiceTest::TearDown();
+ ASSERT_TRUE(IsOk(service_->activatePackage(
+ "/system/apex/com.android.apex.cts.shim.apex")));
+ }
+
+ std::unique_ptr<PrepareTestApexForInstall> installer_;
+};
+
+TEST_F(ApexSameGradeOfPreInstalledVersionTest, VersionOnDataWins) {
+ std::vector<ApexInfo> all;
+ ASSERT_TRUE(IsOk(service_->getAllPackages(&all)));
+
+ ApexInfo on_data;
+ on_data.moduleName = "com.android.apex.cts.shim";
+ on_data.modulePath = "/data/apex/active/com.android.apex.cts.shim@1.apex";
+ on_data.preinstalledModulePath =
+ "/system/apex/com.android.apex.cts.shim.apex";
+ on_data.versionCode = 1;
+ on_data.isFactory = false;
+ on_data.isActive = true;
+
+ ApexInfo preinstalled;
+ preinstalled.moduleName = "com.android.apex.cts.shim";
+ preinstalled.modulePath = "/system/apex/com.android.apex.cts.shim.apex";
+ preinstalled.preinstalledModulePath =
+ "/system/apex/com.android.apex.cts.shim.apex";
+ preinstalled.versionCode = 1;
+ preinstalled.isFactory = true;
+ preinstalled.isActive = false;
+
+ ASSERT_THAT(all, Contains(ApexInfoEq(on_data)));
+ ASSERT_THAT(all, Contains(ApexInfoEq(preinstalled)));
+}
+
+class ApexServiceDeactivationTest : public ApexServiceActivationSuccessTest {
+ public:
+ void SetUp() override {
+ ApexServiceActivationSuccessTest::SetUp();
+
+ ASSERT_TRUE(installer_ != nullptr);
+ }
+
+ void TearDown() override {
+ installer_.reset();
+ ApexServiceActivationSuccessTest::TearDown();
+ }
+
+ std::unique_ptr<PrepareTestApexForInstall> installer_;
+};
+
+TEST_F(ApexServiceActivationSuccessTest, DmDeviceTearDown) {
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+
+ auto find_fn = [](const std::string& name) {
+ auto& dm = DeviceMapper::Instance();
+ std::vector<DeviceMapper::DmBlockDevice> devices;
+ if (!dm.GetAvailableDevices(&devices)) {
+ return Result<bool>(Errorf("GetAvailableDevices failed"));
+ }
+ for (const auto& device : devices) {
+ if (device.name() == name) {
+ return Result<bool>(true);
+ }
+ }
+ return Result<bool>(false);
+ };
+
+#define ASSERT_FIND(type) \
+ { \
+ Result<bool> res = find_fn(package_id); \
+ ASSERT_RESULT_OK(res); \
+ ASSERT_##type(*res); \
+ }
+
+ ASSERT_FIND(FALSE);
+
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ ASSERT_FIND(TRUE);
+
+ ASSERT_TRUE(
+ IsOk(service_->deactivatePackage(installer_->test_installed_file)));
+
+ ASSERT_FIND(FALSE);
+
+ installer_.reset(); // Skip TearDown deactivatePackage.
+}
+
+TEST_F(ApexServiceActivationSuccessTest, DeactivateFreesLoopDevices) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ std::string package_id =
+ installer_->package + "@" + std::to_string(installer_->version);
+ std::vector<std::string> slaves = ListSlavesOfDmDevice(package_id);
+ ASSERT_EQ(1u, slaves.size())
+ << "Unexpected number of slaves: " << Join(slaves, ",");
+ const std::string& loop = slaves[0];
+
+ ASSERT_TRUE(
+ IsOk(service_->deactivatePackage(installer_->test_installed_file)));
+
+ struct loop_info li;
+ unique_fd fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CLOEXEC)));
+ ASSERT_NE(-1, fd.get()) << "Failed to open " << loop << " : "
+ << strerror(errno);
+ ASSERT_EQ(-1, ioctl(fd.get(), LOOP_GET_STATUS, &li))
+ << loop << " is still alive";
+ ASSERT_EQ(ENXIO, errno) << "Unexpected errno : " << strerror(errno);
+
+ installer_.reset(); // Skip TearDown deactivatePackage.
+}
+
+class ApexServicePrePostInstallTest : public ApexServiceTest {
+ public:
+ template <typename Fn>
+ void RunPrePost(Fn fn, const std::vector<std::string>& apex_names,
+ const char* test_message, bool expect_success = true) {
+ // Using unique_ptr is just the easiest here.
+ using InstallerUPtr = std::unique_ptr<PrepareTestApexForInstall>;
+ std::vector<InstallerUPtr> installers;
+ std::vector<std::string> pkgs;
+
+ for (const std::string& apex_name : apex_names) {
+ InstallerUPtr installer(
+ new PrepareTestApexForInstall(GetTestFile(apex_name)));
+ if (!installer->Prepare()) {
+ return;
+ }
+ pkgs.push_back(installer->test_file);
+ installers.emplace_back(std::move(installer));
+ }
+ android::binder::Status st = (service_.get()->*fn)(pkgs);
+ if (expect_success) {
+ ASSERT_TRUE(IsOk(st));
+ } else {
+ ASSERT_FALSE(IsOk(st));
+ }
+
+ if (test_message != nullptr) {
+ std::string logcat = GetLogcat();
+ EXPECT_THAT(logcat, HasSubstr(test_message));
+ }
+
+ // Ensure that the package is neither active nor mounted.
+ for (const InstallerUPtr& installer : installers) {
+ Result<bool> active = IsActive(installer->package, installer->version,
+ installer->test_file);
+ ASSERT_TRUE(IsOk(active));
+ EXPECT_FALSE(*active);
+ }
+ for (const InstallerUPtr& installer : installers) {
+ Result<ApexFile> apex = ApexFile::Open(installer->test_input);
+ ASSERT_TRUE(IsOk(apex));
+ std::string path =
+ apexd_private::GetPackageMountPoint(apex->GetManifest());
+ std::string entry = std::string("[dir]").append(path);
+ std::vector<std::string> slash_apex = ListDir(kApexRoot);
+ auto it = std::find(slash_apex.begin(), slash_apex.end(), entry);
+ EXPECT_TRUE(it == slash_apex.end()) << Join(slash_apex, ',');
+ }
+ }
+};
+
+TEST_F(ApexServicePrePostInstallTest, Preinstall) {
+ RunPrePost(&IApexService::preinstallPackages,
+ {"apex.apexd_test_preinstall.apex"}, "sh : PreInstall Test");
+}
+
+TEST_F(ApexServicePrePostInstallTest, MultiPreinstall) {
+ constexpr const char* kLogcatText =
+ "sh : /apex/com.android.apex.test_package/etc/sample_prebuilt_file";
+ RunPrePost(&IApexService::preinstallPackages,
+ {"apex.apexd_test_preinstall.apex", "apex.apexd_test.apex"},
+ kLogcatText);
+}
+
+TEST_F(ApexServicePrePostInstallTest, PreinstallFail) {
+ RunPrePost(&IApexService::preinstallPackages,
+ {"apex.apexd_test_prepostinstall.fail.apex"},
+ /* test_message= */ nullptr, /* expect_success= */ false);
+}
+
+TEST_F(ApexServicePrePostInstallTest, Postinstall) {
+ RunPrePost(&IApexService::postinstallPackages,
+ {"apex.apexd_test_postinstall.apex"},
+ "sh : PostInstall Test");
+}
+
+TEST_F(ApexServicePrePostInstallTest, MultiPostinstall) {
+ constexpr const char* kLogcatText =
+ "sh : /apex/com.android.apex.test_package/etc/sample_prebuilt_file";
+ RunPrePost(&IApexService::postinstallPackages,
+ {"apex.apexd_test_postinstall.apex", "apex.apexd_test.apex"},
+ kLogcatText);
+}
+
+TEST_F(ApexServicePrePostInstallTest, PostinstallFail) {
+ RunPrePost(&IApexService::postinstallPackages,
+ {"apex.apexd_test_prepostinstall.fail.apex"},
+ /* test_message= */ nullptr, /* expect_success= */ false);
+}
+
TEST_F(ApexServiceTest, SubmitSingleSessionTestSuccess) {
PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test.apex"),
"/data/app-staging/session_123",
@@ -1309,6 +2224,61 @@
}
}
+TEST_F(ApexServiceTest, UnstagePackagesSuccess) {
+ PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
+ PrepareTestApexForInstall installer2(
+ GetTestFile("apex.apexd_test_different_app.apex"));
+
+ if (!installer1.Prepare() || !installer2.Prepare()) {
+ return;
+ }
+
+ std::vector<std::string> pkgs = {installer1.test_file, installer2.test_file};
+ ASSERT_TRUE(IsOk(service_->stagePackages(pkgs)));
+
+ pkgs = {installer2.test_installed_file};
+ ASSERT_TRUE(IsOk(service_->unstagePackages(pkgs)));
+
+ auto active_packages = ReadEntireDir(kActiveApexPackagesDataDir);
+ ASSERT_TRUE(IsOk(active_packages));
+ ASSERT_THAT(*active_packages,
+ UnorderedElementsAre(installer1.test_installed_file));
+}
+
+TEST_F(ApexServiceTest, UnstagePackagesFail) {
+ PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test.apex"));
+ PrepareTestApexForInstall installer2(
+ GetTestFile("apex.apexd_test_different_app.apex"));
+
+ if (!installer1.Prepare() || !installer2.Prepare()) {
+ return;
+ }
+
+ std::vector<std::string> pkgs = {installer1.test_file};
+ ASSERT_TRUE(IsOk(service_->stagePackages(pkgs)));
+
+ pkgs = {installer1.test_installed_file, installer2.test_installed_file};
+ ASSERT_FALSE(IsOk(service_->unstagePackages(pkgs)));
+
+ // Check that first package wasn't unstaged.
+ auto active_packages = ReadEntireDir(kActiveApexPackagesDataDir);
+ ASSERT_TRUE(IsOk(active_packages));
+ ASSERT_THAT(*active_packages,
+ UnorderedElementsAre(installer1.test_installed_file));
+}
+
+TEST_F(ApexServiceTest, UnstagePackagesFailPreInstalledApex) {
+ auto status = service_->unstagePackages(
+ {"/system/apex/com.android.apex.cts.shim.apex"});
+ ASSERT_FALSE(IsOk(status));
+ const std::string& error_message =
+ std::string(status.exceptionMessage().c_str());
+ ASSERT_THAT(error_message,
+ HasSubstr("Can't uninstall pre-installed apex "
+ "/system/apex/com.android.apex.cts.shim.apex"));
+ ASSERT_TRUE(RegularFileExists("/system/apex/com.android.apex.cts.shim.apex"));
+}
+
class ApexServiceRevertTest : public ApexServiceTest {
protected:
void SetUp() override { ApexServiceTest::SetUp(); }
@@ -1544,10 +2514,30 @@
ASSERT_THAT(session_info, SessionInfoEq(expected));
}
+TEST_F(ApexServiceRevertTest, RevertStoresCrashingNativeProcess) {
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
+ if (!installer.Prepare()) {
+ return;
+ }
+ auto session = ApexSession::CreateSession(1543);
+ ASSERT_TRUE(IsOk(session));
+ ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::ACTIVATED)));
+
+ // Make sure /data/apex/active is non-empty.
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+ std::string native_process = "test_process";
+ // TODO(ioffe): this is calling into internals of apexd which makes test quite
+ // britle. With some refactoring we should be able to call binder api, or
+ // make this a unit test of apexd.cpp.
+ Result<void> res = ::android::apex::RevertActiveSessions(native_process, "");
+ session = ApexSession::GetSession(1543);
+ ASSERT_EQ(session->GetCrashingNativeProcess(), native_process);
+}
+
static pid_t GetPidOf(const std::string& name) {
char buf[1024];
const std::string cmd = std::string("pidof -s ") + name;
- FILE* cmd_pipe = popen(cmd.c_str(), "r"); // NOLINT(cert-env33-c): test code
+ FILE* cmd_pipe = popen(cmd.c_str(), "r");
if (cmd_pipe == nullptr) {
PLOG(ERROR) << "Cannot open pipe for " << cmd;
return 0;
@@ -1701,15 +2691,18 @@
}
ApexServiceTest::SetUp();
- // Skip test if for some reason shim APEX is missing.
+ // Assert that shim apex is pre-installed.
std::vector<ApexInfo> list;
ASSERT_TRUE(IsOk(service_->getAllPackages(&list)));
- bool found = std::any_of(list.begin(), list.end(), [](const auto& apex) {
- return apex.moduleName == "com.android.apex.cts.shim";
- });
- if (!found) {
- GTEST_SKIP() << "Can't find com.android.apex.cts.shim";
- }
+ ApexInfo expected;
+ expected.moduleName = "com.android.apex.cts.shim";
+ expected.modulePath = "/system/apex/com.android.apex.cts.shim.apex";
+ expected.preinstalledModulePath =
+ "/system/apex/com.android.apex.cts.shim.apex";
+ expected.versionCode = 1;
+ expected.isFactory = true;
+ expected.isActive = true;
+ ASSERT_THAT(list, Contains(ApexInfoEq(expected)));
}
};
@@ -1847,6 +2840,82 @@
ASSERT_FALSE(IsOk(service_->stagePackages({installer.test_file})));
}
+TEST_F(ApexServiceTest, RemountPackagesPackageOnSystemChanged) {
+ static constexpr const char* kSystemPath =
+ "/system_ext/apex/apex.apexd_test.apex";
+ static constexpr const char* kPackageName = "com.android.apex.test_package";
+ if (!fs_mgr_overlayfs_is_setup()) {
+ GTEST_SKIP() << "/system_ext is not overlayed into read-write";
+ }
+ if (auto res = IsActive(kPackageName); !res.ok()) {
+ FAIL() << res.error();
+ } else {
+ ASSERT_FALSE(*res) << kPackageName << " is active";
+ }
+ ASSERT_EQ(0, access(kSystemPath, F_OK))
+ << "Failed to stat " << kSystemPath << " : " << strerror(errno);
+ ASSERT_TRUE(IsOk(service_->activatePackage(kSystemPath)));
+ std::string backup_path = GetTestFile("apex.apexd_test.apexd.bak");
+ // Copy original /system_ext apex file. We will need to restore it after test
+ // runs.
+ ASSERT_RESULT_OK(CopyFile(kSystemPath, backup_path, fs::copy_options::none));
+
+ // Make sure we cleanup after ourselves.
+ auto deleter = android::base::make_scope_guard([&]() {
+ if (auto ret = service_->deactivatePackage(kSystemPath); !ret.isOk()) {
+ LOG(ERROR) << ret.exceptionMessage();
+ }
+ auto ret = CopyFile(backup_path, kSystemPath,
+ fs::copy_options::overwrite_existing);
+ if (!ret.ok()) {
+ LOG(ERROR) << ret.error();
+ }
+ });
+
+ // Copy v2 version to /system_ext/apex/ and then call remountPackages.
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
+ if (!installer.Prepare()) {
+ FAIL() << GetDebugStr(&installer);
+ }
+ ASSERT_RESULT_OK(CopyFile(installer.test_file, kSystemPath,
+ fs::copy_options::overwrite_existing));
+ // Don't check that remountPackages succeeded. Most likely it will fail, but
+ // it should still remount our test apex.
+ service_->remountPackages();
+
+ // Check that v2 is now active.
+ auto active_apex = GetActivePackage("com.android.apex.test_package");
+ ASSERT_RESULT_OK(active_apex);
+ ASSERT_EQ(2u, active_apex->versionCode);
+ // Check that module path didn't change, modulo symlink.
+ std::string realSystemPath;
+ ASSERT_TRUE(android::base::Realpath(kSystemPath, &realSystemPath));
+ ASSERT_EQ(realSystemPath, active_apex->modulePath);
+}
+
+TEST_F(ApexServiceActivationSuccessTest, RemountPackagesPackageOnDataChanged) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+ // Copy v2 version to /data/apex/active and then call remountPackages.
+ PrepareTestApexForInstall installer2(GetTestFile("apex.apexd_test_v2.apex"));
+ if (!installer2.Prepare()) {
+ FAIL() << GetDebugStr(&installer2);
+ }
+ ASSERT_RESULT_OK(CopyFile(installer2.test_file,
+ installer_->test_installed_file,
+ fs::copy_options::overwrite_existing));
+ // Don't check that remountPackages succeeded. Most likely it will fail, but
+ // it should still remount our test apex.
+ service_->remountPackages();
+
+ // Check that v2 is now active.
+ auto active_apex = GetActivePackage("com.android.apex.test_package");
+ ASSERT_RESULT_OK(active_apex);
+ ASSERT_EQ(2u, active_apex->versionCode);
+ // Sanity check that module path didn't change.
+ ASSERT_EQ(installer_->test_installed_file, active_apex->modulePath);
+}
+
TEST_F(ApexServiceTest,
SubmitStagedSessionFailsManifestMismatchCleansUpHashtree) {
PrepareTestApexForInstall installer(
@@ -1884,6 +2953,195 @@
}
};
+struct NoCodeApexNameProvider {
+ static std::string GetTestName() { return "apex.apexd_test_nocode.apex"; }
+ static std::string GetPackageName() {
+ return "com.android.apex.test_package";
+ }
+};
+
+class ApexServiceActivationNoCode
+ : public ApexServiceActivationTest<NoCodeApexNameProvider> {};
+
+TEST_F(ApexServiceActivationNoCode, NoCodeApexIsNotExecutable) {
+ ASSERT_TRUE(IsOk(service_->activatePackage(installer_->test_installed_file)))
+ << GetDebugStr(installer_.get());
+
+ std::string mountinfo;
+ ASSERT_TRUE(
+ android::base::ReadFileToString("/proc/self/mountinfo", &mountinfo));
+ bool found_apex_mountpoint = false;
+ for (const auto& line : android::base::Split(mountinfo, "\n")) {
+ std::vector<std::string> tokens = android::base::Split(line, " ");
+ // line format:
+ // mnt_id parent_mnt_id major:minor source target option propagation_type
+ // ex) 33 260:19 / /apex rw,nosuid,nodev -
+ if (tokens.size() >= 7 &&
+ tokens[4] ==
+ "/apex/" + NoCodeApexNameProvider::GetPackageName() + "@1") {
+ found_apex_mountpoint = true;
+ // Make sure that option contains noexec
+ std::vector<std::string> options = android::base::Split(tokens[5], ",");
+ EXPECT_NE(options.end(),
+ std::find(options.begin(), options.end(), "noexec"));
+ break;
+ }
+ }
+ EXPECT_TRUE(found_apex_mountpoint);
+}
+
+struct BannedNameProvider {
+ static std::string GetTestName() { return "sharedlibs.apex"; }
+ static std::string GetPackageName() { return "sharedlibs"; }
+};
+
+class ApexServiceActivationBannedName
+ : public ApexServiceActivationTest<BannedNameProvider> {
+ public:
+ ApexServiceActivationBannedName() : ApexServiceActivationTest(false) {}
+};
+
+TEST_F(ApexServiceActivationBannedName, ApexWithBannedNameCannotBeActivated) {
+ ASSERT_FALSE(
+ IsOk(service_->activatePackage(installer_->test_installed_file)));
+}
+
+namespace {
+void PrepareCompressedTestApex(const std::string& input_apex,
+ const std::string& builtin_dir,
+ const std::string& decompressed_dir,
+ const std::string& active_apex_dir) {
+ const Result<ApexFile>& apex_file = ApexFile::Open(input_apex);
+ ASSERT_TRUE(apex_file.ok());
+ ASSERT_TRUE(apex_file->IsCompressed()) << "Not a compressed APEX";
+
+ auto prebuilt_file_path =
+ builtin_dir + "/" + android::base::Basename(input_apex);
+ fs::copy(input_apex, prebuilt_file_path);
+
+ const ApexManifest& manifest = apex_file->GetManifest();
+ const std::string& package = manifest.name();
+ const int64_t& version = manifest.version();
+
+ auto decompressed_file_path = decompressed_dir + "/" + package + "@" +
+ std::to_string(version) + ".apex";
+ auto result = apex_file->Decompress(decompressed_file_path);
+ ASSERT_TRUE(result.ok()) << "Failed to decompress " << result.error();
+ auto active_apex_file_path =
+ active_apex_dir + "/" + package + "@" + std::to_string(version) + ".apex";
+ auto error =
+ link(decompressed_file_path.c_str(), active_apex_file_path.c_str());
+ ASSERT_EQ(error, 0) << "Failed to hardlink decompressed APEX";
+}
+
+CompressedApexInfo CreateCompressedApex(const std::string& name,
+ const int version, const int size) {
+ CompressedApexInfo result;
+ result.moduleName = name;
+ result.versionCode = version;
+ result.decompressedSize = size;
+ return result;
+}
+} // namespace
+
+class ApexServiceTestForCompressedApex : public ApexServiceTest {
+ public:
+ static constexpr const char* kTempPrebuiltDir = "/data/apex/temp_prebuilt";
+
+ void SetUp() override {
+ ApexServiceTest::SetUp();
+ ASSERT_NE(nullptr, service_.get());
+
+ TemporaryDir decompression_dir, active_apex_dir;
+ if (0 != mkdir(kTempPrebuiltDir, 0777)) {
+ int saved_errno = errno;
+ ASSERT_EQ(saved_errno, EEXIST)
+ << kTempPrebuiltDir << ":" << strerror(saved_errno);
+ }
+ PrepareCompressedTestApex(
+ GetTestFile("com.android.apex.compressed.v1.capex"), kTempPrebuiltDir,
+ kApexDecompressedDir, kActiveApexPackagesDataDir);
+ service_->recollectPreinstalledData({kTempPrebuiltDir});
+ service_->recollectDataApex(kActiveApexPackagesDataDir,
+ kApexDecompressedDir);
+ }
+
+ void TearDown() override {
+ ApexServiceTest::TearDown();
+ DeleteDirContent(kTempPrebuiltDir);
+ rmdir(kTempPrebuiltDir);
+ DeleteDirContent(kApexDecompressedDir);
+ DeleteDirContent(kActiveApexPackagesDataDir);
+ }
+};
+
+TEST_F(ApexServiceTestForCompressedApex, CalculateSizeForCompressedApex) {
+ int64_t result;
+ // Empty list of compressed apex info
+ {
+ CompressedApexInfoList empty_list;
+ ASSERT_TRUE(
+ IsOk(service_->calculateSizeForCompressedApex(empty_list, &result)));
+ ASSERT_EQ(result, 0ll);
+ }
+
+ // Multiple compressed APEX should get summed
+ {
+ CompressedApexInfoList non_empty_list;
+ CompressedApexInfo new_apex = CreateCompressedApex("new_apex", 1, 1);
+ CompressedApexInfo new_apex_2 = CreateCompressedApex("new_apex_2", 1, 2);
+ CompressedApexInfo compressed_apex_same_version =
+ CreateCompressedApex("com.android.apex.compressed", 1, 4);
+ CompressedApexInfo compressed_apex_higher_version =
+ CreateCompressedApex("com.android.apex.compressed", 2, 8);
+ non_empty_list.apexInfos.push_back(new_apex);
+ non_empty_list.apexInfos.push_back(new_apex_2);
+ non_empty_list.apexInfos.push_back(compressed_apex_same_version);
+ non_empty_list.apexInfos.push_back(compressed_apex_higher_version);
+ ASSERT_TRUE(IsOk(
+ service_->calculateSizeForCompressedApex(non_empty_list, &result)));
+ ASSERT_EQ(result, 11ll); // 1+2+8. compressed_apex_same_version is ignored
+ }
+}
+
+TEST_F(ApexServiceTestForCompressedApex, ReserveSpaceForCompressedApex) {
+ // Multiple compressed APEX should reserve equal to
+ // CalculateSizeForCompressedApex
+ {
+ CompressedApexInfoList non_empty_list;
+ CompressedApexInfo new_apex = CreateCompressedApex("new_apex", 1, 1);
+ CompressedApexInfo new_apex_2 = CreateCompressedApex("new_apex_2", 1, 2);
+ CompressedApexInfo compressed_apex_same_version =
+ CreateCompressedApex("com.android.apex.compressed", 1, 4);
+ CompressedApexInfo compressed_apex_higher_version =
+ CreateCompressedApex("com.android.apex.compressed", 2, 8);
+ non_empty_list.apexInfos.push_back(new_apex);
+ non_empty_list.apexInfos.push_back(new_apex_2);
+ non_empty_list.apexInfos.push_back(compressed_apex_same_version);
+ non_empty_list.apexInfos.push_back(compressed_apex_higher_version);
+ int64_t required_size;
+ ASSERT_TRUE(IsOk(service_->calculateSizeForCompressedApex(non_empty_list,
+ &required_size)));
+ ASSERT_EQ(required_size,
+ 11ll); // 1+2+8. compressed_apex_same_version is ignored
+
+ ASSERT_TRUE(IsOk(service_->reserveSpaceForCompressedApex(non_empty_list)));
+ auto files = ReadDir(kOtaReservedDir, [](auto _) { return true; });
+ ASSERT_TRUE(IsOk(files));
+ ASSERT_EQ(files->size(), 1u);
+ EXPECT_EQ((int64_t)fs::file_size((*files)[0]), required_size);
+ }
+
+ // Sending empty list should delete reserved file
+ {
+ CompressedApexInfoList empty_list;
+ ASSERT_TRUE(IsOk(service_->reserveSpaceForCompressedApex(empty_list)));
+ auto files = ReadDir(kOtaReservedDir, [](auto _) { return true; });
+ ASSERT_TRUE(IsOk(files));
+ ASSERT_EQ(files->size(), 0u);
+ }
+}
+
} // namespace apex
} // namespace android
diff --git a/apexd/sysprop/Android.bp b/apexd/sysprop/Android.bp
index 050434b..0b81efd 100644
--- a/apexd/sysprop/Android.bp
+++ b/apexd/sysprop/Android.bp
@@ -7,6 +7,5 @@
srcs: ["ApexProperties.sysprop"],
property_owner: "Platform",
api_packages: ["android.sysprop"],
- ramdisk_available: true,
recovery_available: true,
}
diff --git a/apexer/Android.bp b/apexer/Android.bp
index 20d6f27..081bae1 100644
--- a/apexer/Android.bp
+++ b/apexer/Android.bp
@@ -27,7 +27,6 @@
"zipalign",
"make_f2fs",
"sload_f2fs",
- "make_erofs",
// TODO(b/124476339) apex doesn't follow 'required' dependencies so we need to include this
// manually for 'avbtool'.
"fec",
@@ -44,6 +43,14 @@
srcs: [
"apex_manifest.py",
],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
libs: [
"apex_manifest_proto",
],
@@ -59,9 +66,13 @@
":mke2fs_conf",
],
version: {
- py3: {
+ py2: {
+ enabled: true,
embedded_launcher: true,
},
+ py3: {
+ enabled: false,
+ },
},
libs: [
"apex_manifest",
@@ -77,9 +88,13 @@
"conv_apex_manifest.py",
],
version: {
- py3: {
+ py2: {
+ enabled: true,
embedded_launcher: true,
},
+ py3: {
+ enabled: false,
+ },
},
libs: [
"apex_manifest_proto",
@@ -124,10 +139,21 @@
"testdata/com.android.example.apex.pk8",
"testdata/com.android.example.apex.x509.pem",
],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
test_suites: ["general-tests"],
libs: [
"apex_manifest",
],
+ test_options: {
+ unit_test: false,
+ },
}
apexer_deps_minus_go_tools = apexer_tools + [
@@ -151,7 +177,7 @@
],
out: ["apexer_test_host_tools.zip"],
tools: apexer_deps_tools + [
- // To force signapk.jar generated in out/host
+ // To force signapk.jar generated in out/soong/host
"signapk",
],
cmd: "HOST_OUT_BIN=$$(dirname $(location apexer)) && " +
diff --git a/apexer/TEST_MAPPING b/apexer/TEST_MAPPING
index 1ad3078..0b3e797 100644
--- a/apexer/TEST_MAPPING
+++ b/apexer/TEST_MAPPING
@@ -1,9 +1,11 @@
{
- "presubmit": [
- {
- "name": "apexer_test"
- }
- ],
+ // b/214537606: disabled since test lab JDK version has been upgraded to follow newer branches,
+ // and will not be able to match sc-v2-dev
+ //"presubmit": [
+ // {
+ // "name": "apexer_test"
+ // }
+ //],
"imports": [
{
"path": "system/apex/tests"
diff --git a/apexer/apexer.py b/apexer/apexer.py
index 65ea25f..f0c17f4 100644
--- a/apexer/apexer.py
+++ b/apexer/apexer.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
#
# Copyright (C) 2018 The Android Open Source Project
#
@@ -32,8 +32,6 @@
import tempfile
import uuid
import xml.etree.ElementTree as ET
-import zipfile
-import glob
from apex_manifest import ValidateApexManifest
from apex_manifest import ApexManifestError
from manifest import android_ns
@@ -80,7 +78,7 @@
parser.add_argument(
'--canned_fs_config',
help='canned_fs_config specifies uid/gid/mode of files. Required for ' +
- '"image" APEXS.')
+ '"image" APEXS.')
parser.add_argument(
'--key', help='path to the private key file. Required for "image" APEXs.')
parser.add_argument(
@@ -108,8 +106,8 @@
metavar='FS_TYPE',
required=False,
default='ext4',
- choices=['ext4', 'f2fs', 'erofs'],
- help='type of filesystem being used for payload image "ext4", "f2fs" or "erofs"')
+ choices=['ext4', 'f2fs'],
+ help='type of filesystem being used for payload image "ext4" or "f2fs"')
parser.add_argument(
'--override_apk_package_name',
required=False,
@@ -180,14 +178,6 @@
action='store_true',
help="""Skip signing the apex payload. Used only for testing purposes."""
)
- parser.add_argument(
- '--test_only',
- action='store_true',
- help=(
- 'Add testOnly=true attribute to application element in '
- 'AndroidManifest file.')
- )
-
return parser.parse_args(argv)
@@ -211,7 +201,6 @@
p = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
output, _ = p.communicate()
- output = output.decode()
if verbose or p.returncode not in expected_return_values:
print(output.rstrip())
@@ -245,19 +234,16 @@
return (size + unit - 1) & (~(unit - 1))
-def PrepareAndroidManifest(package, version, test_only):
+def PrepareAndroidManifest(package, version):
template = """\
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="{package}" android:versionCode="{version}">
<!-- APEX does not have classes.dex -->
- <application android:hasCode="false" {test_only_attribute}/>
+ <application android:hasCode="false" />
</manifest>
"""
-
- test_only_attribute = 'android:testOnly="true"' if test_only else ''
- return template.format(package=package, version=version,
- test_only_attribute=test_only_attribute)
+ return template.format(package=package, version=version)
def ValidateAndroidManifest(package, android_manifest):
@@ -270,17 +256,6 @@
"' in the apex_manifest.pb")
-def ValidateGeneratedAndroidManifest(android_manifest, test_only):
- tree = ET.parse(android_manifest)
- manifest_tag = tree.getroot()
- application_tag = manifest_tag.find('./application')
- if test_only:
- test_only_in_xml = application_tag.attrib[
- '{http://schemas.android.com/apk/res/android}testOnly']
- if test_only_in_xml != 'true':
- raise Exception('testOnly attribute must be equal to true.')
-
-
def ValidateArgs(args):
build_info = None
@@ -288,7 +263,7 @@
if not os.path.exists(args.build_info):
print("Build info file '" + args.build_info + "' does not exist")
return False
- with open(args.build_info, 'rb') as buildInfoFile:
+ with open(args.build_info) as buildInfoFile:
build_info = apex_build_info_pb2.ApexBuildInfo()
build_info.ParseFromString(buildInfoFile.read())
@@ -382,19 +357,18 @@
return True
-
def GenerateBuildInfo(args):
build_info = apex_build_info_pb2.ApexBuildInfo()
if (args.include_cmd_line_in_build_info):
build_info.apexer_command_line = str(sys.argv)
- with open(args.file_contexts, 'rb') as f:
+ with open(args.file_contexts) as f:
build_info.file_contexts = f.read()
- with open(args.canned_fs_config, 'rb') as f:
+ with open(args.canned_fs_config) as f:
build_info.canned_fs_config = f.read()
- with open(args.android_manifest, 'rb') as f:
+ with open(args.android_manifest) as f:
build_info.android_manifest = f.read()
if args.target_sdk_version:
@@ -417,7 +391,6 @@
return build_info
-
def AddLoggingParent(android_manifest, logging_parent_value):
"""Add logging parent as an additional <meta-data> tag.
@@ -462,257 +435,202 @@
indent = get_indent(application.previousSibling, 1)
application.appendChild(doc.createTextNode(indent))
- with tempfile.NamedTemporaryFile(delete=False, mode='w') as temp:
- write_xml(temp, doc)
- return temp.name
+ with tempfile.NamedTemporaryFile(delete=False) as temp:
+ write_xml(temp, doc)
+ return temp.name
+def CreateApex(args, work_dir):
+ if not ValidateArgs(args):
+ return False
-def ShaHashFiles(file_paths):
- """get hash for a number of files."""
- h = hashlib.sha256()
- for file_path in file_paths:
- with open(file_path, 'rb') as file:
- while True:
- chunk = file.read(h.block_size)
- if not chunk:
- break
- h.update(chunk)
- return h.hexdigest()
+ if args.verbose:
+ print 'Using tools from ' + str(tool_path_list)
+ def copyfile(src, dst):
+ if args.verbose:
+ print('Copying ' + src + ' to ' + dst)
+ shutil.copyfile(src, dst)
-def CreateImageExt4(args, work_dir, manifests_dir, img_file):
- """Create image for ext4 file system."""
+ try:
+ manifest_apex = ValidateApexManifest(args.manifest)
+ except ApexManifestError as err:
+ print("'" + args.manifest + "' is not a valid manifest file")
+ print err.errmessage
+ return False
+ except IOError:
+ print("Cannot read manifest file: '" + args.manifest + "'")
+ return False
- lost_found_location = os.path.join(args.input_dir, 'lost+found')
- if os.path.exists(lost_found_location):
- print('Warning: input_dir contains a lost+found/ root folder, which '
- 'has been known to cause non-deterministic apex builds.')
+ # create an empty image that is sufficiently big
+ size_in_mb = (GetDirSize(args.input_dir) / (1024 * 1024))
- # sufficiently big = size + 16MB margin
- size_in_mb = (GetDirSize(args.input_dir) // (1024 * 1024))
- size_in_mb += 16
+ content_dir = os.path.join(work_dir, 'content')
+ os.mkdir(content_dir)
- # Margin is for files that are not under args.input_dir. this consists of
- # n inodes for apex_manifest files and 11 reserved inodes for ext4.
- # TOBO(b/122991714) eliminate these details. Use build_image.py which
- # determines the optimal inode count by first building an image and then
- # count the inodes actually used.
- inode_num_margin = GetFilesAndDirsCount(manifests_dir) + 11
- inode_num = GetFilesAndDirsCount(args.input_dir) + inode_num_margin
+ # APEX manifest is also included in the image. The manifest is included
+ # twice: once inside the image and once outside the image (but still
+ # within the zip container).
+ manifests_dir = os.path.join(work_dir, 'manifests')
+ os.mkdir(manifests_dir)
+ copyfile(args.manifest, os.path.join(manifests_dir, 'apex_manifest.pb'))
+ if args.manifest_json:
+ # manifest_json is for compatibility
+ copyfile(args.manifest_json, os.path.join(manifests_dir, 'apex_manifest.json'))
- cmd = ['mke2fs']
- cmd.extend(['-O', '^has_journal']) # because image is read-only
- cmd.extend(['-b', str(BLOCK_SIZE)])
- cmd.extend(['-m', '0']) # reserved block percentage
- cmd.extend(['-t', 'ext4'])
- cmd.extend(['-I', '256']) # inode size
- cmd.extend(['-N', str(inode_num)])
- uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
- cmd.extend(['-U', uu])
- cmd.extend(['-E', 'hash_seed=' + uu])
- cmd.append(img_file)
- cmd.append(str(size_in_mb) + 'M')
- with tempfile.NamedTemporaryFile(dir=work_dir,
- suffix='mke2fs.conf') as conf_file:
- conf_data = pkgutil.get_data('apexer', 'mke2fs.conf')
- conf_file.write(conf_data)
- conf_file.flush()
- RunCommand(cmd, args.verbose,
- {'MKE2FS_CONFIG': conf_file.name, 'E2FSPROGS_FAKE_TIME': '1'})
-
- # Compile the file context into the binary form
- compiled_file_contexts = os.path.join(work_dir, 'file_contexts.bin')
- cmd = ['sefcontext_compile']
- cmd.extend(['-o', compiled_file_contexts])
- cmd.append(args.file_contexts)
- RunCommand(cmd, args.verbose)
-
- # Add files to the image file
- cmd = ['e2fsdroid']
- cmd.append('-e') # input is not android_sparse_file
- cmd.extend(['-f', args.input_dir])
- cmd.extend(['-T', '0']) # time is set to epoch
- cmd.extend(['-S', compiled_file_contexts])
- cmd.extend(['-C', args.canned_fs_config])
- cmd.extend(['-a', '/'])
- cmd.append('-s') # share dup blocks
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
-
- cmd = ['e2fsdroid']
- cmd.append('-e') # input is not android_sparse_file
- cmd.extend(['-f', manifests_dir])
- cmd.extend(['-T', '0']) # time is set to epoch
- cmd.extend(['-S', compiled_file_contexts])
- cmd.extend(['-C', args.canned_fs_config])
- cmd.extend(['-a', '/'])
- cmd.append('-s') # share dup blocks
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
-
- # Resize the image file to save space
- cmd = ['resize2fs']
- cmd.append('-M') # shrink as small as possible
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
-
-
-def CreateImageF2fs(args, manifests_dir, img_file):
- """Create image for f2fs file system."""
- # F2FS requires a ~100M minimum size (necessary for ART, could be reduced
- # a bit for other)
- # TODO(b/158453869): relax these requirements for readonly devices
- size_in_mb = (GetDirSize(args.input_dir) // (1024 * 1024))
- size_in_mb += 100
-
- # Create an empty image
- cmd = ['/usr/bin/fallocate']
- cmd.extend(['-l', str(size_in_mb) + 'M'])
- cmd.append(img_file)
- RunCommand(cmd, args.verbose)
-
- # Format the image to F2FS
- cmd = ['make_f2fs']
- cmd.extend(['-g', 'android'])
- uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
- cmd.extend(['-U', uu])
- cmd.extend(['-T', '0'])
- cmd.append('-r') # sets checkpointing seed to 0 to remove random bits
- cmd.append(img_file)
- RunCommand(cmd, args.verbose)
-
- # Add files to the image
- cmd = ['sload_f2fs']
- cmd.extend(['-C', args.canned_fs_config])
- cmd.extend(['-f', manifests_dir])
- cmd.extend(['-s', args.file_contexts])
- cmd.extend(['-T', '0'])
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, expected_return_values={0, 1})
-
- cmd = ['sload_f2fs']
- cmd.extend(['-C', args.canned_fs_config])
- cmd.extend(['-f', args.input_dir])
- cmd.extend(['-s', args.file_contexts])
- cmd.extend(['-T', '0'])
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, expected_return_values={0, 1})
-
- # TODO(b/158453869): resize the image file to save space
-
-
-def CreateImageErofs(args, work_dir, manifests_dir, img_file):
- """Create image for erofs file system."""
- # mkfs.erofs doesn't support multiple input
-
- tmp_input_dir = os.path.join(work_dir, 'tmp_input_dir')
- os.mkdir(tmp_input_dir)
- cmd = ['/bin/cp', '-ra']
- cmd.extend(glob.glob(manifests_dir + '/*'))
- cmd.extend(glob.glob(args.input_dir + '/*'))
- cmd.append(tmp_input_dir)
- RunCommand(cmd, args.verbose)
-
- cmd = ['make_erofs']
- cmd.extend(['-z', 'lz4hc'])
- cmd.extend(['--fs-config-file', args.canned_fs_config])
- cmd.extend(['--file-contexts', args.file_contexts])
- uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
- cmd.extend(['-U', uu])
- cmd.extend(['-T', '0'])
- cmd.extend([img_file, tmp_input_dir])
- RunCommand(cmd, args.verbose)
- shutil.rmtree(tmp_input_dir)
-
- # The minimum image size of erofs is 4k, which will cause an error
- # when execute generate_hash_tree in avbtool
- cmd = ['/bin/ls', '-lgG', img_file]
- output, _ = RunCommand(cmd, verbose=False)
- image_size = int(output.split()[2])
- if image_size == 4096:
- cmd = ['/usr/bin/fallocate', '-l', '8k', img_file]
- RunCommand(cmd, verbose=False)
-
-
-def CreateImage(args, work_dir, manifests_dir, img_file):
- """create payload image."""
- if args.payload_fs_type == 'ext4':
- CreateImageExt4(args, work_dir, manifests_dir, img_file)
- elif args.payload_fs_type == 'f2fs':
- CreateImageF2fs(args, manifests_dir, img_file)
- elif args.payload_fs_type == 'erofs':
- CreateImageErofs(args, work_dir, manifests_dir, img_file)
-
-
-def SignImage(args, manifest_apex, img_file):
- """sign payload image.
-
- Args:
- args: apexer options
- manifest_apex: apex manifest proto
- img_file: unsigned payload image file
- """
-
- if args.do_not_check_keyname or args.unsigned_payload:
- key_name = manifest_apex.name
- else:
- key_name = os.path.basename(os.path.splitext(args.key)[0])
-
- cmd = ['avbtool']
- cmd.append('add_hashtree_footer')
- cmd.append('--do_not_generate_fec')
- cmd.extend(['--algorithm', 'SHA256_RSA4096'])
- cmd.extend(['--hash_algorithm', 'sha256'])
- cmd.extend(['--key', args.key])
- cmd.extend(['--prop', 'apex.key:' + key_name])
- # Set up the salt based on manifest content which includes name
- # and version
- salt = hashlib.sha256(manifest_apex.SerializeToString()).hexdigest()
- cmd.extend(['--salt', salt])
- cmd.extend(['--image', img_file])
- if args.no_hashtree:
- cmd.append('--no_hashtree')
- if args.signing_args:
- cmd.extend(shlex.split(args.signing_args))
- RunCommand(cmd, args.verbose)
-
- # Get the minimum size of the partition required.
- # TODO(b/113320014) eliminate this step
- info, _ = RunCommand(['avbtool', 'info_image', '--image', img_file],
- args.verbose)
- vbmeta_offset = int(re.search('VBMeta\ offset:\ *([0-9]+)', info).group(1))
- vbmeta_size = int(re.search('VBMeta\ size:\ *([0-9]+)', info).group(1))
- partition_size = RoundUp(vbmeta_offset + vbmeta_size,
- BLOCK_SIZE) + BLOCK_SIZE
-
- # Resize to the minimum size
- # TODO(b/113320014) eliminate this step
- cmd = ['avbtool']
- cmd.append('resize_image')
- cmd.extend(['--image', img_file])
- cmd.extend(['--partition_size', str(partition_size)])
- RunCommand(cmd, args.verbose)
-
-
-def CreateApexPayload(args, work_dir, content_dir, manifests_dir,
- manifest_apex):
- """Create payload.
-
- Args:
- args: apexer options
- work_dir: apex container working directory
- content_dir: the working directory for payload contents
- manifests_dir: manifests directory
- manifest_apex: apex manifest proto
-
- Returns:
- payload file
- """
if args.payload_type == 'image':
+ if args.do_not_check_keyname or args.unsigned_payload:
+ key_name = manifest_apex.name
+ else:
+ key_name = os.path.basename(os.path.splitext(args.key)[0])
+
img_file = os.path.join(content_dir, 'apex_payload.img')
- CreateImage(args, work_dir, manifests_dir, img_file)
+
+ if args.payload_fs_type == 'ext4':
+ # sufficiently big = size + 16MB margin
+ size_in_mb += 16
+
+ # margin is for files that are not under args.input_dir. this consists of
+ # n inodes for apex_manifest files and 11 reserved inodes for ext4.
+ # TOBO(b/122991714) eliminate these details. use build_image.py which
+ # determines the optimal inode count by first building an image and then
+ # count the inodes actually used.
+ inode_num_margin = GetFilesAndDirsCount(manifests_dir) + 11
+ inode_num = GetFilesAndDirsCount(args.input_dir) + inode_num_margin
+
+ cmd = ['mke2fs']
+ cmd.extend(['-O', '^has_journal']) # because image is read-only
+ cmd.extend(['-b', str(BLOCK_SIZE)])
+ cmd.extend(['-m', '0']) # reserved block percentage
+ cmd.extend(['-t', 'ext4'])
+ cmd.extend(['-I', '256']) # inode size
+ cmd.extend(['-N', str(inode_num)])
+ uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
+ cmd.extend(['-U', uu])
+ cmd.extend(['-E', 'hash_seed=' + uu])
+ cmd.append(img_file)
+ cmd.append(str(size_in_mb) + 'M')
+ with tempfile.NamedTemporaryFile(dir=work_dir, suffix="mke2fs.conf") as conf_file:
+ conf_data = pkgutil.get_data('apexer', 'mke2fs.conf')
+ conf_file.write(conf_data)
+ conf_file.flush()
+ RunCommand(cmd, args.verbose,
+ {"MKE2FS_CONFIG": conf_file.name, 'E2FSPROGS_FAKE_TIME': '1'})
+
+ # Compile the file context into the binary form
+ compiled_file_contexts = os.path.join(work_dir, 'file_contexts.bin')
+ cmd = ['sefcontext_compile']
+ cmd.extend(['-o', compiled_file_contexts])
+ cmd.append(args.file_contexts)
+ RunCommand(cmd, args.verbose)
+
+ # Add files to the image file
+ cmd = ['e2fsdroid']
+ cmd.append('-e') # input is not android_sparse_file
+ cmd.extend(['-f', args.input_dir])
+ cmd.extend(['-T', '0']) # time is set to epoch
+ cmd.extend(['-S', compiled_file_contexts])
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.append('-s') # share dup blocks
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ cmd = ['e2fsdroid']
+ cmd.append('-e') # input is not android_sparse_file
+ cmd.extend(['-f', manifests_dir])
+ cmd.extend(['-T', '0']) # time is set to epoch
+ cmd.extend(['-S', compiled_file_contexts])
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.append('-s') # share dup blocks
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ # Resize the image file to save space
+ cmd = ['resize2fs']
+ cmd.append('-M') # shrink as small as possible
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ elif args.payload_fs_type == 'f2fs':
+ # F2FS requires a ~100M minimum size (necessary for ART, could be reduced a bit for other)
+ # TODO(b/158453869): relax these requirements for readonly devices
+ size_in_mb += 100
+
+ # Create an empty image
+ cmd = ['/usr/bin/fallocate']
+ cmd.extend(['-l', str(size_in_mb)+'M'])
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose)
+
+ # Format the image to F2FS
+ cmd = ['make_f2fs']
+ cmd.extend(['-g', 'android'])
+ uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
+ cmd.extend(['-U', uu])
+ cmd.extend(['-T', '0'])
+ cmd.append('-r') # sets checkpointing seed to 0 to remove random bits
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose)
+
+ # Add files to the image
+ cmd = ['sload_f2fs']
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.extend(['-f', manifests_dir])
+ cmd.extend(['-s', args.file_contexts])
+ cmd.extend(['-T', '0'])
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, expected_return_values={0,1})
+
+ cmd = ['sload_f2fs']
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.extend(['-f', args.input_dir])
+ cmd.extend(['-s', args.file_contexts])
+ cmd.extend(['-T', '0'])
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, expected_return_values={0,1})
+
+ # TODO(b/158453869): resize the image file to save space
+
+ if args.unsigned_payload_only:
+ shutil.copyfile(img_file, args.output)
+ if (args.verbose):
+ print('Created (unsigned payload only) ' + args.output)
+ return True
+
if not args.unsigned_payload:
- SignImage(args, manifest_apex, img_file)
+ cmd = ['avbtool']
+ cmd.append('add_hashtree_footer')
+ cmd.append('--do_not_generate_fec')
+ cmd.extend(['--algorithm', 'SHA256_RSA4096'])
+ cmd.extend(['--hash_algorithm', 'sha256'])
+ cmd.extend(['--key', args.key])
+ cmd.extend(['--prop', 'apex.key:' + key_name])
+ # Set up the salt based on manifest content which includes name
+ # and version
+ salt = hashlib.sha256(manifest_apex.SerializeToString()).hexdigest()
+ cmd.extend(['--salt', salt])
+ cmd.extend(['--image', img_file])
+ if args.no_hashtree:
+ cmd.append('--no_hashtree')
+ if args.signing_args:
+ cmd.extend(shlex.split(args.signing_args))
+ RunCommand(cmd, args.verbose)
+
+ # Get the minimum size of the partition required.
+ # TODO(b/113320014) eliminate this step
+ info, _ = RunCommand(['avbtool', 'info_image', '--image', img_file],
+ args.verbose)
+ vbmeta_offset = int(re.search('VBMeta\ offset:\ *([0-9]+)', info).group(1))
+ vbmeta_size = int(re.search('VBMeta\ size:\ *([0-9]+)', info).group(1))
+ partition_size = RoundUp(vbmeta_offset + vbmeta_size,
+ BLOCK_SIZE) + BLOCK_SIZE
+
+ # Resize to the minimum size
+ # TODO(b/113320014) eliminate this step
+ cmd = ['avbtool']
+ cmd.append('resize_image')
+ cmd.extend(['--image', img_file])
+ cmd.extend(['--partition_size', str(partition_size)])
+ RunCommand(cmd, args.verbose)
else:
img_file = os.path.join(content_dir, 'apex_payload.zip')
cmd = ['soong_zip']
@@ -722,102 +640,37 @@
cmd.extend(['-C', manifests_dir])
cmd.extend(['-D', manifests_dir])
RunCommand(cmd, args.verbose)
- return img_file
+ if args.payload_only:
+ shutil.copyfile(img_file, args.output)
+ if (args.verbose):
+ print('Created (payload only) ' + args.output)
+ return True
-def CreateAndroidManifestXml(args, work_dir, manifest_apex):
- """Create AndroidManifest.xml file.
-
- Args:
- args: apexer options
- work_dir: apex container working directory
- manifest_apex: apex manifest proto
-
- Returns:
- AndroidManifest.xml file inside the work dir
- """
+ # package the image file and APEX manifest as an APK.
+ # The AndroidManifest file is automatically generated if not given.
android_manifest_file = os.path.join(work_dir, 'AndroidManifest.xml')
if not args.android_manifest:
if args.verbose:
print('Creating AndroidManifest ' + android_manifest_file)
- with open(android_manifest_file, 'w') as f:
+ with open(android_manifest_file, 'w+') as f:
app_package_name = manifest_apex.name
- f.write(PrepareAndroidManifest(app_package_name, manifest_apex.version,
- args.test_only))
+ f.write(PrepareAndroidManifest(app_package_name, manifest_apex.version))
args.android_manifest = android_manifest_file
- ValidateGeneratedAndroidManifest(args.android_manifest, args.test_only)
else:
ValidateAndroidManifest(manifest_apex.name, args.android_manifest)
shutil.copyfile(args.android_manifest, android_manifest_file)
# If logging parent is specified, add it to the AndroidManifest.
- if args.logging_parent:
+ if args.logging_parent != "":
android_manifest_file = AddLoggingParent(android_manifest_file,
args.logging_parent)
- return android_manifest_file
-
-def CreateApex(args, work_dir):
- if not ValidateArgs(args):
- return False
-
- if args.verbose:
- print('Using tools from ' + str(tool_path_list))
-
- def CopyFile(src, dst):
- if args.verbose:
- print('Copying ' + src + ' to ' + dst)
- shutil.copyfile(src, dst)
-
- try:
- manifest_apex = ValidateApexManifest(args.manifest)
- except ApexManifestError as err:
- print("'" + args.manifest + "' is not a valid manifest file")
- print(err.errmessage)
- return False
- except IOError:
- print("Cannot read manifest file: '" + args.manifest + "'")
- return False
-
- # Create content dir and manifests dir, the manifests dir is used to
- # create the payload image
- content_dir = os.path.join(work_dir, 'content')
- os.mkdir(content_dir)
- manifests_dir = os.path.join(work_dir, 'manifests')
- os.mkdir(manifests_dir)
-
- # Create AndroidManifest.xml file first so that we can hash the file
- # and store the hashed value in the manifest proto buf that goes into
- # the payload image. So any change in this file will ensure changes
- # in payload image file
- android_manifest_file = CreateAndroidManifestXml(
- args, work_dir, manifest_apex)
-
- # APEX manifest is also included in the image. The manifest is included
- # twice: once inside the image and once outside the image (but still
- # within the zip container).
- with open(os.path.join(manifests_dir, 'apex_manifest.pb'), 'wb') as f:
- f.write(manifest_apex.SerializeToString())
- with open(os.path.join(content_dir, 'apex_manifest.pb'), 'wb') as f:
- f.write(manifest_apex.SerializeToString())
+ # copy manifest to the content dir so that it is also accessible
+ # without mounting the image
+ copyfile(args.manifest, os.path.join(content_dir, 'apex_manifest.pb'))
if args.manifest_json:
- CopyFile(args.manifest_json,
- os.path.join(manifests_dir, 'apex_manifest.json'))
- CopyFile(args.manifest_json,
- os.path.join(content_dir, 'apex_manifest.json'))
-
- # Create payload
- img_file = CreateApexPayload(args, work_dir, content_dir, manifests_dir,
- manifest_apex)
-
- if args.unsigned_payload_only or args.payload_only:
- shutil.copyfile(img_file, args.output)
- if args.verbose:
- if args.unsigned_payload_only:
- print('Created (unsigned payload only) ' + args.output)
- else:
- print('Created (payload only) ' + args.output)
- return True
+ copyfile(args.manifest_json, os.path.join(content_dir, 'apex_manifest.json'))
# copy the public key, if specified
if args.pubkey:
@@ -825,7 +678,7 @@
if args.include_build_info:
build_info = GenerateBuildInfo(args)
- with open(os.path.join(content_dir, 'apex_build_info.pb'), 'wb') as f:
+ with open(os.path.join(content_dir, 'apex_build_info.pb'), "wb") as f:
f.write(build_info.SerializeToString())
apk_file = os.path.join(work_dir, 'apex.apk')
@@ -853,10 +706,33 @@
RunCommand(cmd, args.verbose)
zip_file = os.path.join(work_dir, 'apex.zip')
- CreateZip(content_dir, zip_file)
- MergeZips([apk_file, zip_file], args.output)
+ cmd = ['soong_zip']
+ cmd.append('-d') # include directories
+ cmd.extend(['-C', content_dir]) # relative root
+ cmd.extend(['-D', content_dir]) # input dir
+ for file_ in os.listdir(content_dir):
+ if os.path.isfile(os.path.join(content_dir, file_)):
+ cmd.extend(['-s', file_]) # don't compress any files
+ cmd.extend(['-o', zip_file])
+ RunCommand(cmd, args.verbose)
- if args.verbose:
+ unaligned_apex_file = os.path.join(work_dir, 'unaligned.apex')
+ cmd = ['merge_zips']
+ cmd.append('-j') # sort
+ cmd.append(unaligned_apex_file) # output
+ cmd.append(apk_file) # input
+ cmd.append(zip_file) # input
+ RunCommand(cmd, args.verbose)
+
+ # Align the files at page boundary for efficient access
+ cmd = ['zipalign']
+ cmd.append('-f')
+ cmd.append(str(BLOCK_SIZE))
+ cmd.append(unaligned_apex_file)
+ cmd.append(args.output)
+ RunCommand(cmd, args.verbose)
+
+ if (args.verbose):
print('Created ' + args.output)
return True
@@ -872,39 +748,6 @@
shutil.rmtree(self.name)
-def CreateZip(content_dir, apex_zip):
- with zipfile.ZipFile(apex_zip, 'w', compression=zipfile.ZIP_DEFLATED) as out:
- for root, _, files in os.walk(content_dir):
- for file in files:
- path = os.path.join(root, file)
- rel_path = os.path.relpath(path, content_dir)
- # "apex_payload.img" shouldn't be compressed
- if rel_path == 'apex_payload.img':
- out.write(path, rel_path, compress_type=zipfile.ZIP_STORED)
- else:
- out.write(path, rel_path)
-
-
-def MergeZips(zip_files, output_zip):
- with zipfile.ZipFile(output_zip, 'w') as out:
- for file in zip_files:
- # copy to output_zip
- with zipfile.ZipFile(file, 'r') as inzip:
- for info in inzip.infolist():
- # reset timestamp for deterministic output
- info.date_time = (1980, 1, 1, 0, 0, 0)
- # reset filemode for deterministic output. The high 16 bits are for
- # filemode. 0x81A4 corresponds to 0o100644(a regular file with
- # '-rw-r--r--' permission).
- info.external_attr = 0x81A40000
- # "apex_payload.img" should be 4K aligned
- if info.filename == 'apex_payload.img':
- data_offset = out.fp.tell() + len(info.FileHeader())
- info.extra = b'\0' * (BLOCK_SIZE - data_offset % BLOCK_SIZE)
- data = inzip.read(info)
- out.writestr(info, data)
-
-
def main(argv):
global tool_path_list
args = ParseArgs(argv)
diff --git a/apexer/apexer_test.py b/apexer/apexer_test.py
index da5becd..7fec4ec 100644
--- a/apexer/apexer_test.py
+++ b/apexer/apexer_test.py
@@ -41,6 +41,7 @@
TEST_PK8_KEY = os.path.join("testdata", "com.android.example.apex.pk8")
TEST_AVB_PUBLIC_KEY = os.path.join("testdata", "com.android.example.apex.avbpubkey")
+
def run(args, verbose=None, **kwargs):
"""Creates and returns a subprocess.Popen object.
@@ -73,7 +74,7 @@
def run_host_command(args, verbose=None, **kwargs):
host_build_top = os.environ.get("ANDROID_BUILD_TOP")
if host_build_top:
- host_command_dir = os.path.join(host_build_top, "out/host/linux-x86/bin")
+ host_command_dir = os.path.join(host_build_top, "out/soong/host/linux-x86/bin")
args[0] = os.path.join(host_command_dir, args[0])
return run_and_check_output(args, verbose, **kwargs)
@@ -269,7 +270,7 @@
payload_only = True
os.environ["APEXER_TOOL_PATH"] = (self.host_tools_path +
- ":out/host/linux-x86/bin:prebuilts/sdk/tools/linux/bin")
+ ":out/soong/host/linux-x86/bin:prebuilts/sdk/tools/linux/bin")
cmd = ["apexer", "--force", "--include_build_info", "--do_not_check_keyname"]
if DEBUG_TEST:
cmd.append('-v')
@@ -280,7 +281,7 @@
cmd.extend(["--manifest_json", container_files["apex_manifest.json"]])
cmd.extend(["--build_info", container_files["apex_build_info.pb"]])
if not payload_only and "assets" in container_files:
- cmd.extend(["--assets_dir", container_files["assets"]])
+ cmd.extend(["--assets_dir", "assets"])
if not unsigned_payload_only:
cmd.extend(["--key", os.path.join(get_current_dir(), TEST_PRIVATE_KEY)])
cmd.extend(["--pubkey", os.path.join(get_current_dir(), TEST_AVB_PUBLIC_KEY)])
@@ -314,7 +315,7 @@
java_dep_lib += ":" + os.path.join(os.environ["ANDROID_HOST_OUT"], "lib64")
if "ANDROID_BUILD_TOP" in os.environ:
java_dep_lib += ":" + os.path.join(os.environ["ANDROID_BUILD_TOP"],
- "out/host/linux-x86/lib64")
+ "out/soong/host/linux-x86/lib64")
return [java_toolchain, java_dep_lib]
@@ -327,7 +328,7 @@
java_toolchain,
"-Djava.library.path=" + java_dep_lib,
"-jar", self.host_tools['signapk.jar'],
- "-a", "4096", "--align-file-size",
+ "-a", "4096",
os.path.join(get_current_dir(), TEST_X509_KEY),
os.path.join(get_current_dir(), TEST_PK8_KEY),
unsigned_apex, fn]
@@ -425,5 +426,6 @@
def test_apex_with_overridden_package_name(self):
self._run_build_test(TEST_APEX_WITH_OVERRIDDEN_PACKAGE_NAME)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/apexer/conv_apex_manifest.py b/apexer/conv_apex_manifest.py
index 9ebf3f9..dd598db 100644
--- a/apexer/conv_apex_manifest.py
+++ b/apexer/conv_apex_manifest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
#
# Copyright (C) 2019 The Android Open Source Project
#
diff --git a/apexer/runtests.sh b/apexer/runtests.sh
index 4d9d602..e2eacc9 100755
--- a/apexer/runtests.sh
+++ b/apexer/runtests.sh
@@ -25,10 +25,10 @@
source ${ANDROID_BUILD_TOP}/build/envsetup.sh
m -j apexer
-export APEXER_TOOL_PATH="${ANDROID_BUILD_TOP}/out/host/linux-x86/bin:${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/linux/bin"
+export APEXER_TOOL_PATH="${ANDROID_BUILD_TOP}/out/soong/host/linux-x86/bin:${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/linux/bin"
PATH+=":${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/linux/bin"
-for fs_type in ext4 f2fs erofs
+for fs_type in ext4 f2fs
do
input_dir=$(mktemp -d)
output_dir=$(mktemp -d)
@@ -57,7 +57,7 @@
manifest_dir=$(mktemp -d)
manifest_file=${manifest_dir}/apex_manifest.pb
echo '{"name": "com.android.example.apex", "version": 1}' > ${manifest_dir}/apex_manifest.json
-${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/conv_apex_manifest proto ${manifest_dir}/apex_manifest.json -o ${manifest_file}
+${ANDROID_BUILD_TOP}/out/soong/host/linux-x86/bin/conv_apex_manifest proto ${manifest_dir}/apex_manifest.json -o ${manifest_file}
# Create the file_contexts file
file_contexts_file=$(mktemp)
diff --git a/docs/howto.md b/docs/howto.md
index 270d12f..a704249 100644
--- a/docs/howto.md
+++ b/docs/howto.md
@@ -520,8 +520,8 @@
```
$ java \
- -Djava.library.path=$(dirname out/host/linux-x86/lib64/libconscrypt_openjdk_jni.so)\
- -jar out/host/linux-x86/framework/signapk.jar \
+ -Djava.library.path=$(dirname out/soong/host/linux-x86/lib64/libconscrypt_openjdk_jni.so)\
+ -jar out/soong/host/linux-x86/framework/signapk.jar \
-a 4096 \
<apk_certificate_file> \
<apk_private_key_file> \
diff --git a/proto/apex_manifest.proto b/proto/apex_manifest.proto
index 9f93594..22fb7d7 100644
--- a/proto/apex_manifest.proto
+++ b/proto/apex_manifest.proto
@@ -33,8 +33,7 @@
string preInstallHook = 3;
// Post Install Hook
- // This feature is not supported.
- string postInstallHook = 4 [ deprecated = true ];
+ string postInstallHook = 4;
// Version Name
string versionName = 5;
@@ -57,12 +56,9 @@
// marked as "is_jni: true" from the list of "native_shared_libs".
repeated string jniLibs = 9;
- // List of libs required that are located in a shared libraries APEX. The
- // Android platform only checks whether this list is non-empty, and by default
- // the Android build system never sets this. This field can be used when
- // producing or processing an APEX using libraries in /apex/sharedlibs (see
- // `provideSharedApexLibs` field) to store some information about the
- // libraries.
+ // List of libs required that are located in a shared libraries APEX.
+ // Format of the content is 'library:hash'.
+ // Example) libc++.so:83d8f50...
repeated string requireSharedApexLibs = 10;
// Whether this APEX provides libraries to be shared with other APEXs. This
@@ -83,3 +79,4 @@
// Indicates that this APEX can be updated without rebooting device.
bool supportsRebootlessUpdate = 13;
}
+
diff --git a/shim/build/Android.bp b/shim/build/Android.bp
index 99121d2..2fa99bf 100644
--- a/shim/build/Android.bp
+++ b/shim/build/Android.bp
@@ -265,7 +265,6 @@
":com.android.apex.cts.shim.v2_with_post_install_hook",
":com.android.apex.cts.shim.v2_sdk_target_p",
":com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p",
- ":com.android.apex.cts.shim.v2_apk_in_apex_upgrades",
":com.android.apex.cts.shim.v2_rebootless",
":com.android.apex.cts.shim.v3",
":com.android.apex.cts.shim.v3_rebootless",
@@ -448,7 +447,7 @@
targets: ["com.android.apex.cts.shim.v2_signed_bob_rot"],
dest: "com.android.apex.cts.shim.v2_signed_bob_rot.apex",
},
- cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot) --rotation-min-sdk-version 28 --out $(out) $(location :com.android.apex.cts.shim.v2)",
+ cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot) --out $(out) $(location :com.android.apex.cts.shim.v2)",
}
// v2 cts shim package signed by bob + lineage + rollback capability
@@ -466,7 +465,7 @@
targets: ["com.android.apex.cts.shim.v2_signed_bob_rot_rollback"],
dest: "com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
},
- cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot.rollback) --rotation-min-sdk-version 28 --out $(out) $(location :com.android.apex.cts.shim.v2)",
+ cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot.rollback) --out $(out) $(location :com.android.apex.cts.shim.v2)",
}
// v3 cts shim package signed by bob
@@ -501,7 +500,7 @@
targets: ["com.android.apex.cts.shim.v3_signed_bob_rot"],
dest: "com.android.apex.cts.shim.v3_signed_bob_rot.apex",
},
- cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot) --rotation-min-sdk-version 28 --out $(out) $(location :com.android.apex.cts.shim.v3)",
+ cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot) --out $(out) $(location :com.android.apex.cts.shim.v3)",
}
// This one is only used in ApexdHostTest and not meant to be installed
@@ -583,16 +582,3 @@
installable: false,
updatable: false,
}
-
-// Apex shim with upgraded apk-in-apexes
-apex {
- name: "com.android.apex.cts.shim.v2_apk_in_apex_upgrades",
- manifest: "manifest_v2.json",
- androidManifest: "AndroidManifest.xml",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.cts.shim.key",
- prebuilts: ["hash_of_dev_null"],
- apps: ["CtsShim", "CtsShimPrivUpgrade"],
- installable: false,
- updatable: false,
-}
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v1.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v1.apex
index c2dc28f..791d0dd 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v1.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2.apex
index 880ab4a..0a26d23 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_file.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_file.apex
index 8c84cd5..5ed2c7e 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_folder.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_folder.apex
index b519bbe..133f7f7 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
index 38e2339..6ce5397 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
deleted file mode 100644
index 3d7bf51..0000000
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
+++ /dev/null
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex
index f4bc7e8..4228ffe 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_package_name.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_package_name.apex
index 59e9fe1..de090f1 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_no_hashtree.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
index 353949b..162044c 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_rebootless.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_rebootless.apex
index c39b790..9d68887 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_rebootless.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_rebootless.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
index da25328..44f7613 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
index 3eaf372..389871d 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob.apex
index 6f38273..f8fa44f 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index 1969746..9658818 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index be642bf..3440043 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
index 7bebb77..d6f7d8f 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index 8006022..cc214f8 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index 3465dbb..dab82a0 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
index 67743a9..9706f2f 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_wrong_sha.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
index aa1c10c..f305cff 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v3.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v3.apex
index b345bca..3122c96 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v3.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_rebootless.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v3_rebootless.apex
index c3bab7c..0f5134d 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_rebootless.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v3_rebootless.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob.apex
index 4733bad..a83bf51 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index 6972daa..703b641 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/shim/prebuilts/arm/com.android.apex.cts.shim_not_pre_installed.apex b/shim/prebuilts/arm/com.android.apex.cts.shim_not_pre_installed.apex
index 4cda1c6..806ccc7 100644
--- a/shim/prebuilts/arm/com.android.apex.cts.shim_not_pre_installed.apex
+++ b/shim/prebuilts/arm/com.android.apex.cts.shim_not_pre_installed.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v1.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v1.apex
index 030c53b..a94ae75 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v1.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2.apex
index b090a96..a9c2758 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_file.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_file.apex
index c498b32..5ed2c7e 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_folder.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_folder.apex
index e83ec07..133f7f7 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
index 4545b1c..6ce5397 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
deleted file mode 100644
index 298fd85..0000000
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_upgrades.apex
+++ /dev/null
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex
index d911fe0..4228ffe 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_package_name.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_package_name.apex
index 053df91..de090f1 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_package_name.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_package_name.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_no_hashtree.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
index 65a5473..19ec142 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_no_hashtree.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_rebootless.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_rebootless.apex
index 9f94684..9d68887 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_rebootless.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_rebootless.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
index 8fd510c..9929c3d 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sdk_target_p.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
index baae3e3..389871d 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob.apex
index 1e80788..3f2fc50 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index c064928..cf628ab 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index 685f347..ba5af3b 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
index f2329ae..38c073f 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_payload.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index bb2d96e..cc214f8 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index fd00bd5..dab82a0 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
index e7da653..9706f2f 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_wrong_sha.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
index 32bf141..f305cff 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v3.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v3.apex
index 1bd8b1b..7f3e9ec 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v3.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_rebootless.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v3_rebootless.apex
index 2f7a2e5..0f5134d 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_rebootless.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v3_rebootless.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob.apex
index 38fe019..1aeb0b0 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index 68505d5..20f1c85 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/shim/prebuilts/x86/com.android.apex.cts.shim_not_pre_installed.apex b/shim/prebuilts/x86/com.android.apex.cts.shim_not_pre_installed.apex
index 7fd07b5..806ccc7 100644
--- a/shim/prebuilts/x86/com.android.apex.cts.shim_not_pre_installed.apex
+++ b/shim/prebuilts/x86/com.android.apex.cts.shim_not_pre_installed.apex
Binary files differ
diff --git a/tests/Android.bp b/tests/Android.bp
index 956af99..425f2bc 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -87,7 +87,6 @@
apex {
name: "apex.test",
manifest: "testdata/apex_manifest.json",
- androidManifest: "testdata/AndroidManifest.xml",
prebuilts: ["sample_prebuilt_file"],
key: "apex.test.key",
certificate: ":apex.test.certificate",
@@ -221,8 +220,8 @@
android_test_helper_app {
name: "apex_compression_tests_app",
- manifest: "app/ApexCompressionTests_AndroidManifest.xml",
- srcs: ["app/src/**/ApexCompressionTests.java"],
+ manifest: "app/AndroidManifest.xml",
+ srcs: ["app/src/**/*.java"],
static_libs: ["androidx.test.rules", "cts-install-lib", "cts-rollback-lib", "testng"],
test_suites: ["general-tests"],
java_resources: [
@@ -230,89 +229,3 @@
":com.android.apex.compressed.v2_original",
]
}
-
-java_test_host {
- name: "apex_apkinapex_tests",
- srcs: ["src/**/ApkInApexTests.java"],
- libs: ["tradefed", "truth-prebuilt"],
- static_libs: ["cts-install-lib-host", "frameworks-base-hostutils", "testng"],
- test_config: "apk-in-apex-tests.xml",
- test_suites: ["general-tests"],
- data: [
- ":apex_apkinapex_tests_app",
- ],
- java_resources: [
- ":com.android.apex.product.test",
- ":com.android.apex.product.app.test.xml",
- ":com.android.apex.system.test",
- ":com.android.apex.system.app.test.xml",
- ":com.android.apex.system_ext.test",
- ":com.android.apex.system_ext.app.test.xml",
- ":com.android.apex.vendor.test",
- ":com.android.apex.vendor.app.test.xml",
- ],
-}
-
-cc_test_library {
- name: "libApkInApex_jni",
- gtest: false,
- srcs: [
- "app/jni/com_android_tests_apex_app_ApkInApexTests.cpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- header_libs: [
- "jni_headers"
- ],
- stl: "c++_shared",
- sdk_version: "current",
-}
-
-java_test_host {
- name: "apex_apkinapexmaxsdk_tests",
- srcs: ["src/**/MaxSdkTests.java"],
- libs: [
- "tradefed",
- "truth-prebuilt"
- ],
- static_libs: [
- "cts-install-lib-host",
- "frameworks-base-hostutils",
- "testng"
- ],
- test_config: "max-sdk-tests.xml",
- test_suites: ["general-tests"],
- data: [
- ":apex_maxsdk_tests_app",
- ":apex_maxsdk_regular_app_tests",
- ],
- java_resources: [
- ":com.android.apex.maxsdk.test",
- ],
-}
-
-android_test_helper_app {
- name: "apex_apkinapex_tests_app",
- manifest: "app/ApkInApexTests_AndroidManifest.xml",
- srcs: ["app/src/**/ApkInApexTests.java"],
- jni_libs: [
- "libApkInApex_jni",
- ],
- static_libs: ["androidx.test.rules", "cts-install-lib", "cts-rollback-lib", "testng"],
- test_suites: ["general-tests"],
-}
-
-android_test_helper_app {
- name: "apex_maxsdk_tests_app",
- manifest: "app/MaxSdkTests_AndroidManifest.xml",
- srcs: ["app/src/**/MaxSdkTests.java"],
- static_libs: ["androidx.test.rules", "cts-install-lib", "cts-rollback-lib", "testng"],
- test_suites: ["general-tests"],
-}
-
-android_test_helper_app {
- name: "apex_maxsdk_regular_app_tests",
- manifest: "testdata/maxsdk/app/AndroidManifest_normalApp.xml",
-}
diff --git a/tests/OWNERS b/tests/OWNERS
index 93a9224..0ffc7cf 100644
--- a/tests/OWNERS
+++ b/tests/OWNERS
@@ -1,4 +1,3 @@
chenzhu@google.com
jiyong@google.com
-satayev@google.com
yuwu@google.com
diff --git a/tests/README.md b/tests/README.md
index ae42641..1d71d30 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1 +1,4 @@
Integration tests for Apex OS Infrastructure.
+
+Presently, these tests require an unreleased version of the framework, and
+therefore will not likely succeed on a pure AOSP build.
diff --git a/tests/TEST_MAPPING b/tests/TEST_MAPPING
index dd4daa2..d3177a8 100644
--- a/tests/TEST_MAPPING
+++ b/tests/TEST_MAPPING
@@ -7,9 +7,6 @@
"name": "timezone_data_e2e_tests"
},
{
- "name": "apex_apkinapex_tests"
- },
- {
"name": "CtsApexSharedLibrariesTestCases"
}
],
diff --git a/tests/apk-in-apex-tests.xml b/tests/apk-in-apex-tests.xml
deleted file mode 100644
index baa00b6..0000000
--- a/tests/apk-in-apex-tests.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Runs the apk-in-apex test cases">
- <option name="test-suite-tag" value="apk-in-apex-tests" />
- <option name="test-suite-tag" value="apct" />
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="apex_apkinapex_tests_app.apk" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.HostTest" >
- <option name="class"
- value="com.android.tests.apex.host.ApkInApexTests" />
- </test>
-</configuration>
diff --git a/tests/app/ApexCompressionTests_AndroidManifest.xml b/tests/app/AndroidManifest.xml
similarity index 93%
rename from tests/app/ApexCompressionTests_AndroidManifest.xml
rename to tests/app/AndroidManifest.xml
index 428ab69..0644ba7 100644
--- a/tests/app/ApexCompressionTests_AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tests.apex.compression.app" >
+ package="com.android.tests.apex.app" >
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application>
@@ -27,7 +27,7 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.tests.apex.compression.app"
+ android:targetPackage="com.android.tests.apex.app"
android:label="ApexCompression Test"/>
</manifest>
diff --git a/tests/app/ApkInApexTests_AndroidManifest.xml b/tests/app/ApkInApexTests_AndroidManifest.xml
deleted file mode 100644
index 59e7fa9..0000000
--- a/tests/app/ApkInApexTests_AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tests.apex.apkinapex.app" >
-
- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
- <application>
- <receiver android:name="com.android.cts.install.lib.LocalIntentSender"
- android:exported="true" />
- <uses-library android:name="android.test.runner" />
- </application>
-
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.tests.apex.apkinapex.app"
- android:label="ApexCompression Test"/>
-
-</manifest>
diff --git a/tests/app/MaxSdkTests_AndroidManifest.xml b/tests/app/MaxSdkTests_AndroidManifest.xml
deleted file mode 100644
index 1aec150..0000000
--- a/tests/app/MaxSdkTests_AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?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="com.android.tests.apex.maxsdk.app">
-
- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
-
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.tests.apex.maxsdk.app"
- android:label="ApexMaxSdk Test" />
-</manifest>
diff --git a/tests/app/jni/com_android_tests_apex_app_ApkInApexTests.cpp b/tests/app/jni/com_android_tests_apex_app_ApkInApexTests.cpp
deleted file mode 100644
index a948c7a..0000000
--- a/tests/app/jni/com_android_tests_apex_app_ApkInApexTests.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- *
- */
-
-#include <jni.h>
-
-namespace {
-
-bool fakeMethod() { return true; }
-
-jint com_android_tests_apex_app_nativeFakeMethod(JNIEnv * /*env*/,
- jclass /*clazz*/) {
- return (jboolean)fakeMethod();
-}
-
-static JNINativeMethod gMethods[] = {
- {"nativeFakeMethod", "()Z",
- (void *)com_android_tests_apex_app_nativeFakeMethod}};
-
-} // anonymous namespace
-
-int register_android_native_code_test_data(JNIEnv *env) {
- jclass clazz = env->FindClass("com/android/tests/apex/app/ApkInApexTests");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
-
-jint JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
- JNIEnv *env = nullptr;
- if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)
- return JNI_ERR;
- if (register_android_native_code_test_data(env))
- return JNI_ERR;
- return JNI_VERSION_1_6;
-}
diff --git a/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java b/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java
index b0989d0..a97293c 100644
--- a/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java
+++ b/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java
@@ -28,6 +28,7 @@
import androidx.test.InstrumentationRegistry;
import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
import com.android.cts.install.lib.TestApp;
import com.android.cts.rollback.lib.RollbackUtils;
@@ -146,6 +147,8 @@
// Trigger rollback
RollbackInfo available = RollbackUtils.getAvailableRollback(COMPRESSED_APEX_PACKAGE_NAME);
RollbackUtils.rollback(available.getRollbackId(), UNCOMPRESSED_APEX_V2);
+ RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
+ InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
}
@Test
diff --git a/tests/app/src/com/android/tests/apex/app/ApkInApexTests.java b/tests/app/src/com/android/tests/apex/app/ApkInApexTests.java
deleted file mode 100644
index f069378..0000000
--- a/tests/app/src/com/android/tests/apex/app/ApkInApexTests.java
+++ /dev/null
@@ -1,90 +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 com.android.tests.apex.app;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class ApkInApexTests {
- private final Context mContext = InstrumentationRegistry.getContext();
- private final PackageManager mPm = mContext.getPackageManager();
-
-
- @Before
- public void adoptShellPermissions() {
- InstrumentationRegistry
- .getInstrumentation()
- .getUiAutomation()
- .adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- }
-
- @After
- public void dropShellPermissions() {
- InstrumentationRegistry
- .getInstrumentation()
- .getUiAutomation()
- .dropShellPermissionIdentity();
- }
-
- @Test
- public void testPrivPermissionIsGranted() throws Exception {
- PackageInfo pi = mPm.getPackageInfo("com.android.apex.product.app.test",
- PackageManager.GET_PERMISSIONS);
- assertThat(pi.requestedPermissions).asList()
- .contains("android.permission.PACKAGE_USAGE_STATS");
-
- pi = mPm.getPackageInfo("com.android.apex.system.app.test",
- PackageManager.GET_PERMISSIONS);
- assertThat(pi.requestedPermissions).asList()
- .contains("android.permission.PACKAGE_USAGE_STATS");
-
- pi = mPm.getPackageInfo("com.android.apex.system_ext.app.test",
- PackageManager.GET_PERMISSIONS);
- assertThat(pi.requestedPermissions).asList()
- .contains("android.permission.PACKAGE_USAGE_STATS");
-
- pi = mPm.getPackageInfo("com.android.apex.vendor.app.test",
- PackageManager.GET_PERMISSIONS);
-
- assertThat(pi.requestedPermissions).asList()
- .contains("android.permission.START_ACTIVITIES_FROM_BACKGROUND");
- }
-
- @Test
- public void testJniCalls() throws Exception {
- System.loadLibrary("ApkInApex_jni");
- assertThat(nativeFakeMethod()).isTrue();
- }
-
- private native boolean nativeFakeMethod();
-}
diff --git a/tests/app/src/com/android/tests/apex/app/MaxSdkTests.java b/tests/app/src/com/android/tests/apex/app/MaxSdkTests.java
deleted file mode 100644
index e149022..0000000
--- a/tests/app/src/com/android/tests/apex/app/MaxSdkTests.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.apex.app;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertThrows;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class MaxSdkTests {
- // these apps are installed via apk-in-apex
- private static final String APP_NO_MAX_SDK = "com.android.apex.maxsdk.app.available.test";
- private static final String APP_MAX_SDK_10K =
- "com.android.apex.maxsdk.app.available.target10k.test";
- private static final String APP_MAX_SDK_31 = "com.android.apex.maxsdk.app.unavailable.test";
- // REGULAR_APP is installed as a normal app
- private static final String REGULAR_APP_WITH_MAX_SDK =
- "com.android.apex.maxsdk.regular.app.test";
- private final Context mContext = InstrumentationRegistry.getContext();
- private final PackageManager mPm = mContext.getPackageManager();
-
- @Test
- public void testApkInApexIsAvailable() throws Exception {
- PackageInfo pi = mPm.getPackageInfo(APP_NO_MAX_SDK, 0);
- assertThat(pi).isNotNull();
- }
-
- @Test
- public void testAppWithMaxSdk10KIsAvailable() throws Exception {
- PackageInfo pi = mPm.getPackageInfo(APP_MAX_SDK_10K, 0);
- assertThat(pi).isNotNull();
- }
-
- @Test
- public void testAppWithMaxSdk31() throws Exception {
- // this app should not be available because it has uses-sdk maxSdkVersion="31"
- assertThrows(PackageManager.NameNotFoundException.class,
- () -> mPm.getPackageInfo(APP_MAX_SDK_31, 0));
- }
-
- @Test
- public void testRegularAppIsAvailable() throws Exception {
- // because this is a regular app, max-sdk should not be checked
- PackageInfo pi = mPm.getPackageInfo(REGULAR_APP_WITH_MAX_SDK, 0);
- assertThat(pi).isNotNull();
- }
-}
diff --git a/tests/max-sdk-tests.xml b/tests/max-sdk-tests.xml
deleted file mode 100644
index afc1ef8..0000000
--- a/tests/max-sdk-tests.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Runs the max-sdk support test cases">
- <option name="test-suite-tag" value="max-sdk-tests" />
- <option name="test-suite-tag" value="apct" />
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="apex_maxsdk_tests_app.apk" />
- <option name="test-file-name" value="apex_maxsdk_regular_app_tests.apk" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.HostTest" >
- <option name="class"
- value="com.android.tests.apex.host.MaxSdkTests" />
- </test>
-</configuration>
diff --git a/tests/native/AndroidTest.xml b/tests/native/AndroidTest.xml
index be00cda..fa189d5 100644
--- a/tests/native/AndroidTest.xml
+++ b/tests/native/AndroidTest.xml
@@ -26,7 +26,4 @@
<option name="module-name" value="CtsApexSharedLibrariesTestCases" />
<option name="runtime-hint" value="65s" />
</test>
- <!-- Controller that will skip the module if a native bridge situation is detected -->
- <!-- For example: module wants to run arm32 and device is x86 -->
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java b/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java
index 6203b9b..e0871df 100644
--- a/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java
+++ b/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java
@@ -16,11 +16,13 @@
package com.android.tests.apex;
+import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assume.assumeTrue;
import android.cts.install.lib.host.InstallUtilsHost;
+import android.platform.test.annotations.RequiresDevice;
import com.android.tests.rollback.host.AbandonSessionsRule;
import com.android.tradefed.config.Option;
@@ -49,6 +51,9 @@
private static final Duration BOOT_COMPLETE_TIMEOUT = Duration.ofMinutes(2);
+ private static final String USERSPACE_REBOOT_SUPPORTED_PROP =
+ "init.userspace_reboot.is_supported";
+
// Protected so that derived tests can have access to test utils automatically
protected final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
@@ -80,13 +85,21 @@
@Test
public final void testStageActivateUninstallApexPackage() throws Exception {
- stageActivateUninstallApexPackage();
+ stageActivateUninstallApexPackage(false/*userspaceReboot*/);
}
- private void stageActivateUninstallApexPackage() throws Exception {
+ @Test
+ @RequiresDevice // TODO(b/147726967): Remove when Userspace reboot works on cuttlefish
+ public final void testStageActivateUninstallApexPackageWithUserspaceReboot() throws Exception {
+ assumeTrue("Userspace reboot not supported on the device",
+ getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
+ stageActivateUninstallApexPackage(true/*userspaceReboot*/);
+ }
+
+ private void stageActivateUninstallApexPackage(boolean userspaceReboot) throws Exception {
ApexInfo apex = installApex(mApexFileName);
- getDevice().reboot(); // for install to take affect
+ reboot(userspaceReboot); // for install to take affect
Set<ApexInfo> activatedApexes = getDevice().getActiveApexes();
assertWithMessage("Failed to activate %s", apex).that(activatedApexes).contains(apex);
@@ -112,6 +125,25 @@
return testApexInfo;
}
+ protected final void reboot(boolean userspaceReboot) throws Exception {
+ if (userspaceReboot) {
+ assertThat(getDevice().setProperty("test.userspace_reboot.requested", "1")).isTrue();
+ getDevice().rebootUserspace();
+ } else {
+ getDevice().reboot();
+ }
+ boolean success = getDevice().waitForBootComplete(BOOT_COMPLETE_TIMEOUT.toMillis());
+ assertWithMessage("Device didn't boot in %s", BOOT_COMPLETE_TIMEOUT).that(success).isTrue();
+ if (userspaceReboot) {
+ // If userspace reboot fails and fallback to hard reboot is triggered then
+ // test.userspace_reboot.requested won't be set.
+ boolean res = getDevice().getBooleanProperty("test.userspace_reboot.requested", false);
+ String message = "Userspace reboot failed, fallback to full reboot was triggered. ";
+ message += "Boot reason: " + getDevice().getProperty("sys.boot.reason.last");
+ assertWithMessage(message).that(res).isTrue();
+ }
+ }
+
/**
* Do some additional check, invoked by {@link #testStageActivateUninstallApexPackage()}.
*/
diff --git a/tests/src/com/android/tests/apex/ApexRollbackTests.java b/tests/src/com/android/tests/apex/ApexRollbackTests.java
index b7cb78b..68f82ca 100644
--- a/tests/src/com/android/tests/apex/ApexRollbackTests.java
+++ b/tests/src/com/android/tests/apex/ApexRollbackTests.java
@@ -52,10 +52,6 @@
private boolean mWasAdbRoot = false;
- private static boolean sCheckedIfCrashingProcessExists = false;
- private static boolean sAlreadyCrashingProcessExists = false;
- private static String sCrashingProcess;
-
@Before
public void setUp() throws Exception {
mHostUtils.uninstallShimApexIfNecessary();
@@ -64,12 +60,6 @@
if (!mWasAdbRoot) {
assumeTrue("Requires root", getDevice().enableAdbRoot());
}
- if (!sCheckedIfCrashingProcessExists) {
- sAlreadyCrashingProcessExists =
- getDevice().getBooleanProperty("sys.init.updatable_crashing", false);
- sCrashingProcess = getDevice().getProperty("sys.init.updatable_crashing_process_name");
- sCheckedIfCrashingProcessExists = true;
- }
}
/**
@@ -105,9 +95,11 @@
assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
ITestDevice device = getDevice();
// Skip this test if there is already crashing process on device
+ boolean hasCrashingProcess =
+ device.getBooleanProperty("sys.init.updatable_crashing", false);
+ String crashingProcess = device.getProperty("sys.init.updatable_crashing_process_name");
assumeFalse(
- "Device already has a crashing process: " + sCrashingProcess,
- sAlreadyCrashingProcessExists);
+ "Device already has a crashing process: " + crashingProcess, hasCrashingProcess);
File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
// To simulate an apex update that causes a boot loop, we install a
@@ -261,6 +253,8 @@
assertThat(activatedApexes).doesNotContain(ctsShimV1);
}
+ // TODO(ioffe): check that we recover from the boot loop in case of userspace reboot.
+
/**
* Test to verify that apexd won't boot loop a device in case {@code sys.init
* .updatable_crashing} is {@code true} and there is no apex session to revert.
@@ -281,6 +275,97 @@
}
/**
+ * Test to verify that if a hard reboot is triggered during userspace reboot boot
+ * sequence, an apex update will not be reverted.
+ */
+ @Test
+ public void testFailingUserspaceReboot_doesNotRevertUpdate() throws Exception {
+ assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device doesn't support userspace reboot",
+ getDevice().getBooleanProperty("init.userspace_reboot.is_supported", false));
+ assumeTrue("Device doesn't support fs checkpointing", mHostUtils.isCheckpointSupported());
+
+ File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ // Simulate failure in userspace reboot by triggering a full reboot in the middle of the
+ // boot sequence.
+ assertThat(getDevice().setProperty("test.apex_revert_test_force_reboot", "1")).isTrue();
+ String error = mHostUtils.installStagedPackage(apexFile);
+ assertWithMessage("Failed to stage com.android.apex.cts.shim.v2.apex : %s", error).that(
+ error).isNull();
+ // After we reboot the device, apexd will apply the update
+ getDevice().rebootUserspace();
+ // Verify that hard reboot happened.
+ assertThat(getDevice().getIntProperty("sys.init.userspace_reboot.last_finished",
+ -1)).isEqualTo(-1);
+ Set<ApexInfo> activatedApexes = getDevice().getActiveApexes();
+ assertThat(activatedApexes).doesNotContain(new ApexInfo("com.android.apex.cts.shim", 1L));
+ assertThat(activatedApexes).contains(new ApexInfo("com.android.apex.cts.shim", 2L));
+ }
+
+ /**
+ * Test to verify that if a hard reboot is triggered before executing init executes {@code
+ * /system/bin/vdc checkpoint markBootAttempt} of userspace reboot boot sequence, apex update
+ * still will be installed.
+ */
+ @Test
+ public void testUserspaceRebootFailedShutdownSequence_doesNotRevertUpdate() throws Exception {
+ assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device doesn't support userspace reboot",
+ getDevice().getBooleanProperty("init.userspace_reboot.is_supported", false));
+ assumeTrue("Device doesn't support fs checkpointing", mHostUtils.isCheckpointSupported());
+
+ File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ // Simulate failure in userspace reboot by triggering a full reboot in the middle of the
+ // boot sequence.
+ assertThat(getDevice().setProperty("test.apex_userspace_reboot_simulate_shutdown_failed",
+ "1")).isTrue();
+ String error = mHostUtils.installStagedPackage(apexFile);
+ assertWithMessage("Failed to stage com.android.apex.cts.shim.v2.apex : %s", error).that(
+ error).isNull();
+ // After the userspace reboot started, we simulate it's failure by rebooting device during
+ // on userspace-reboot-requested action. Since boot attempt hasn't been marked yet, next
+ // boot will apply the update.
+ assertThat(getDevice().getIntProperty("test.apex_userspace_reboot_simulate_shutdown_failed",
+ 0)).isEqualTo(1);
+ getDevice().rebootUserspace();
+ // Verify that hard reboot happened.
+ assertThat(getDevice().getIntProperty("sys.init.userspace_reboot.last_finished",
+ -1)).isEqualTo(-1);
+ Set<ApexInfo> activatedApexes = getDevice().getActiveApexes();
+ assertThat(activatedApexes).contains(new ApexInfo("com.android.apex.cts.shim", 2L));
+ }
+
+ /**
+ * Test to verify that if a hard reboot is triggered around the time of
+ * executing {@code /system/bin/vdc checkpoint markBootAttempt} of userspace reboot boot
+ * sequence, apex update will still be installed.
+ */
+ @Test
+ public void testUserspaceRebootFailedRemount_revertsUpdate() throws Exception {
+ assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device doesn't support userspace reboot",
+ getDevice().getBooleanProperty("init.userspace_reboot.is_supported", false));
+ assumeTrue("Device doesn't support fs checkpointing", mHostUtils.isCheckpointSupported());
+
+ File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ // Simulate failure in userspace reboot by triggering a full reboot in the middle of the
+ // boot sequence.
+ assertThat(getDevice().setProperty("test.apex_userspace_reboot_simulate_remount_failed",
+ "1")).isTrue();
+ String error = mHostUtils.installStagedPackage(apexFile);
+ assertWithMessage("Failed to stage com.android.apex.cts.shim.v2.apex : %s", error).that(
+ error).isNull();
+ // After we reboot the device, apexd will apply the update
+ getDevice().rebootUserspace();
+ // Verify that hard reboot happened.
+ assertThat(getDevice().getIntProperty("sys.init.userspace_reboot.last_finished",
+ -1)).isEqualTo(-1);
+ Set<ApexInfo> activatedApexes = getDevice().getActiveApexes();
+ assertThat(activatedApexes).doesNotContain(new ApexInfo("com.android.apex.cts.shim", 1L));
+ assertThat(activatedApexes).contains(new ApexInfo("com.android.apex.cts.shim", 2L));
+ }
+
+ /**
* Test to verify that boot cleanup logic in apexd is triggered when there is a crash looping
* process, but there is nothing to revert.
*/
@@ -321,9 +406,13 @@
assumeTrue("Fs checkpointing is enabled", mHostUtils.isCheckpointSupported());
ITestDevice device = getDevice();
+ // Skip this test if there is already crashing process on device
+ final boolean hasCrashingProcess =
+ device.getBooleanProperty("sys.init.updatable_crashing", false);
+ final String crashingProcess =
+ device.getProperty("sys.init.updatable_crashing_process_name");
assumeFalse(
- "Device already has a crashing process: " + sCrashingProcess,
- sAlreadyCrashingProcessExists);
+ "Device already has a crashing process: " + crashingProcess, hasCrashingProcess);
final File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
// To simulate an apex update that causes a boot loop, we install a
diff --git a/tests/src/com/android/tests/apex/SharedLibsApexTest.java b/tests/src/com/android/tests/apex/SharedLibsApexTest.java
index df49f62..fdeac2c 100644
--- a/tests/src/com/android/tests/apex/SharedLibsApexTest.java
+++ b/tests/src/com/android/tests/apex/SharedLibsApexTest.java
@@ -33,7 +33,6 @@
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
-import java.time.Duration;
@RunWith(DeviceJUnit4ClassRunner.class)
public class SharedLibsApexTest extends BaseHostJUnit4Test {
@@ -512,13 +511,12 @@
assertThat(getDevice().doesFileExist("/data/apex/active/"
+ getInstalledApexFileName(ApexName.SHAREDLIBS, ApexVersion.ONE))).isTrue();
mPreparer.reboot();
- mHostUtils.waitForFileDeleted("/data/apex/active/"
- + getInstalledApexFileName(ApexName.BAR, ApexVersion.ONE), Duration.ofMinutes(3));
- mHostUtils.waitForFileDeleted("/data/apex/active/"
- + getInstalledApexFileName(ApexName.FOO, ApexVersion.ONE), Duration.ofMinutes(3));
- mHostUtils.waitForFileDeleted("/data/apex/active/"
- + getInstalledApexFileName(ApexName.SHAREDLIBS, ApexVersion.ONE),
- Duration.ofMinutes(3));
+ assertThat(getDevice().doesFileExist("/data/apex/active/"
+ + getInstalledApexFileName(ApexName.BAR, ApexVersion.ONE))).isFalse();
+ assertThat(getDevice().doesFileExist("/data/apex/active/"
+ + getInstalledApexFileName(ApexName.FOO, ApexVersion.ONE))).isFalse();
+ assertThat(getDevice().doesFileExist("/data/apex/active/"
+ + getInstalledApexFileName(ApexName.SHAREDLIBS, ApexVersion.ONE))).isFalse();
getDevice().disableAdbRoot();
runAsResult = getDevice().executeShellCommand(
diff --git a/tests/src/com/android/tests/apex/host/ApexCompressionTests.java b/tests/src/com/android/tests/apex/host/ApexCompressionTests.java
index e37bc0d..a09ca60 100644
--- a/tests/src/com/android/tests/apex/host/ApexCompressionTests.java
+++ b/tests/src/com/android/tests/apex/host/ApexCompressionTests.java
@@ -91,7 +91,7 @@
* For example, <code>runPhase("testApkOnlyEnableRollback");</code>
*/
private void runPhase(String phase) throws Exception {
- assertTrue(runDeviceTests("com.android.tests.apex.compression.app",
+ assertTrue(runDeviceTests("com.android.tests.apex.app",
"com.android.tests.apex.app.ApexCompressionTests",
phase));
}
@@ -283,10 +283,10 @@
runPhase("testUnusedDecompressedApexIsCleanedUp_HigherVersion");
getDevice().reboot();
- // Verify that the decompressed APEX has been cleaned up
- String filePath = Paths.get(DECOMPRESSED_DIR_PATH,
- COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX).toString();
- mHostUtils.waitForFileDeleted(filePath, Duration.ofSeconds(15));
+ // Verify that DECOMPRESSED_DIR_PATH does not contain the decompressed APEX
+ files = getFilesInDir(DECOMPRESSED_DIR_PATH);
+ assertThat(files).doesNotContain(
+ COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
}
@Test
@@ -302,10 +302,10 @@
runPhase("testUnusedDecompressedApexIsCleanedUp_SameVersion");
getDevice().reboot();
- // Verify that the decompressed APEX has been cleaned up
- String filePath = Paths.get(DECOMPRESSED_DIR_PATH,
- COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX).toString();
- mHostUtils.waitForFileDeleted(filePath, Duration.ofSeconds(15));
+ // Verify that DECOMPRESSED_DIR_PATH does not contain the decompressed APEX
+ files = getFilesInDir(DECOMPRESSED_DIR_PATH);
+ assertThat(files).doesNotContain(
+ COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
}
@Test
@@ -378,9 +378,8 @@
"Can't find " + COMPRESSED_APEX_PACKAGE_NAME));
assertThat(activeApex.sourceDir).startsWith("/system");
// Ensure previous decompressed APEX has been cleaned up
- String filePath = Paths.get(DECOMPRESSED_DIR_PATH,
- COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX).toString();
- mHostUtils.waitForFileDeleted(filePath, Duration.ofSeconds(15));
+ assertThat(getFilesInDir(DECOMPRESSED_DIR_PATH))
+ .doesNotContain(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
}
@Test
@@ -432,9 +431,8 @@
"Can't find " + COMPRESSED_APEX_PACKAGE_NAME));
assertThat(activeApex.sourceDir).startsWith("/system");
// Ensure orphaned decompressed APEX has been cleaned up
- String filePath = Paths.get(DECOMPRESSED_DIR_PATH,
- COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX).toString();
- mHostUtils.waitForFileDeleted(filePath, Duration.ofSeconds(15));
+ assertThat(getFilesInDir(APEX_ACTIVE_DIR))
+ .doesNotContain(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
}
}
diff --git a/tests/src/com/android/tests/apex/host/ApkInApexTests.java b/tests/src/com/android/tests/apex/host/ApkInApexTests.java
deleted file mode 100644
index 8452e41..0000000
--- a/tests/src/com/android/tests/apex/host/ApkInApexTests.java
+++ /dev/null
@@ -1,104 +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 com.android.tests.apex.host;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeTrue;
-
-import android.cts.install.lib.host.InstallUtilsHost;
-
-import com.android.internal.util.test.SystemPreparer;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class ApkInApexTests extends BaseHostJUnit4Test {
- private static final String PRODUCT_APEX = "com.android.apex.product.test.apex";
- private static final String SYSTEM_APEX = "com.android.apex.system.test.apex";
- private static final String SYSTEM_EXT_APEX = "com.android.apex.system_ext.test.apex";
- private static final String VENDOR_APEX = "com.android.apex.vendor.test.apex";
-
- private static final String PRODUCT_PRIVAPP_XML = "com.android.apex.product.app.test.xml";
- private static final String SYSTEM_PRIVAPP_XML = "com.android.apex.system.app.test.xml";
- private static final String SYSTEM_EXT_PRIVAPP_XML = "com.android.apex.system_ext.app.test.xml";
- private static final String VENDOR_PRIVAPP_XML = "com.android.apex.vendor.app.test.xml";
-
- private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
- private final TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private final SystemPreparer mPreparer = new SystemPreparer(mTemporaryFolder,
- this::getDevice);
-
- @Rule
- public final RuleChain ruleChain = RuleChain.outerRule(mTemporaryFolder).around(mPreparer);
-
- @Before
- public void setUp() throws Exception {
- assumeTrue("Updating APEX is not supported", mHostUtils.isApexUpdateSupported());
- mPreparer.pushResourceFile(PRODUCT_APEX,
- "/product/apex/" + PRODUCT_APEX);
- mPreparer.pushResourceFile(PRODUCT_PRIVAPP_XML,
- "/product/etc/permissions/" + PRODUCT_PRIVAPP_XML);
- mPreparer.pushResourceFile(SYSTEM_APEX,
- "/system/apex/" + SYSTEM_APEX);
- mPreparer.pushResourceFile(SYSTEM_PRIVAPP_XML,
- "/system/etc/permissions/" + SYSTEM_PRIVAPP_XML);
- mPreparer.pushResourceFile(SYSTEM_EXT_APEX,
- "/system_ext/apex/" + SYSTEM_EXT_APEX);
- mPreparer.pushResourceFile(SYSTEM_EXT_PRIVAPP_XML,
- "/system_ext/etc/permissions/" + SYSTEM_EXT_PRIVAPP_XML);
- mPreparer.pushResourceFile(VENDOR_APEX,
- "/vendor/apex/" + VENDOR_APEX);
- mPreparer.pushResourceFile(VENDOR_PRIVAPP_XML,
- "/vendor/etc/permissions/" + VENDOR_PRIVAPP_XML);
- mPreparer.reboot();
- }
-
- @After
- public void tearDown() throws Exception {
- getDevice().disableAdbRoot();
- }
-
- /**
- * Runs the given phase of a test by calling into the device.
- * Throws an exception if the test phase fails.
- * <p>
- * For example, <code>runPhase("testApkOnlyEnableRollback");</code>
- */
- private void runPhase(String phase) throws Exception {
- assertThat(runDeviceTests("com.android.tests.apex.apkinapex.app",
- "com.android.tests.apex.app.ApkInApexTests",
- phase)).isTrue();
- }
- @Test
- public void testPrivPermissionIsGranted() throws Exception {
- runPhase("testPrivPermissionIsGranted");
- }
-
- @Test
- public void testJniCalls() throws Exception {
- runPhase("testJniCalls");
- }
-}
diff --git a/tests/src/com/android/tests/apex/host/MaxSdkTests.java b/tests/src/com/android/tests/apex/host/MaxSdkTests.java
deleted file mode 100644
index d6eadb1..0000000
--- a/tests/src/com/android/tests/apex/host/MaxSdkTests.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.apex.host;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeTrue;
-
-import android.cts.install.lib.host.InstallUtilsHost;
-
-import com.android.internal.util.test.SystemPreparer;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class MaxSdkTests extends BaseHostJUnit4Test {
-
- private static final String APEX = "com.android.apex.maxsdk.test.apex";
-
- private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
- private final TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private final SystemPreparer mPreparer = new SystemPreparer(mTemporaryFolder,
- this::getDevice);
-
- @Rule
- public final RuleChain ruleChain = RuleChain.outerRule(mTemporaryFolder).around(mPreparer);
-
- @Before
- public void setUp() throws Exception {
- assumeTrue("Updating APEX is not supported", mHostUtils.isApexUpdateSupported());
- mPreparer.pushResourceFile(APEX, "/product/apex/" + APEX);
- mPreparer.reboot();
- }
-
- @After
- public void tearDown() throws Exception {
- getDevice().disableAdbRoot();
- }
-
- @Test
- public void verifyMaxSdk() throws Exception {
- assertThat(
- runDeviceTests(
- "androidx.test.runner.AndroidJUnitRunner",
- "com.android.tests.apex.maxsdk.app",
- (String) null /* class */,
- (String) null /* method */
- )
- ).isTrue();
- }
-}
diff --git a/tests/testdata/AndroidManifest.xml b/tests/testdata/AndroidManifest.xml
index e7c5c02..04bc559 100644
--- a/tests/testdata/AndroidManifest.xml
+++ b/tests/testdata/AndroidManifest.xml
@@ -1,26 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.apex.test">
- <!-- APEX does not have classes.dex -->
- <application android:hasCode="false">
- <apex-system-service
- android:name="com.android.apex.test.ApexSystemService"
- android:path="/apex/com.android.apex.test/javalib/fake.jar"
- android:minSdkVersion="30"/>
-
- <!-- Always inactive system service, since maxSdkVersion is low -->
- <apex-system-service
- android:name="com.android.apex.test.OldApexSystemService"
- android:path="/apex/com.android.apex.test/javalib/fake.jar"
- android:minSdkVersion="1"
- android:maxSdkVersion="1"
- />
-
- <!-- Always inactive system service, since minSdkVersion is high -->
- <apex-system-service
- android:name="com.android.apex.test.NewApexSystemService"
- android:path="/apex/com.android.apex.test/javalib/fake.jar"
- android:minSdkVersion="999999"
- />
- </application>
+ package="com.android.apex.test">
+ <!-- APEX does not have classes.dex -->
+ <application android:hasCode="false" />
</manifest>
+
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/Android.bp b/tests/testdata/apkinapex/com.android.apex.product.test/Android.bp
deleted file mode 100644
index df7fc12..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/Android.bp
+++ /dev/null
@@ -1,52 +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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.product.test.key",
- public_key: "com.android.apex.product.test.avbpubkey",
- private_key: "com.android.apex.product.test.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.product.test.certificate",
- certificate: "com.android.apex.product.test",
-}
-
-apex {
- name: "com.android.apex.product.test",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
- key: "com.android.apex.product.test.key",
- updatable: false,
- apps: ["com.android.apex.product.app.test"],
-}
-
-android_app {
- name: "com.android.apex.product.app.test",
- manifest: "App_AndroidManifest.xml",
- sdk_version: "31",
- privileged: true,
- apex_available: [
- "com.android.apex.product.test",
- ]
-}
-
-filegroup {
- name: "com.android.apex.product.app.test.xml",
- srcs: ["com.android.apex.product.app.test.xml"],
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/App_AndroidManifest.xml b/tests/testdata/apkinapex/com.android.apex.product.test/App_AndroidManifest.xml
deleted file mode 100644
index d9aae58..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/App_AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 Android Open 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="com.android.apex.product.app.test">
- <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
-</manifest>
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.app.test.xml b/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.app.test.xml
deleted file mode 100644
index 839d058..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.app.test.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
- <!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<permissions>
- <privapp-permissions package="com.android.apex.product.app.test">
- <permission name="android.permission.PACKAGE_USAGE_STATS" />
- </privapp-permissions>
-</permissions>
\ No newline at end of file
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.avbpubkey b/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.avbpubkey
deleted file mode 100644
index bef1df6..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.pem b/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.pem
deleted file mode 100644
index e3d0e23..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJJwIBAAKCAgEAr38x/rCRXvNcq8I9zjWh8HNcKJOeaFCP52OQKGiaZlRofQ1g
-VGqvFAxWZY81WlitPBQQ/LtGB26bUSsUn3D7Z4VxHKL9zlY3brhqEBTcLRy4kaFS
-LMInAdWbID9cjUfnWvXe5+ELUpqP822T9CsnrnzxgO60HpbqigENs1NtkcFG4Qi1
-vqG6UdRkufyz671+/N/1lttKNySL8OxFZSfPj66XqhEW5kKrLSj3Fa1hOQY3Ml9V
-arLjcxIO9Lx83ns/QiQV6wwgy62zThTyYgPPEeulY8CyurhC8TMLhnGzTY71KmK2
-XrSHSzVqm92NZSI8OCaoDes8JOns0ey4Z2g2Tn0TCcmi27Oe6+2mIMOuxrWP5coc
-KVZ+o/NmeyXoSbM6+NdVhaUBaGdxe2lrrfvsL3Pn7zKZSMadVx+Th+7epLmYUp78
-VWfb7Ub1JCvHDm03Cf29Hv6SOlrXz64p1UnAbWbeUrCcIhhgE/DvUxBgIc+2Epqb
-GGRIp5XYciHFpNoDnWHTU/sDvCdZbz7p0312OFmb3oslzQdT7wTi8lcmWxr16rAD
-ZA8V0IdUngGPUPM6Vi3fNv/78tD+Bo6I2ul5MWgEUO3Vy26fZTWgCGvLa0JkTK9s
-nQilgQPdvrH7ad4HJINK2npWc6gPE0EH4eGifa16ZQ9MC6pZyk7rYNkK/csCAwEA
-AQKCAf9MF9qVk/l0MhD8aDxkLN0KZPqQnXERydybd5AJ9VD9DZxAnIwoDhnbl33e
-izmW8twqMIktDAZRMqQljYhjmZloSXPB9uoVjUx7tXpHfsP4y3s7qbb3sTc4lGWu
-lcqLd6HYzsLXx7whFONVqS19sTiDb6lHPjjbCpSnQc2u832OtT8GU8B556Xh1TXX
-brqUfJWTD4hs4KhNQIts6wUr1xcoNYuNMdu7+yw9aIW54HNHRmqobK2clfQI8MuL
-Ui7SSJ4lD4BxadDOf4I/WNW/qece3g3YMrVMQJjF/FwC70nPVyz2M9bfOWdwNLkE
-3AtyzmVN83TqlBR/7O3CF+Hc9FKW/dLw4u35+2WBmN84WUOv8bx7xaGINcdAKI8Z
-TRe0e1wpmRn/GuO1NusVpTVnBenVCSjWGvDH8+Ggg+xBNshj8ce6IM951Tp94Zos
-ED0E2EPL4ubajk8uRI8uGaCz3424+SwIxEHX4KToKffR3weeRcWzJiz/U4KCyV6p
-qgGybNIiUQRX8jkiXDGDN0dQL8QNzaeIKGPny/JyfmNUqeoJNQIIcGZlQ4WG/srV
-BISYuBTghGO/D+XEOh/3tN8Ftx0QQjqa0EYfd+4GGSvZO764veoFAdvo8rJxXQf8
-PPXH9hxHZQUcnqblCLG2KVxkCB1Up7HyrUTJwUn4clKxAWzBAoIBAQDV+53JfHFJ
-i5EmLnAU6N0QsyyHGnMVkjRx4Eft1qnYwSHJ4HE8y+xRT1I4dpSlifjyQNrApq3j
-6jk8u6m5JYM9jdkaYyZrkx2GWn9TuJE5Q7VRfpVtduMsR6rGfkEpLdGEsoScQ69g
-M0SYQk3gqqz2w74tlPgCoU3c8wXgV66JSJP/6v367e3HSJJW8HzRoukScrBdJRL9
-SPDAdb3+OpM4pzMtkU7vtDU2ACyBESDC8brvmeIZ0ZnE6eyrrkA3VsxrW4mRg02g
-q8SIzUO8ar9L/lXlJj2uMAP4auZUbODmkJ3XHRGDJUpRjRsN/zABY/tfiZecALtR
-EsCgW8B+24UhAoIBAQDR9PuozxeXV2rwG9v+YFor9RtCviC11E9dD/wwtVulR+vn
-8o4qM5wihvLYpESfdP9FtTZt2X90xoleHZZmEa7MXkJgw5w0UUm7xlczXLarOVjv
-0r2ObKsvKaI7I/YkmCdaV5t7dQYDKLHOlf6jXv6HU0IoHyhy7zjAFyARwnZ5DMYu
-0g6W/o7Cez8iHQTgsCkQe28wfR8V6iR1PS1PIYS4sVWdH2/YE6yTeb4MXsoqG2lu
-FpkL4z9j9/n8mFjERX/N29UZuB2IpBPs8y3Xha0lXUn/mZcmUf4O986E49LzGbg/
-F9w/O4GztUuPHnvs6qVuK2AyN8qHOdU/LnF35jlrAoIBABaWdvN75WGEEBBduosa
-gatvnnWsfxV513tl13HtxQQSbwSmYo2uYQW8P8uiCNLom5TG79CCR7zVTrFwhdv7
-b70hqhc0/CtC3kz+ZI5r3ziSQyOVHyTs9dIIxqgpT6uPIJzHU2RDaNHY15bS+PGM
-UrHBu+OH5B4y9MssBCTIXK41MRpErga88uqkaH4w6JwgfEXsQV2zuitudat7QlEB
-0eSbEbXvrsty1GMc5ZXCPxkU90yvi8R58adtogQFYtX0naN/iCgKGjmpqBdgw5Oy
-GPtmn56OyNgITYL9lc63p43vGhpJAT48w3mUUZTKqUCcUz6kgZKAKUXHmvnSdaFu
-fsECggEBANA6HKDWCrqhC0DpEG0fWC7CX2/5Km3LC47rfJ0+MI8iXlfi2pYGK3Ke
-zhiICjrvCQE0cK/PhrXk9XXu+CtwnCC51zEqry+/8tWVJwScjdoQ/SCUrESlh701
-mFz5FHREprrVqjFt5TGa2YVeg3W5j8vcif9Kr44VrP3tsXOLnn39akwjLi8YdbNy
-EjId/6lrbL6Y/LRlU0AjwFa5/sa9ImkeDx/OftkY4g49LnwMQooyN4TkSpNcpJDb
-7gVTfq3hk5gxzw476KaMu+pDX5KhVBB7jhk+VYa+yK5FnH91h9BsEKwaWOgpd0Ao
-rLBbdmKIcNtrj3Mem/EzLUgFIqncHdMCggEAP4FNHcLLWWQFvTog4rUeDeEvVyiF
-sfz5KD8fXDIHwSQRg4877qa96aSuXUUSLIr3/QlZyI/kh9inrLbJTzq9FSf5PJB+
-A1fSKH67H696hZUy04qtQDFt7HVD8UZ/vBn79HO/nGWnnc3hWJTSnniuvBTwxM++
-4//Vnmm5SF4a7gUYczbuHiSG9kltCFSO7SfqaCStsZWdxfxvxD4JYLS5AvZ/eNwk
-oko2AgS29BWySJBV7CT29ch1YHccvm9UEaaJunN10qkufWQ8RFeUk/CGe14f+fR1
-blkU3+rHZppVvNMAsTNoXbcbqfptZb+4IPbPg1lLp9gwETvfMnb4cXVX8w==
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.pk8 b/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.pk8
deleted file mode 100644
index a16e635..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.x509.pem b/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.x509.pem
deleted file mode 100644
index 44a6506..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/com.android.apex.product.test.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3zCCA8cCFFS0AutXdKo2HIVPZD/RDZDd2LqMMA0GCSqGSIb3DQEBCwUAMIGq
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEmMCQGA1UEAwwdY29t
-LmFuZHJvaWQuYXBleC5wcm9kdWN0LnRlc3QwIBcNMjExMTA0MTc0NjI3WhgPNDc1
-OTEwMDExNzQ2MjdaMIGqMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p
-YTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4G
-A1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNv
-bTEmMCQGA1UEAwwdY29tLmFuZHJvaWQuYXBleC5wcm9kdWN0LnRlc3QwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC6Qyaym34nAtGBoH5JwJAxxieNK83Q
-jG4wf56qMX1Kq+NFc+rYqsMebq3Tijc/3CSdE5f/4FE3cXwBJzhUKKDuBjKOGgyY
-YMYrgbdB23LyWlgmuRfUX68MAOAQ9GJrzBhVWKYRn66j6HJ9mEkHxNq0QO1XcSkB
-3K0bNS7rp4rfzOZnGtnGSoDdAjwyaN4NhBxkWTvZ7+LiHQixkL6yxPTtQEEbGh06
-Ni6X9upoByhXVYlaGDhfYhMksSaEVgCQQrXuCbnu9SRwCYfGL6HHeOO2F2XPyIi4
-K4ND490/mlNpk1p225IARQA/PAQcZFgb+++X75/fd/KzI9lcRKR3Gj1DS4giHp5Z
-3PUgB7q/nFJl4UcqkbwkasDC9vgVp7vgjIYJB9jrw4hAfsubsjKkOYbl4WrPGBTa
-Me9K6Bqk5mWUFHKyqt8ztLiJhq62CzE3dK5zo+koixYMHRJoup+7fDNi8O8j5G7D
-JDmAnPMhru/Ey9UQOxSQT+lvl4PRB11qZtmY1BT695IyKs+LxukPPGqOh3qBYt2G
-B2QRwXJVbqrfyMG32t2KY42j053hI4sY5kv+Mmt4tK2xrrWJ6VUJuQKWXoF8+1px
-O2xVXkIjsRpx9+rx5N5Gh29yvFCLsYFikDYFolmVSA+rfQxgQ0I4qUcZWWhYXu9b
-gKoY2pOpwdjDXQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBTdD9Aa179TBSBHJQK
-STQ1m8mX7RTdI854AkcdLrFR+NNukmaV5aep2dDRB6zj2uU8bjRvNLe/KgQROj24
-S4WSHcX2AyjeBHzH28vfbqZJee/a01VVv9id4h7sbN+P4k2kd8K0pMLuDLryu64q
-7qEej2E5eiROUVrgeMUrzmMV3ef4CJfi5Myw1+HEekR4LfaHAbUZJ7A9rmX0N+LX
-ysNj2wSL5Yj/3sn8XvOJU2K4v/1M6JphzJLDT6N+uOmmuzSTk9uh6Aq4WWUjShp9
-6k2NfNffbE+Ds/AgRmkxFMFARCLgdvu1PfjCua6sGnbH5xJvvkXpvipb8vnbmWjj
-EyJi7oPXZFtDyB5wG92q7YA/PCyXRuPG4QXkKSHqCN4An0t+/0VnusUGZyXE6SQc
-6EkLdn3Sm++sZS/Vix7Xn7okHwtN1UR2MOIRsYPNqofeQ4Qnt96vzm5pdHCHa9eu
-5lys3wplCmyyATiWcQqRKJ4jLDaYbErfIb5mK8TQEP5E/Hw/hZvtqk4+fKTt8me3
-SUnLN1LXGhio0m3Os6vv22KL5BIa2kdVUdZpOJh85jUPnJcxaGCt/owNN6gkbfbp
-VWal+dzAw40U3SWqsMETgNUtCj+rHRdoaidnV3dI9dGXWWTK9q2HE6W5aYZxtHrz
-Xrfar3a04h4eewoDgbxeCcz5Bg==
------END CERTIFICATE-----
diff --git a/tests/testdata/apkinapex/com.android.apex.product.test/manifest.json b/tests/testdata/apkinapex/com.android.apex.product.test/manifest.json
deleted file mode 100644
index 59a9184..0000000
--- a/tests/testdata/apkinapex/com.android.apex.product.test/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.product.test",
- "version": 1
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/Android.bp b/tests/testdata/apkinapex/com.android.apex.system.test/Android.bp
deleted file mode 100644
index 7282270..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/Android.bp
+++ /dev/null
@@ -1,52 +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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.system.test.key",
- public_key: "com.android.apex.system.test.avbpubkey",
- private_key: "com.android.apex.system.test.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.system.test.certificate",
- certificate: "com.android.apex.system.test",
-}
-
-apex {
- name: "com.android.apex.system.test",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
- key: "com.android.apex.system.test.key",
- updatable: false,
- apps: ["com.android.apex.system.app.test"],
-}
-
-android_app {
- name: "com.android.apex.system.app.test",
- manifest: "App_AndroidManifest.xml",
- sdk_version: "31",
- privileged: true,
- apex_available: [
- "com.android.apex.system.test",
- ]
-}
-
-filegroup {
- name: "com.android.apex.system.app.test.xml",
- srcs: ["com.android.apex.system.app.test.xml"],
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/App_AndroidManifest.xml b/tests/testdata/apkinapex/com.android.apex.system.test/App_AndroidManifest.xml
deleted file mode 100644
index b990458..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/App_AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 Android Open 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="com.android.apex.system.app.test">
- <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
-</manifest>
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.app.test.xml b/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.app.test.xml
deleted file mode 100644
index 08f4843..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.app.test.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
- <!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<permissions>
- <privapp-permissions package="com.android.apex.system.app.test">
- <permission name="android.permission.PACKAGE_USAGE_STATS" />
- </privapp-permissions>
-</permissions>
\ No newline at end of file
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.avbpubkey b/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.avbpubkey
deleted file mode 100644
index ef0438e..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.pem b/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.pem
deleted file mode 100644
index 2a70c45..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAtg292H3PefeFs4TuslvGRKy4je+e9x58GqGY/ADAwu5Hj/Id
-Lrn0Q29eeG66fmFCIQaid76eGs8dnPn9cz9GVltzuv0GX/KCn9+vz1/WGZ5KyMDQ
-8C9ZJ1+AtEPdO1QiLcQ2Sv33d84BBAaeypWfqCcADkMzYrU3zVuaLy/dwdX67Y8i
-NhQi50QhKCM26wtYpNB6XL70/awptR8dAA7Q9iFTKTJGBc3/W+lwZvkzyPMCbZs1
-gjywRN2B2nFmn6Cz1GRD43rMGhJGSCgUyjYXCfvmqX80Lxlw8aIsHAueMaoVlq9T
-6xlrfyWGIhqJfdK/dmu+JP7RJO1MjkY0F4BSowvPvCyjXQfX0d7+PFK2C2CARySe
-XNkCSjLzOh0LPRP7ytUKaaYb23AeynzZhSJK9Ux8k1sdDKQw9t8D1ba6Nn06SG1n
-q5jGusFMi2lYgKFsKs6W/kuwP7LnFXpMVMBy0DkIQFmCBbItSvb05DXR0cUAgSa5
-8hOaUFL3l3kLKu9MFZ8CsxBwbu+WqN7Zp3//tZEC9iasPbogaqjQcHUhIBU0VKlH
-V8cbg2PS4nuPb2xYFsNcsP70U2xschjqwhdzticNv5ChMI/yACEHxdRrEDc3dUYt
-anDTjLLgARYdi9wgPo8jZc9nNE1hoaG4Z45aNcWSnlVKSTJOZLH7laVQvykCAwEA
-AQKCAgEAls7hUgI+KYnqnqBi3yr5HhB6PVGfPJRrN+Bfi3nQNGoQq+RjWj6+YlJS
-Tq9jG6fTkOofEdS8wfaKUGwiESL8UDMntmE9s6N/o5I34DBCeixPROe87Qo770rE
-og+Jp0j1mzXrx8mEAyGKY9xcE/NIM5JDEI2Idp8pn5rfKXGcYKKyX7HvJB8gHrWo
-RciOCLz4bGcqxcOFzNGeJySj8FVVsl4+tmSn7s0LWQcSjqqmxDLR8xvcgotldVaM
-5/iCi38jGLEKL9mcU4iJ4eIZ/rw575JVLFlsUAviLLgrk/vnyrpbcdzBRoJjMwtR
-htS2yp0W77Em7RyNAer1PPJY2pL5YCNptr8YLGIetkydo7WOdnRV/W7m5tgn1+hR
-gGSmx0mSu0dY9ugqF6LTpFTs9z5iRfVmlRbrj9SmkLJUfCUbfYssVHYFmI3Z+ge3
-S0Qoc+fuA0FWjGtR+jKzrqdQAGKAG4RGxHsRRrjzYyA9Qd7C/JRcgd2cUAPYCrzE
-LEgr7ym+IZ+y3HSAYUxs6avnhg/aeHpPTDHpYvMoeMo0YT0vT3PwamDpb97H+B9k
-fR9HnbbkWlcLPqvBG3x4DlV2wP5Otksq0QqhBfra8KrgVFZQ0SXVBMz4s/x5V1gl
-CHYq3uwGcMpQbFFh8vjVDUdZIrnHAPNI24JkrCz8ns8EHGjz3ZUCggEBAN4/Gw7+
-1pESmTGk0IXFVe+JFRucnVdW4Fw+0zC0rota7FYv6f4309diEU+r2kN+JmSvtxrx
-H3Yu2BdsSrB3zixC0ucgGkiO3Iy6vwGjDYrbPBJ1Umqhxg9Vzu8zVxt6EF6DP8U4
-K4wHSM+PcAYPGdzo5L2YTj7/P5rP9eGSe+nmn74cI+YXPFRkkZVnnOsW1L9GzYNT
-IeVTQoPNNQ3e6K4QW8dJT/oMYAHB6TsE2a7qrMgevIbWu59bLFEFre6SpnkybZt5
-2yhio6o37Q8s2CTLDn6p03ggDrzayycB4v7cWcRq1jE4Lg8MMRpV1BouBum9d5mP
-43ymezcRUGnAJj8CggEBANGz8p6Vc8ZnxujLEWOm1LXyVbj+GXbDm78vwZs4oLSi
-JdEwlW08Dg/dGWhmJO3y0XtO3oQ2luPD+RRm5oCfrVV/s354bU28QZ56bH1YR8PX
-qgwVdZqzCMxmS/nDQA4icGoWILTuK2o5xoOSu0qjwTkJxRhxji0YuxKTNK5Hf9gP
-YcW8rhyPomgzgocav4JSyDqdE5Pg5G5Sc0ExEcIRNvCJalOreifaKimJ5nsUsoVf
-tuARinz+Esr2OH13BEhEVXu5xeex/q6pJww5AGHkMD29QVfPj7kRjsnR9bBlHgkg
-it5NrSlVDaI7SW94hYeB5xszUiXUsDKCX3RPH6ZZ0JcCggEBANqTyAH0goSFfSNF
-DEw0K3N9J8RTQK+wYtJ2e3BwkyW9U6jkUMbUk0VGTu5Df1NX01y9MGGP+bhbE+3d
-dIugGKaRRilH+nGYB7NkywxKF7yUJ72jo136IvfcFbxNiwMcBtNdVC+cMb/zPhnc
-4XkkCvSoHKeXDoWItj6E/zdNwQ7m4f6wYGIgQhZiHoiJMdxIRQ6mDON2tGR9gXJt
-NRuiOsdOkWUrZjvvRdEUrFR+TbVpWmsrR5F5yWdN3QUGh+yWUKHsBb6elvteH8b+
-X+jH2wA8sNHEJpYDOVtl990yTtUHVEYIKQaZUTs9a2GSPhtNX0EtNV5TFJH4jkA3
-iBWphDMCggEAHKaTTWtp5/+hw4iLFaxjf4BeiendnMZY7yQdNZHlEwjcVdpncAc2
-fKBeqk7aWNBGIqzB5hp3PyM1Ur5EW+p1CitqYKsfc/F2napoTC/VjkJW71O3P62a
-VCLd2n/8rnGyHixrx4yKzfaa0rsnb6kz6xEUpqRNIogwdvc5yV3nb6OaXiPLPge5
-zrbK7J6Q78NTq/5uAFRHoXMOYCfOH0+uy+paZpgVFoDOJeK7ZLGNOn+7Qp3i5/Tm
-qGg/i5TJNv5vF3poOaGuBDsEJL1c+gLtPGIxHUg0gLqPYa+X+8O0+NZDYuAF+pGu
-TS4AeIRk6gCrjKHUZWrLr/r0A7YTwuyefQKCAQAYHLBC8GJyZ4XKa710Z8E6pyPQ
-8O6gKDCn9dwOPU/MySmjCzy1WN907qfaUOAu8V8lwbrgleabx55qm5mgJvgeACJV
-SRs3R6xGBeglD9p8ffdLJpl+H6ToD7LprsidnoJ86JzdujnZ0n11I+LFJNSx9so/
-mnBtYII7GmDo5e+whi9mBKy9HfmzjIY0SsPx3d3UGLhyYsd3GlIJVlwpMYMNzzKO
-vPG/zlSr6nVuwErc4lISP+v8ThuCNX2iCJ8T304utIm8f9xnWXGVgl2WYWqpKWlV
-YbMWY9X+U46jr9ZdwUeGdQFYIwuIHJ2OEXUPfm12zW5ZyNvvIcaN4u75XlKT
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.pk8 b/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.pk8
deleted file mode 100644
index 025f2cd..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.x509.pem b/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.x509.pem
deleted file mode 100644
index 3c7bb6f..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/com.android.apex.system.test.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3TCCA8UCFDZWDufIf2NnqQxJ6twoAcosGjeiMA0GCSqGSIb3DQEBCwUAMIGp
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
-LmFuZHJvaWQuYXBleC5zeXN0ZW0udGVzdDAgFw0yMTExMDQxNzQ2MDZaGA80NzU5
-MTAwMTE3NDYwNlowgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5hcGV4LnN5c3RlbS50ZXN0MIICIjANBgkq
-hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAugO3YGqR0dJFmL2H7QDOiSHYPGOvMZD0
-udb0YM0wEcvq8MKxakhJuprrQPITIrA/19EbsPnVW2dVgg5Ss0O1pXMpsGL7CppS
-pLJOkNWHnPtAe8BkUGLJmUrqyYLygyM2iJ8J32Q6oyFV/Wxfk5tNTLL9bl3SrM/V
-0nrLkEmt0yvTh8kxdc/41oYPbUSaDbfk/zkiK1hkJaraqPaCir+Pt/dogwjyFyGy
-8+DkTDZFaG749ONASGJUfYptkHyVPGvbCY0MkVvUB+b7Z2n55LHJoQL+Xypr4364
-ShOHGvSsHcfM3UkaH8lRh59zd0xRcGARA71vclNBBrzNTINsd8jvh/UGdt1Ncedr
-gFC+mDnkdphMF3LeAtim1hnZ96h1pDNvTzLbygoSoquBrHRbQLnhjrzCRII3xLxQ
-GSdPLXUOA/8S7hf154H9RIwdiRyZ9hTYcjVPPXeKkqhR0Pb0cnlAncgd74dHKyIj
-QGlGTiih3jP9aYqQBCZQoNhiuQJaG3n2XgddPr5FnmFsssmSNGCbIRlhkbh9dCWx
-gQmA8fbuzzDTp2Wlcpe4dcEhIpHK96bBn439n/1LK8Ffn8K77+MDqz0Yic/Nuolg
-EyUu8kephLXoCJI85IhclOr9hrCQnlA3jMQmF0XXxh3pKXejbI3Y1sMHjmOBiyYt
-rIdmfWDiO5ECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAnYLicSFfR+sa+mXNzgn3
-jdUtilK5L97f1OcvSzC0e0Zc87iZGP1A/6CxjVousa9s+z4Emi80bTUmSDH2K7pr
-BRyUU4U9kUCEtnGxi9OUDdX9hYloWkJx4Ub83cjzCRZYKNo4mKSBs4Q/MuiJ+/Op
-LbHCDYu6H49lHzfDe+ELhiBXrWSbmDVK8NFizN/eJhAyX/DCqkmdZ+AjUqSfZfUs
-WcozlWBF8hIQ1dKUQOQSCUzqbHXZwC8y03DuLtWIhZ6SXOdD1uSvvdaWP6IjzuzF
-WRiFlO3Rrxf80RKnQWe2JE1Nautb5RCNdfNUJTowFBvdLFc+LQeHOTZ3SILn64wu
-zPWVLUx4n/oNPNJAfLxTtXH1nzhVkgYIdrvm/2lOWfLCvVDLncGULm8+w3MWY9oX
-Fq8CMhKx9Uj+vleQX5yV4TenW92/51ATXCSN3w8Wk1OBH+pzWzFFjRIyYOPa1oqv
-Xs1/HJSK3FZcjKY+W5qSSXU7RptAZh8/1HA9oP12nYsHm3Aa9G1VDrFw34rMMz13
-QN17B72y0hoPs1Fm9vI0qDy+lAgnq6HNIrgrEUDtlXYaDZcCaPgBTFXDoBj4/L7b
-lg/O8MyJ9Tx4b94qfhesgYOwgO/95hY2L3XBI77MbLvJA5VQ6lHfuTsKoPDf4z2/
-XFK/sUlIc3Nig/PVVEo4mxE=
------END CERTIFICATE-----
diff --git a/tests/testdata/apkinapex/com.android.apex.system.test/manifest.json b/tests/testdata/apkinapex/com.android.apex.system.test/manifest.json
deleted file mode 100644
index 35c429f..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system.test/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.system.test",
- "version": 1
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/Android.bp b/tests/testdata/apkinapex/com.android.apex.system_ext.test/Android.bp
deleted file mode 100644
index ebab455..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/Android.bp
+++ /dev/null
@@ -1,52 +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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.system_ext.test.key",
- public_key: "com.android.apex.system_ext.test.avbpubkey",
- private_key: "com.android.apex.system_ext.test.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.system_ext.test.certificate",
- certificate: "com.android.apex.system_ext.test",
-}
-
-apex {
- name: "com.android.apex.system_ext.test",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
- key: "com.android.apex.system_ext.test.key",
- updatable: false,
- apps: ["com.android.apex.system_ext.app.test"],
-}
-
-android_app {
- name: "com.android.apex.system_ext.app.test",
- manifest: "App_AndroidManifest.xml",
- sdk_version: "31",
- privileged: true,
- apex_available: [
- "com.android.apex.system_ext.test",
- ]
-}
-
-filegroup {
- name: "com.android.apex.system_ext.app.test.xml",
- srcs: ["com.android.apex.system_ext.app.test.xml"],
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/App_AndroidManifest.xml b/tests/testdata/apkinapex/com.android.apex.system_ext.test/App_AndroidManifest.xml
deleted file mode 100644
index 08e6e8d..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/App_AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 Android Open 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="com.android.apex.system_ext.app.test">
- <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
-</manifest>
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.app.test.xml b/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.app.test.xml
deleted file mode 100644
index c7da76f..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.app.test.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
- <!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<permissions>
- <privapp-permissions package="com.android.apex.system_ext.app.test">
- <permission name="android.permission.PACKAGE_USAGE_STATS" />
- </privapp-permissions>
-</permissions>
\ No newline at end of file
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.avbpubkey b/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.avbpubkey
deleted file mode 100644
index 0d978b8..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.pem b/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.pem
deleted file mode 100644
index fe56f0b..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEA8rwV0tBSXu3BFaM7+7KS/KpOK6q9yGzqZz4Pg8PUxelI1dBQ
-/Jja6s5ow8NugACWP4pOBXmDj0sGoUE5DrC+03mQKjTibZqrH8AUY6+cE+YQPVdy
-/wEVO1VmO9MXiF+VY+3IBUodtKPMj+jlsRPlIALH20QQY4wygcK9CLQAZe3op5zA
-EOv+BUz1GMxDUqxbmnzRbJimpbXkR2R98/QIBlbqCey0c48fdRykq9zkXWa3GrjZ
-ikW/SYYcv9qQzkJlN8/WUEE69mAH2ny1HQ4KUsfXAvyeNvjt5xQk3DGvzWuNYCRj
-1ptKfGkOVlr4kr8PMpGgY+KpL2gJlN/xc1hRCP3XPfGX5IU0NOa5WjyKfA8CIHzO
-oxa8haifcwkcQvbMy69QD+XZ4Pge8KW7D8+UnBeGU1TqAWz4l2ZPq67/Fb/uLvOo
-0WVdT/cmeSF/NfQnzAwiV/WBzzZWSjNMHhQEEongSg5Gd22QPBd1slgVdUfYNhCi
-iGHVHEGqruYbhXdmAo9UCPLWUrCCjgaANDV6u6/2nge/UCyAx1vPYgHXxMTpTErY
-yqsDacgRhYIFFYaeuDt5qcQs/c1p62GJdAwJwN3ziZvuou4jEopHeaQsWkzL99ai
-NYmWsG8USpshP47OA7vt5dbX++UXwp4QXeZqGz0OShRTNL4CUolq5I++JMMCAwEA
-AQKCAgEAlH0AsKzlptK0ymLH/+o2xr/7//R8Eo6mOjAZ15ZFpChYeQvtbwim6vsH
-1bHI+B7jysz1e53hIBhaXu0CVX1DzyRPT7J4TWpPgqXDE1RLG1Ui3BOR8nMcJObS
-GojAnZkzTyUXtjynvWhybBqh4Fh2UsXAst6JVAxgnUae0yMiFziZmWdnizKCe4Wf
-beMO0BVGGFSA3HjpgPerRQ0xi7nd6triYt3dac/FA6RZDBWd0ZFTM9KeqVqPcQ/M
-qISxDqxJNQI8bW3p/uuyAjNFrBd5szgyzM3yj1hqWHDXN6hhjj1cB9NbC96Fi2PM
-9IDEDSk5x8qUHmZ67tgq/FqeXtxI/RET027E2bxDUc3hJ1pJtx6hh2B6USUnFOnj
-tvSkpUun1KhdhZwnOXg5AEg6rcZNbyl4nhSlsfT/rVNSj3LpPCeoHULozuPbP0PS
-CIJyt5y2Fo5T/VRPokWsqxi768wJHotNuGbqiMbyPKKvL7XZOU08ERapaMxNHxeC
-km4Pjo5s41XxDxGewZxnwy0bAzVhiH8ii0piD8OdxZKF3Mo6+mTd3b+YvgpePDA5
-37NgJDgqV9pvYVQGLDe5qr7ddhgJPqWhFQ0kLQJvbm4gNrBsSDHfYBMm1dn51DZA
-pZk2H99K3n3oaecL3mBOAcvkFjKLvleXzDbQgoSqzdbG9xW0lqECggEBAP7XZ6CE
-VhjDGqSZYneJT+4YvTL3/sfy9OX80yURnG6+q/8VsodUbeXy/Bqfmf5eqtzOA1tP
-6SxOOvnbJkflD3l5e0uKQpsh+yfwSDsKFjRMW2j8D+x9PikCZAX3IrwldugIt3mM
-aKBD2QqIk/VeHSkbLAi61U4njpHCPxkdOAar+heGNR7sVWbaPU2jrxpsZme+O6Lx
-IEGiMBh7KlvIx0lEmaW6CUm8gqtiVx/iSazMCr1O0Cva+i1jfUBrlgMnofFQzZr0
-WbyLTbujxpkjxgFezF8Xwu/J+MHMmwO0c9iKYs4j0FycWN3eZ11iI2SrqAZbdip3
-sVFa6PGitEwr4HMCggEBAPPWlxPbZ9kl0uSaf0kenPoQkAtOtdU4Iso0VEwaEMB7
-mCYqoY4tWFuR2FMTMoibRtvyvGewXQhQ5gLt98a9KQAHXSVrypXvEZ1aHROe2kq6
-+XtR4jKh1+3Iq/br1dDrZPNgYhrSdw3zgpumKsx6rMT00hOjbfMX6EsAHu5biGkJ
-Jo6zJhzwfQPrWknUYF+6HaxTNqDR+q1s0DTu73XWQfSVIevzeHhOvzm2VvsH28se
-uOEqkGvZRq36ZZ7aCOJqP5L3Wa9tZvphmGSFhDU93lVNFupGi2WTLuSkmhRqfxcL
-RziE6Ul82vhhuy0G3wFdSHRS6AykEpRHt286piX1JnECggEAY52sAlD4nsFVXtYe
-aX+hYP8Gpi/OxjYwiN5lYu4ZaijabuH6YXAdbW+oIHgW6Bn1TE6zfTQlf44s+5Iw
-ypW9kMxt579p/d4woRIKChoNR/A5Iza0usrSS5GFq9dJGqbCbj1KCxdZppwe8UEm
-JRne6DyY3+i4jM5lqpB1vclwJxt+rUdm6GmVkJjqsbi0L+4DsbXo9e6vnzhY+Jjc
-m/hF/lv0e5XXH52yrm/Igswf5I31/L4cHaiBdtCXG2FyyFTrtrrRRCsUEOGbRyfj
-7+TN96co2FsfdkBLHuZuCeq2BgVCTjYtsqXjDwdq/FPqZeW7zpBeBoe3JogU2q+x
-Lr1QBQKCAQBG7wEqJKSUNf2gxRUMN1yhHlpY/7/D1D3CpvBy5w5CgHHlgHdY/fX7
-RXUxzZ7gwJMffwCyBUs7FRWkeoefB/46ZOoC7dWUQmTUapeU0pxcKwJSjqKH6i7/
-nGXyQe8EhMXsSvifJuS9aT5weyluLK2/6hyG2/8rPaQ01UcqPfRz4daWoqUOvCMS
-FdBBNAgJMQJa1CZLKGqNMt9q1qtQk1DCjvO8SSqdjQLyDgpFoqac80YDMrequB1o
-lTQkvvbgrtnprg0oDGJtqiCD9ZddSa85D2EALB93IBb/KqcsE0L/eCdy2K9o0mp8
-4SlrUtli8zkVpdydeMly214QfHZDCorxAoIBAAgxpIbntMADhpGPzN7d/XcgcHaz
-+kOxatnVYePxosAQOVPN5GrJzUUZ5rRTpqEoe+j9OJFIR6+p6yHdz9SeACdI2707
-hKoAAfB35CjfH23jGKu9ocMnSu2B7Ssp8NVN9c7iVcvXj6+MihFTxHBwRJq5pRg1
-RXdyZkidmB5vy9kxvVwRWbRQm9env8Eb8yyTCNlDd61FfJBO6gB9llEncj+fILOG
-5fyVq/V/wnm156IXe7C/y0HTwjWWpOT5bFW4cvSy/hp/+fR8Kv19WDRK3GngcnJW
-sGe7PECIYPbKJvuOMt3aP+poeOm9rV5i7f5K+vRdxrDHz7xK4Is/ur1OG6Y=
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.pk8 b/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.pk8
deleted file mode 100644
index e9b17b5..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.x509.pem b/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.x509.pem
deleted file mode 100644
index 516effd..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/com.android.apex.system_ext.test.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF5TCCA80CFFkJTEXUYaClwWvv+oDTGGGDUJE9MA0GCSqGSIb3DQEBCwUAMIGt
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEpMCcGA1UEAwwgY29t
-LmFuZHJvaWQuYXBleC5zeXN0ZW1fZXh0LnRlc3QwIBcNMjExMTA0MTc0NjE0WhgP
-NDc1OTEwMDExNzQ2MTRaMIGtMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv
-cm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQ
-MA4GA1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lk
-LmNvbTEpMCcGA1UEAwwgY29tLmFuZHJvaWQuYXBleC5zeXN0ZW1fZXh0LnRlc3Qw
-ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDU2EVWNLhekkYf1mT8RnED
-9pf7v/1RN65CAFDmNydLsd8S4ef0xiIJEgaOH70T3AinLIq5o9EYJenGkvhLWdB1
-YEMcaNlmIz/HjxFOHwIyzNoUyHOP049ZggW8sCWzrB2srO0Dv9EjIzuA3c8s2cFx
-mKKzarW45CDACoFQ5KXn73LzKc3CI/qBnnMGlzWpCY2VW4rJjUCiSmAg2F6+bC7M
-xu0YPIabo6OL4dFHFI37Zhh8RkbrMyT+C6sA7wJym2X1dIt6NQ7/kDKRwjWAMz9D
-Myt1mg7CiK+rNgWsYJZcPopxvuis4RXppgl2JZhi+31NWlaxgPEOo+u1jUWCJRLG
-z1qjL1icGWB6f3oG2hMpV+QuNCAJyQj7Ixn6zLXjQaV2YngK0PJwKYW+jKc3/w8T
-mF4MsMmPGYg7734VsK/K+IAl5KkcYRMvAbBMJ+cm/V89yKLuWngf73F7AOQn6jyZ
-Puo3y9k7vdIVO1TGKltCx66R+omMwjt8OmqMDPQcaXo1fb1CZbvOEPrGIFn1pdN9
-H7IjszxldJzBSBD4Pee1XyykI4tkEIG4ZvwF7NNSPUPkTIgcu47YASe2Z+aWhAwp
-fyz+0D2NOtEBvjg+jDq1jgr1716DP7h91iwOSDt+/VCmuUzaN2IEeIM7m24/X+iq
-79oUCfEu2sEuNz9LHJONKQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQB0rOMaVXta
-sa8o1ijJkZYu3xR17aZcq5FjiziqF22pkVOKNMLm8/IlSFEYgXFzHdtplslHD6Sm
-0ohITbEOJVarAchphl0WiW9YU9tvEbV06feOBE8UgOkAm6eLW4ahfxKUGtikL3UK
-Cudjjz56uzXoxsJuylwP3e+rhKH4otL7bzEHI7Unmz2eNd5ro67avzIuxCUVKcQL
-ne43YWLvlO0DjUBUXQcYIuhNTaGkgzRwezKZHQCG61LDdTVVrxzh+H3H1A6yYD9h
-BsuTJn3ybuXhS+NGo5PEbSPMN9m6nWPMOhzov0fMp3q78riBERw8K1Ut1v2UWmto
-w6xDV7WBhUWT3U8fvYKni+L0dAEDImCvIMgi7+2ucQUhhIyMkShABlYOrWmgYa9W
-/gljh9yrtMc/r/LEsgf/CUSiMDW/fQZrP9LaApwH5LF0ObXiklrhhC3UT+utlRZi
-9RMvlW7OZQCefEwRAVk/KM69tLZaafKuGFgEtvqRvBqK/NQwsgJ0F6zQpUQ2x0qP
-YIv8qbSJYLybAcm3cYwJ7KZQesdydVgY/AVRzFOoT9T7h4Lx3B/UG054LYW4UoTT
-XQjRK9jufPsLvDIbkf02TX1N5RSp2U5EvViaujUmFLlqQfJZcIo9dGKltVThuBuh
-gFuk3Y7JQVZ0GDt6gpeSLReRjGD1OBAbZA==
------END CERTIFICATE-----
diff --git a/tests/testdata/apkinapex/com.android.apex.system_ext.test/manifest.json b/tests/testdata/apkinapex/com.android.apex.system_ext.test/manifest.json
deleted file mode 100644
index 2249493..0000000
--- a/tests/testdata/apkinapex/com.android.apex.system_ext.test/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.system_ext.test",
- "version": 1
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/Android.bp b/tests/testdata/apkinapex/com.android.apex.vendor.test/Android.bp
deleted file mode 100644
index 8300d6f..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/Android.bp
+++ /dev/null
@@ -1,52 +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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.vendor.test.key",
- public_key: "com.android.apex.vendor.test.avbpubkey",
- private_key: "com.android.apex.vendor.test.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.vendor.test.certificate",
- certificate: "com.android.apex.vendor.test",
-}
-
-apex {
- name: "com.android.apex.vendor.test",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
- key: "com.android.apex.vendor.test.key",
- updatable: false,
- apps: ["com.android.apex.vendor.app.test"],
-}
-
-android_app {
- name: "com.android.apex.vendor.app.test",
- manifest: "App_AndroidManifest.xml",
- sdk_version: "31",
- privileged: true,
- apex_available: [
- "com.android.apex.vendor.test",
- ]
-}
-
-filegroup {
- name: "com.android.apex.vendor.app.test.xml",
- srcs: ["com.android.apex.vendor.app.test.xml"],
-}
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/App_AndroidManifest.xml b/tests/testdata/apkinapex/com.android.apex.vendor.test/App_AndroidManifest.xml
deleted file mode 100644
index 1b3df04..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/App_AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 Android Open 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="com.android.apex.vendor.app.test">
- <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
-</manifest>
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.app.test.xml b/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.app.test.xml
deleted file mode 100644
index 6c68a2b..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.app.test.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
- <!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<permissions>
- <privapp-permissions package="com.android.apex.vendor.app.test">
- <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
- </privapp-permissions>
-</permissions>
\ No newline at end of file
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.avbpubkey b/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.avbpubkey
deleted file mode 100644
index 3ad68fc..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.pem b/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.pem
deleted file mode 100644
index 686044f..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAsZO4GlL/2dGKXPIPaTweLINGRQQoDsZwS1FCR5kYaGj2Wgn5
-cM+HpmMuNAkb7IZYStfG/6mrIydweMHEaW9pr8vMzHC+4EJOCzsDZKTCM+C3UXUQ
-8u8/RT+c48LVPpxpp9YPBS1WXlVJFh5ejQL5dZlSJMiMRsStp4KODi/uy0zo3ULW
-AKStB5cShBUTb8SzzqP0OaPR7q6D0gCxgW+BjmbyoKnM/ba4dXZ/Sqf5LYwHSRub
-nNfUA3lGuFQ8KD4IA+Qt9N4MoPkxpa3/Pjp5rltYUv8WHQYhm6jtFZXQLHgJh/EC
-1kJzFnM2lz/Z70DoGf7XOJ/chv4tT7ft1c4lFhPBjLCPoIsdzbSByYVU3ff0dowh
-Yh3Ec7TtIUL+OsLN8M/LC+uBNUyz1WN/q6+OEY+71NgDgAo9pebzfaH5F9+HqGBH
-7pCqT2tviip6xHcpLdT4Wsu839i44b1l9NI7YIMEXodsdhocicGAjIRlV/bvdMAk
-M5MaIAyt7jqIaJAuUoQ41+aByUFMYqzeDrjnWkXjqQuo0hMl5vUQW+YATLvUxwEh
-IqQx8kmm0IEvgn/wgUDiN2hBEjc/AuFZXPMzk1SKcR6Ia9HwMRuWh2BkF5xmb+v1
-iZeB/cew5OZM2Al3cJ5eBbAXsLDvM3P4NlUh8Mb6jPM5Cyru0KQIXUGWq9cCAwEA
-AQKCAgBTGYrFHuRGPY3fcxONLqn8MK6Yq5pHV8vDI1K+CMHoUn4+on5NsYCMd8tu
-ZHjh1fjJhXLFv9OrjtBOYncU1COENf4wCe75KW42STaMSaHr/xQqlXsKBLX6JQu5
-djquoym6dizvQkkxuf2K0Ulz+dldlBNhzUv/7hhJ1Im/z+SS1PoAWT+ma2nhrGvo
-zagb3NQ8NnOa6bPbW2Wqx9JJfTIGvtx6HRwl+vUVWw+0kyjDjMz4BGhtHH9F5OIY
-bqr8NhMwJv7uoV8NkbAPFX7l0x2QX4TUyjTB/lWJ76KLQGF7/eyP5lRqigwrjF0W
-qLXHBfvX9m8nO4BK1/XCYZN2Q5MMmmGVc/9RXhYed2Zv+UaMBODlbu4SZqNiQcqU
-9VlYQiwK84pLbCV2pVDLzQSdFFHBJuRcOuTstZF6trQU4EKX+VDilCc4oGxHcShH
-NCZXiLsuxLqxNKPRzh1Hg1wMdid8jUO0EB7mZlpfnoFNuA35ll/FffRtV8iSKVi+
-MCR0+AK2cWN34K+FQolVZh3fIs2OL8QvGc/KRYQjo/yelsyrzEhkdCW+DQ/X2Bq1
-VzhOc/mPZvI1eHLyc6gigOIDUylxbink9r34Scbz8W5WEEcuOxMQGu5ZgXg0caSU
-Ce3+ChTt2tZFvRMeHiKk1RApWONYP+VVgjQfkbdyljgup6/YgQKCAQEA6ii7+Q5T
-/xP/z6TVLpHlaQq61WGY/Fd4mp5NphP3PrZ+tGnyzpDV4w1Sf8EAIICZVszklTep
-No3XMQef/p5MvgWBdGbdXtPH9bfLoHbG12HpmRnbKZT18YhlW0RpJWNTCiEgNdAh
-C/fAz7NJ+SFFistRn6hslY4CqljOBSBYuPf/FwECG50viRCCwF5GXooDz3iObbaH
-IFwm28FaaflPYfckqm8S1rcH1Yr4CDDG/dw8NhA/0lpCig3zGcu1x4cuyQsK0ZuK
-zJ0Jahxzj8HYlLpvyc2b0LMp54lMs83HvW0gJMhyEG0Er+eDQDbje2lFImhxqq3K
-1k+kaGNdERFBlwKCAQEAwiPqDdVpHbe/LG7G2V/FPHXOC7YERdim9AmScm8Hcf4L
-UJUNI7WgfT72oiHmlzexsh0UrXa1oEIUzw5zol/GWUTRWH6Wvo5ExT5oESbtJWtV
-sml/HPWmys7pCq5hgwZj7Rhal5ooWpsZJ1mEEycCkXVdZqJMD0CfjQd5zMtK19L/
-tjkvZfr/FmTCgSswqYYJ6oh2T5ef+Gb+U3yCh09/KJlbN1Ebgc4uCourUJ9kwN//
-Fq0rUwU6rrbbgDsKBD5DaOu+vfSGVsqY63IeT4RzajD6ZiG3APtedPn/GODo4YfI
-ES0y1cqDyyJbmxfsHOKsIiH1bKPpKYRIsPuhAfKvwQKCAQBmlgIEUyqpjfF83xIm
-nPSM2I6R/Xgw1YGY+9G4+PZRG1LXZ7NgnEOYfbWvErcjhjOnu4xJc2FG7U1hxZ1q
-x5+HgJH+lTJW4SGxnRww6Nikc9kLojBKP2CguMju+0G1h5ZR0cFy0gQoYhqu5DV8
-V/9Hl1vjPr6Tpuu0BcP8qvcz0jKHuYFa57pzqjAeZy8dLAoPUxnTJyx8GONNU6Bw
-3TDSEpyVrqPqPbXI8GFJ9VS400vtw6CyX6jXItVmb8Dr8WWl3piWzDY6/nGpc12N
-lbd1MVjYaKPjAxtQvO5Ft9nSO4ThmI+gcqKjDiKKd4GiB7SqJmfmBs3epnW45g9X
-8t9xAoIBAQDBryDn0jy/qDyy8IW0Aib9ba414s6afE3787zGK9zqrf/N0hY8xQwr
-R/C4ykeKH8dJIlgpwt/q1WJ7PDjDCvgQwWZ1+j0cOUWE3wDl88bt6QqjJzrowm83
-sHuw605fcLWqqfxfeS2/TzMmHdl1Xhri0YtwRITLRram9YlfdoXhkiEJRD30aReq
-2LVwNo2i4xXrhV87gtLW+LHMytBSfE4pS+5D3sgplXA7lyJAGfVjs1WD4xnxBquH
-+Og+IyiYGSIZf/BZBKYt2ov7gWuZ+1NF4z09PW+dLCsNWwhUYrYToupHsKchwZwA
-wfNQZOpr2vzORMDcNR7+C3qWD0SPc/ZBAoIBAQDRnG1oseVuZvk2GkiaSYmF4DJi
-NUcHSuDmNV6wnczgn/csOXxE4ZCtnf6wT4G4yd+kHVEAEOEKF5EfdnrTGuBRpAdG
-LyzYoFc7HLo2aY+JyDo0FBNLj3w3dD0YI24xXst+d7fl3rCKF7ZdDNI2tqI89vgb
-71mz4LXOECIEDaww/8vmq24X+Mqh2QugpoHgRS+LNiZZozqRIZf2BY+gjEmCynWd
-G3gbuj6xm0nEmXxuyR8CAH/ZeFn63HQBHJLTVqId1GbD+u2JEkZEQYOyfCwfk/sG
-v92TIn3qDRUF12HYdSOOZNURXJBfiFta1gsmNePDr8KRnKAY35p0HlSY43Vo
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.pk8 b/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.pk8
deleted file mode 100644
index 318020b..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.x509.pem b/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.x509.pem
deleted file mode 100644
index 048a4f8..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/com.android.apex.vendor.test.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3TCCA8UCFF9h0n91axJ62gD/xssXeSrUmAvdMA0GCSqGSIb3DQEBCwUAMIGp
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
-LmFuZHJvaWQuYXBleC52ZW5kb3IudGVzdDAgFw0yMTExMDQxNzQ2MjFaGA80NzU5
-MTAwMTE3NDYyMVowgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5hcGV4LnZlbmRvci50ZXN0MIICIjANBgkq
-hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt7zWvwuFCqqc8C7aMlkJRHENiAm9E52I
-1xAtlmUWAgQkkubPp91oY2yWTE0CH5WELis7iaBeZVIhuoDv1IvYHmIU/Jjd2g55
-vFmAzgJQV6b8h6sifJWqj0dkxgEMUalqYzbpQTcqSalypTEzxBPRWk97qPcZUoUJ
-MLLeCJtXdCdfCFXdUV+k3caMfID3xxXWGwms4DYJFAAbHVdDtfJkQ7nnad4PFK0+
-96p8piYqxG9b76/r4XNmpBQn4Fg/2/BTG1LRBTinJkk4OeCdnaAzlBIgcH3FXT77
-Zg+vqTsbNCaC7CrOAFU7KT50+kCSm65+CUPv+se+yiBBf6b8h93nV4UubyCFNQtr
-9+6I3IQxZJ2ArjJzriBYmuDV6hAEDY6c95ItCveEd2tQlWhnYTpOGw7OAC9+A2m+
-CzSGBFdVbloIEWt2MZPChdquxMd1v6t6mJdcFCWa1Ls6khiHlMYpmywyPSVyC5RA
-q5eG24vXGP0M5PhECgHaWVevrKVYcUyzWj/CrVxpkMFmejE081OvI3jlDyZSDBHH
-5xwlySWbiR2xNyCri5W+A/4qF+MT4UsqREnajHteHXoD7E3BoLWAlkFHNiclVQmT
-onNjtWEf6+9G49TJJ7xYWFvXC83xGhsaM0C3dZ0z/O1r0deXScSH20CP2A+/J2YW
-ROgQ7NVbxP0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAngWUpDnD9n2Az9V7kl21
-PhKvsQaqad8NDQTAXYFU9JgNmVWk+TBHu1cKD7y06s676Hj+8yxZmi4twNYzVSf+
-pBBNazhGDsCPLUfSMgj8pCoXYxnFok+DrixY7p1fce5s7YZeu4IPUmsidMLO3YhJ
-lit1PmH5sEsFeC5E8OKP++uvOnOjbw5RWZs1t+FFW1RbDXMGTn3fpah+mN/N5Ie0
-t8FA+nghgGwiAx5/mf/B32RHjK+7BeHZZJWj87j3uBXOAkgH7vmcuy1zvlH8huTD
-Xh+rYUZBj0Ik+8iqF9Zj5tQLTuSVtaEiSH4kIvnLeFUYmQZwnnLPhzHB6dcL+KRY
-A4Zztxq6m3/5lA+6i4nHF/woY0cBnCaIirDRqjSzx9zlgk7ko4ZJAbTbEV735AbU
-253C73isnx465/sdiq9bk9/vIi6mj0ZAlPXtGict6XAnmjIqQKMAtJQJ0xB187BT
-PHqbUthMA10N4jey2QkyKVERZP7KyZFiPF99bM6gYemnnpedEawMF3dPSIK0egki
-78/VQVTBC5Uelx8QrIuYzT6EZHuGHIuNlm42WuH8pEOl0oh/jsXWTSiRFE/kQ9Gk
-/7bFLsiRPGSxccKy7QpMYvs08hKgQz3S/n22Wr3zmopVdqKnZ5kLoqpfsE4Ve0ab
-H379betgKB8EGRPjQLdNeI8=
------END CERTIFICATE-----
diff --git a/tests/testdata/apkinapex/com.android.apex.vendor.test/manifest.json b/tests/testdata/apkinapex/com.android.apex.vendor.test/manifest.json
deleted file mode 100644
index 7cbe6f9..0000000
--- a/tests/testdata/apkinapex/com.android.apex.vendor.test/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.vendor.test",
- "version": 1
-}
diff --git a/tests/testdata/maxsdk/app/AndroidManifest_normalApp.xml b/tests/testdata/maxsdk/app/AndroidManifest_normalApp.xml
deleted file mode 100644
index 6b3ca97..0000000
--- a/tests/testdata/maxsdk/app/AndroidManifest_normalApp.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2022 Android Open 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 for a regular app, not part of the apex -->
-<manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.apex.maxsdk.regular.app.test">
- <!-- because this app will be installed as a regular app (not as an apk-in-apex),
- maxSdkVersion shouldn't prevent the app from being installed -->
- <uses-sdk android:maxSdkVersion="31"/>
-</manifest>
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/Android.bp b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/Android.bp
deleted file mode 100644
index a54da03..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/Android.bp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.maxsdk.test.key",
- public_key: "com.android.apex.maxsdk.test.avbpubkey",
- private_key: "com.android.apex.maxsdk.test.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.maxsdk.test.certificate",
- certificate: "com.android.apex.maxsdk.test",
-}
-
-apex_test {
- name: "com.android.apex.maxsdk.test",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
- key: "com.android.apex.maxsdk.test.key",
- certificate: ":com.android.apex.maxsdk.test.certificate",
- updatable: false,
- installable: false,
- apps: [
- "com.android.apex.maxsdk.app.available.test",
- "com.android.apex.maxsdk.app.unavailable.test",
- "com.android.apex.maxsdk.app.available.target10k.test",
- ],
-}
-
-android_app {
- name: "com.android.apex.maxsdk.app.available.test",
- manifest: "AndroidManifest.xml",
- sdk_version: "31",
- apex_available: [
- "com.android.apex.maxsdk.test",
- ]
-}
-
-android_app {
- name: "com.android.apex.maxsdk.app.unavailable.test",
- manifest: "AndroidManifest_withMaxSdk.xml",
- sdk_version: "31",
- apex_available: [
- "com.android.apex.maxsdk.test",
- ]
-}
-
-android_app {
- name: "com.android.apex.maxsdk.app.available.target10k.test",
- manifest: "AndroidManifest_withMaxSdk10k.xml",
- sdk_version: "31",
- apex_available: [
- "com.android.apex.maxsdk.test",
- ]
-}
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest.xml b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest.xml
deleted file mode 100644
index c7dade9..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2022 Android Open 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="com.android.apex.maxsdk.app.available.test">
-</manifest>
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest_withMaxSdk.xml b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest_withMaxSdk.xml
deleted file mode 100644
index 4439eaf..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest_withMaxSdk.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2022 Android Open 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="com.android.apex.maxsdk.app.unavailable.test">
- <uses-sdk android:maxSdkVersion="31"/>
-</manifest>
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest_withMaxSdk10k.xml b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest_withMaxSdk10k.xml
deleted file mode 100644
index d22bf66..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/AndroidManifest_withMaxSdk10k.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2022 Android Open 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="com.android.apex.maxsdk.app.available.target10k.test">
- <uses-sdk android:maxSdkVersion="10000"/>
-</manifest>
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.avbpubkey b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.avbpubkey
deleted file mode 100644
index f4af547..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.pem b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.pem
deleted file mode 100644
index dde5fd2..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJJwIBAAKCAgEAvFhH2F48NE3Cdh98JB/31VsCPF68d+2jHYAG6eqM0lDOOM9p
-nDJZ6EReAQZ7Es8HSnYUCSIfNGmZUvwWMjYLyrXpaBf4kmwiErkHXAh3dn4243Bo
-OtTBiLvvh2KFZjdRhJrnUQRfsFaIaFlr10eLYZv4lMSEPS+wpxJRsAWbHSpqzVis
-mFYPAB/HztmuRsHeWadQp0mwEZD3KYLI3g/q9DKEg+CqordzhOSh4kADgACZpRjf
-mIvqCgTo5c53sl1GoiIWly/LP+Z3QJtJFtNs2cKxAR9XadSXqgCaKReQnsD/dYf5
-PJWT0v21uma+N2bFu0kQEPPZOeJCPyOsbWLwZzQQToL3SRkUjteYfY36RUNHjM5L
-Pqa/wau0UvpCZPHVmg4fh26QPcVCnZpAhwjNnnsXArDjRUuXNPpPNnRaGGic/t5k
-oeHw2LVSw/UKLqzLx2+FtBiu2wiOzuByrlTqiu4fj7hd9B1cPR85VkFyq+kISGHT
-xEp6SDKRuoxGt43QHztocfsiVyZlvN6goOZkHl/Qpgxl8FZDESwA0VvH/5I+yVO7
-JYSKHJLDn01oX2O64G6uymjA/5nwDmjn+Hs5vemduNzjl+Qie0y3ezC+S2TEwRMs
-KIviz4KrcHKntwGk57y99FdBZumgYwBJCVjSt2D+S7Ba9OmhoTUcjKId9x8CAwEA
-AQKCAgBKn3enxH56Aq0ffA4Fihz5jZtvK+HkamUMVSNoHqQ42Ac8/wDLADAbFKti
-IJ02sIwk9m+txrUyYPx8oqBwuHUnlbeqpIS6DtnZLTI7Rqd+bTd2GZ1SYeVkNYIL
-0/8ippxHu9AWi3MWPNLC9VsC6rfQrqlo2AvE6lZFe76dzTrN7XZvccjAeqhq1iym
-Sh0Ar+NXBjGwdkOqUhN7gPPw98GRi0pxrdwtqB2+848oQ1CfsJ0vipFcsWLDIXrd
-QlaudsJ7jqIAuNEAumFZWa01vAMOrFLRLQfHSJHmq2JpEYsdOz575KndVS5ClH8i
-IX8QGEoTkDkrXlIc2waAWbQBiwfQTW/O5PRLd2xp3tFwR5W2or3xxaa6QzzLEd9c
-8cpaRwMwXpRxpXmNvKBoqDYdrKRgLS/vM7bfCFCk4i4poUpeyHHkfziWRs9ahaiT
-dMlrfm73ocqWCmhcHnb/tJAGzdJCkk8TEGd1aMC/CSz/mqr7ik57pxCt0L09lHRR
-IReNDkR189KoIdtnh6kphDZmAuswlkh0C1i4611j5pKH9KYghRHBJ/lnI1fXqnyw
-GcbI1iCSL9Ca+Xvb58HLxnXRqVuKslshXnoZt7SFLvgHvlMRIZwuGti9lb+OTl1c
-UT7So14sVj5z5w7ilV5OmmBNYwGuG25mEAhwSONenwDNLehYUQKCAQEA7yakhv0G
-GOSoRXSgsjfRTxXI1X/WyMIYIKOXjJtkvBTIZGWNyhmfr4jPs3bqi403e0Gc+G/h
-TioEyyOrZ5pcxQ56lqx/S6ybFxH1QEa1OJcBkB4gtw+JLgoGLEr+eO18c+9RJPTY
-Z9nuNJcGsRvJkaSshqgrabbQz27dcL52DWqOop7wc3aUHlK2t9igutyMtfx4cTN3
-wszgXPQiMmTgcKBsUwg3T9CUoEH+EtUnklUO9hs3ePjlpC4JXfjpvNJm8HWOA6vw
-Vy6DExoC870SiLapl3qwKXOEItUmH3r9OxK6gUAH+WhkSWpUzCXSfJ9hhLLdwVEt
-z+gYC1nJqN32XQKCAQEAyZ1K5WiKdj2SgB/jeT+AvxZ9hel6ByHSfbtOKLSBzbTB
-8zAkui5MoK2B3Mho3B1lCCdNbmiY8OiholA9ixo9AFLcNj0FMXiocNntWrPQxGAX
-yzsX5ZdycIDRqPo+NKuEs41H1CjeWB9ieketwqyEjKW+YxBqvk49OM1t50C8pJCC
-ODOwN6PINPcwsIheQHVVqpt3N0If4hgpjYqyhZaTBcEVqlQELyydmDGqyZn0oSI4
-tgy20pxBH7iPQ5aAn7XgWaixT1+Z93zN704tG97RxEglBPZXXyFtWXOiTRIRZqd5
-osmFYkG8kKAFUuOMAnuINabtJo80+fFNq4Lzur+TqwKCAQBOi/2bzHz1LhzKeyzQ
-fB7F/9yvqsZLt9we1DxRVTR3xcevmd9BErts9t1pD1SnsyEW3Y0F2BFDD+/1HGkO
-pRd1LXU8Cbnhi/aAVEid7NtWk9pSkGKkXXjr4yT15UfBRhcLKP4YykZNjbl8EmKD
-RyIkMNbtf0yK8x2QE9StVBEIBQiGBvfopHivoPEcXw0jco7QsvSIEaRzGcFTJmgY
-7yL8OuR5PQiVsWcvX51oaBQQLtm0IWpN1Enwa6Jt9/QlLWHb9nBHanCM4dzxKCjy
-DxaISp5W/1fetW8f1awoyMdlYJhbHUHBO/U8W60wQ/fnMJ3h7LGC7fvC/nLvP3VJ
-fmWNAoIBAAb0o0HY4nYD18sNzpY/R5zQFNKK5Ifcdduam66x04yaQNq3/Xxi3ofo
-lINecqetZ+/pEzXM7AHbtL/ZztW+uP4K3cgNQOGdDQqfqh2n+Hrd6dQ8HK3yFKOm
-/hS7VWwRwslDBYhfRJR7uLUJRghiVUxY54GZbmVUY65TAAirZhazWZrAxcKVpvGU
-2ZwtiDrnEWaKaImCgYEWXlCgyVnsgPQA3lN7BI3wFxvKEt9TrWnluVkmhSQs+d4z
-StYFGjjoWG4fcMaRQMmWB7DK3KmKfWgtKQHL0eXZTGF6qM3J4snM21hvZWenZu8C
-ZkyexxTK2D8pnCLpa+V3mrthEDGQLHMCggEAY3BzWH5dQloMYgExtvfifbNXFKzG
-RdQnmAvLT6Nlv7lKUKTD4O0Hrv0o9a/O+y2qTO7HMsnNNpR/Lq9F93Akt16ILC+9
-zqkM7BjVqAzCc48V/yMGtWPZwcR2he1n8HgbdZkU/93UJNQxtTAgEuEnazh4ZBQg
-jWyy6jyOMMXNsEdHUUmcyN7IdFHAAvzamxmIUImshavxXnGjAXZiLz2Ewg2xVKrl
-ZF4HHPfq/cn/4Ic6sQ8tmppuov5p56DpO6Dl5DFvbtciY+GbaO+Aq2tqT6mg0bjY
-H52Jf53T8TaJQg33+yb9Qu0i2X/2QPODm88O1PO8R2UDXIec6PIYymV0tA==
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.pk8 b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.pk8
deleted file mode 100644
index 12d7966..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.x509.pem b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.x509.pem
deleted file mode 100644
index b5dae43..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/com.android.apex.maxsdk.test.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3TCCA8UCFGPwQqpTEKgDNzlnGNkzYp1wSgKQMA0GCSqGSIb3DQEBCwUAMIGp
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
-LmFuZHJvaWQuYXBleC5tYXhzZGsudGVzdDAgFw0yMjAyMjQxOTA1MzNaGA80NzYw
-MDEyMTE5MDUzM1owgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5hcGV4Lm1heHNkay50ZXN0MIICIjANBgkq
-hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApI7HwWXk3RelSA+I49f8vZSnpw6q9LYn
-NePbT884eBxK7xIkDDXsnxSMvzdh8uT3gt3j87QMzZsv8jpyAa5m5Y0bwCDRTFCw
-IFei4eHRLUZeuybR7l7TI6153OArIiUeDO0gZtxzRXN4t2fjU/qo7bTWjrgfOob9
-KW/TCQQFSAocqZK0x1l+FSs3+o6duMe/LwhT7r+LVLxNxXb7TUbb9TP/NrkN8gt9
-BKLrDUHawpA/S22ELspW/IqGAV689dw01CFSJDquqLnJRMHJ3B9367oBQZdHimue
-gQPOoWyMUxTNAeL3WCZ8Uado8/cuyR7oMaSnfdHaWeUMxsxqh40vu2yfSC3kdjYK
-TkQWOI/byK03jTbTERNjSseSmXZqKnwdIvy9F58XzfeqBPZQwzlGc/Eg/oHvvYGF
-VotRyWBO0nAN9/Bt0kgtg/37y93zemsZ6B6QI5dT4RdInC8b9jQkfw0bmN2VE2P0
-7zLXIBck6K59ZfaMi/4+duzrluxxb7X8FaFMmX3QTpbSnPDeuZij0B0KsLI4ul5u
-ItSMDsNQZiv4729OdiX/AGLD1qQLr0se4AL0jXouMgAKscX3MWxhYMM/QcoHR3Vl
-vLZzO+GaGqirElqPxSu/Cd6xrqN027xk9UHe2t5Hp3HXhEhMNY6AlvzRhHZeRqiv
-Ip4NdGNF7BECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAljWrfEAnT/xLDBlIldFD
-mo/oY9CIXolc1SWZwf/yGUnaXm27hMUO4YYSSRVR3okV2HmDDM4RGzMNeZM6gCWR
-+Eeq8nRU2lv7OXxXYJDKE3q++4/KvvfDohZvJ5I8m9SH6jgmP63D9noaBMnp51XL
-92Zr/sQQngNfSjMTTdIqg+XviEsB+knyhDCK3qrVv9dWMIh2U2jQ6s0nAdv4KLJm
-AkfR0LmjdcZLHwCXpPW3Fr+13xK1wFqH9qrGw3NR2XpxHc6tZu6ZOWdrwQr9Zw+5
-+Dt6MC65VFLXC6qCvG+7NdspFVOBT3uxWIl3ow91TPgVeJgiYGQY/+nI8PtIHlCD
-3CF6eyB7necmc2ee2SQNPFGT0fGajprqYRzzHz3mz/9BsrRp7kMGEakG0dPZsWd7
-sLX5ihklLLdkTg3Fp0g0S0DsE44u6TXiJv4363xsGGTu4b438LZX+kQJ2fWpPFBX
-43CUWCk1zTCpwWwSHZxns1cnlwFnNxl7hnZ9WH7dhrRZXpkylsEyeATNTxBBfdlD
-ngCEbXdNyxs06iFrn+BC44vsJKyZCmnBC03AJMyfaxNutqnFwBwToA9F7d61UzqA
-LeKlnRdt3JI5WdREqHCsbpyv7tgykKlf3vYqjqHKca3gcsCOJFCzAxaz5voA3J+p
-LWUarJ6nfdZVIFm4M6DNUKU=
------END CERTIFICATE-----
diff --git a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/manifest.json b/tests/testdata/maxsdk/com.android.apex.maxsdk.test/manifest.json
deleted file mode 100644
index 25e51f0..0000000
--- a/tests/testdata/maxsdk/com.android.apex.maxsdk.test/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.maxsdk.test",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/shared_libs_repack.py b/tests/testdata/sharedlibs/build/shared_libs_repack.py
index 022d932..31b9a6b 100644
--- a/tests/testdata/sharedlibs/build/shared_libs_repack.py
+++ b/tests/testdata/sharedlibs/build/shared_libs_repack.py
@@ -212,7 +212,7 @@
def _get_host_tools_path(tool_name=None):
# This script is located at e.g.
- # out/host/linux-x86/bin/shared_libs_repack/shared_libs_repack.py.
+ # out/soong/host/linux-x86/bin/shared_libs_repack/shared_libs_repack.py.
# Find the host tools dir by going up two directories.
dirname = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
if tool_name:
diff --git a/tools/.clang-format b/tools/.clang-format
deleted file mode 100644
index f6cb8ad..0000000
--- a/tools/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-BasedOnStyle: Google
diff --git a/tools/Android.bp b/tools/Android.bp
index bdcc289..6b4427b 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -91,46 +91,3 @@
unit_test: true,
},
}
-
-cc_binary_host {
- name: "host_apex_verifier",
- srcs: ["host_apex_verifier.cc"],
- defaults: [
- "libapex-deps",
- ],
- shared_libs: [
- "libhidl-gen-utils",
- "libprocessgroup",
- ],
- static_libs: [
- "libapex",
- "libinit_host",
- ],
-}
-
-sh_test_host {
- name: "host-apex-verifier",
- src: "host-apex-verifier.sh",
- test_suites: ["device-tests"],
- test_config: "host-apex-verifier.xml",
- test_options: {
- unit_test: false,
- },
- data_bins: [
- "deapexer",
- "debugfs_static",
- "host_apex_verifier",
- ],
- data_libs: [
- "libbase",
- "libc++",
- "libcgrouprc",
- "libcrypto",
- "libcutils",
- "liblog",
- "libprocessgroup",
- "libprotobuf-cpp-full",
- "libz",
- "libziparchive",
- ],
-}
diff --git a/tools/apex_compression_test.py b/tools/apex_compression_test.py
index 2a30007..018fc56 100644
--- a/tools/apex_compression_test.py
+++ b/tools/apex_compression_test.py
@@ -74,7 +74,7 @@
host_build_top = os.environ.get('ANDROID_BUILD_TOP')
if host_build_top:
host_command_dir = os.path.join(host_build_top,
- 'out/host/linux-x86/bin')
+ 'out/soong/host/linux-x86/bin')
args[0] = os.path.join(host_command_dir, args[0])
return run_and_check_output(args, verbose, **kwargs)
@@ -152,7 +152,7 @@
host_build_top = os.environ.get('ANDROID_BUILD_TOP')
if host_build_top:
os.environ['APEX_COMPRESSION_TOOL_PATH'] = (
- os.path.join(host_build_top, 'out/host/linux-x86/bin')
+ os.path.join(host_build_top, 'out/soong/host/linux-x86/bin')
+ ':' + os.path.join(host_build_top, 'prebuilts/sdk/tools/linux/bin'))
else:
os.environ['APEX_COMPRESSION_TOOL_PATH'] = os.path.dirname(
diff --git a/tools/apex_compression_tool.py b/tools/apex_compression_tool.py
index a5545f5..3c0f16d 100644
--- a/tools/apex_compression_tool.py
+++ b/tools/apex_compression_tool.py
@@ -89,13 +89,10 @@
cmd.extend(['-o', args.output])
# We want to put the input apex inside the compressed APEX with name
- # "original_apex". Originally this was done by creating a hard link
- # in order to put the renamed file inside the zip, but it causes some issue
- # when running this tool with Bazel in a sandbox which restricts the function
- # of creating cross-device links. So instead of creating hard links, we make a
- # copy of the original_apex here.
+ # "original_apex". So we create a hard link and put the renamed file inside
+ # the zip
original_apex = os.path.join(work_dir, 'original_apex')
- shutil.copy2(args.input, original_apex)
+ os.link(args.input, original_apex)
cmd.extend(['-C', work_dir])
cmd.extend(['-f', original_apex])
@@ -118,24 +115,24 @@
# Set digest of original_apex to apex_manifest.pb
apex_manifest_path = os.path.join(extract_dir, 'apex_manifest.pb')
- assert AddOriginalApexDigestToManifest(apex_manifest_path, image_path, args.verbose)
+ assert AddOriginalApexDigestToManifest(apex_manifest_path, image_path)
# Don't forget to compress
cmd.extend(['-L', '9'])
- RunCommand(cmd, verbose=args.verbose)
+ RunCommand(cmd, verbose=True)
return True
-def AddOriginalApexDigestToManifest(capex_manifest_path, apex_image_path, verbose=False):
+def AddOriginalApexDigestToManifest(capex_manifest_path, apex_image_path):
# Retrieve the root digest of the image
avbtool_cmd = [
'avbtool',
'print_partition_digests', '--image',
apex_image_path]
# avbtool_cmd output has format "<name>: <value>"
- root_digest = RunCommand(avbtool_cmd, verbose=verbose)[0].decode().split(': ')[1].strip()
+ root_digest = RunCommand(avbtool_cmd, True)[0].decode().split(': ')[1].strip()
# Update the manifest proto file
with open(capex_manifest_path, 'rb') as f:
pb = apex_manifest_pb2.ApexManifest()
@@ -157,8 +154,6 @@
# Handle sub-command "compress"
parser_compress = subparsers.add_parser('compress',
help='compresses an APEX')
- parser_compress.add_argument('-v', '--verbose', action='store_true',
- help='verbose execution')
parser_compress.add_argument('--input', type=str, required=True,
help='path to input APEX file that will be '
'compressed')
diff --git a/tools/create_apex_skeleton.sh b/tools/create_apex_skeleton.sh
old mode 100755
new mode 100644
index 60a83df..818e119
--- a/tools/create_apex_skeleton.sh
+++ b/tools/create_apex_skeleton.sh
@@ -1,28 +1,15 @@
#!/bin/sh
-# Creates an apex stub in a subdirectory named after the input package name.
+# Creates an apex stub in a subdirectory named after the package name. Edit the APEX_NAME variable
+# before running.
-# Exit early if any subcommands fail.
-set -e
+APEX_NAME=com.android.yourpackagenamehere
-APEX_NAME=$1
-if [ -z ${APEX_NAME} ]
-then
- echo "Missing apex package name"
- echo "Usage $0 apex_package_name [existing_apex_key_name]"
- exit -1
-fi
-
-# Optional. If provided, uses existing key files and module name.
-# Otherwise, generates new key files using the APEX_NAME.
-APEX_KEY=$2
-
-YEAR=$(date +%Y)
-mkdir -p ${APEX_NAME}
+mkdir ${APEX_NAME}
cd ${APEX_NAME}
cat > Android.bp <<EOF
-// Copyright (C) ${YEAR} The Android Open Source Project
+// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -35,19 +22,27 @@
// WITHOUT 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"],
+apex_key {
+ name: "${APEX_NAME}.key",
+ public_key: "${APEX_NAME}.avbpubkey",
+ private_key: "${APEX_NAME}.pem",
}
+android_app_certificate {
+ name: "${APEX_NAME}.certificate",
+ certificate: "${APEX_NAME}",
+}
+
+apex {
+ name: "${APEX_NAME}",
+ manifest: "manifest.json",
+ file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
+ key: "${APEX_NAME}.key",
+}
EOF
-if [ -z ${APEX_KEY} ]
-then
-APEX_KEY=${APEX_NAME}
-
-openssl genrsa -out ${APEX_KEY}.pem 4096
-avbtool extract_public_key --key ${APEX_KEY}.pem --output ${APEX_KEY}.avbpubkey
+openssl genrsa -out ${APEX_NAME}.pem 4096
+avbtool extract_public_key --key ${APEX_NAME}.pem --output ${APEX_NAME}.avbpubkey
cat > csr.conf <<EOF
[req]
@@ -62,41 +57,14 @@
O="Android"
OU="Android"
emailAddress="android@android.com"
-CN="${APEX_KEY}"
+CN="${APEX_NAME}"
EOF
-openssl req -x509 -config csr.conf -newkey rsa:4096 -nodes -days 999999 -keyout key.pem -out ${APEX_KEY}.x509.pem
+openssl req -x509 -config csr.conf -newkey rsa:4096 -nodes -days 999999 -keyout key.pem -out ${APEX_NAME}.x509.pem
rm csr.conf
-openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out ${APEX_KEY}.pk8 -nocrypt
+openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out ${APEX_NAME}.pk8 -nocrypt
rm key.pem
-cat >> Android.bp <<EOF
-apex_key {
- name: "${APEX_KEY}.key",
- public_key: "${APEX_KEY}.avbpubkey",
- private_key: "${APEX_KEY}.pem",
-}
-
-android_app_certificate {
- name: "${APEX_KEY}.certificate",
- certificate: "${APEX_KEY}",
-}
-
-EOF
-
-fi
-
-cat >> Android.bp <<EOF
-apex {
- name: "${APEX_NAME}",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts", // Default, please edit, see go/android-apex-howto
- key: "${APEX_KEY}.key",
- certificate: ":${APEX_KEY}.certificate",
- updatable: false,
-}
-EOF
-
cat > manifest.json << EOF
{
"name": "${APEX_NAME}",
diff --git a/tools/host-apex-verifier.sh b/tools/host-apex-verifier.sh
deleted file mode 100644
index e732758..0000000
--- a/tools/host-apex-verifier.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-set -x
-
-APEX_UPDATABLE="`adb shell getprop ro.apex.updatable`"
-if [[ $APEX_UPDATABLE != "true" ]]; then
- echo "Skipping this test: device uses flattened APEXes."
- exit 0;
-fi
-
-echo "Pulling APEXes from the device factory APEX directories."
-TEMP_DIR="`mktemp -d`"
-adb pull /system/apex/ $TEMP_DIR/system
-adb pull /system_ext/apex/ $TEMP_DIR/system_ext
-adb pull /product/apex/ $TEMP_DIR/product
-adb pull /vendor/apex/ $TEMP_DIR/vendor
-adb pull /odm/apex/ $TEMP_DIR/odm
-
-set -e
-
-echo "Running host_apex_verifier."
-SDK_VERSION="`adb shell getprop ro.build.version.sdk`"
-TEST_DIR=$(dirname $0)
-HOST_APEX_VERIFIER=$TEST_DIR/host_apex_verifier
-DEBUGFS=$TEST_DIR/debugfs_static
-DEAPEXER=$TEST_DIR/deapexer
-$HOST_APEX_VERIFIER \
- --deapexer $DEAPEXER \
- --debugfs $DEBUGFS \
- --sdk_version $SDK_VERSION \
- --out_system $TEMP_DIR/system \
- --out_system_ext $TEMP_DIR/system_ext \
- --out_product $TEMP_DIR/product \
- --out_vendor $TEMP_DIR/vendor \
- --out_odm $TEMP_DIR/odm
-
-rm -rf $TEMP_DIR
diff --git a/tools/host-apex-verifier.xml b/tools/host-apex-verifier.xml
deleted file mode 100644
index 46ac96c..0000000
--- a/tools/host-apex-verifier.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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.
--->
-<configuration description="Config for host_apex_verifier test">
- <option name="test-suite-tag" value="host-apex-verifier" />
- <!-- This test requires a device, so it's not annotated with a null-device -->
- <test class="com.android.tradefed.testtype.binary.ExecutableHostTest" >
- <option name="binary" value="host-apex-verifier" />
- </test>
-</configuration>
diff --git a/tools/host_apex_verifier.cc b/tools/host_apex_verifier.cc
deleted file mode 100644
index 6afce92..0000000
--- a/tools/host_apex_verifier.cc
+++ /dev/null
@@ -1,262 +0,0 @@
-//
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <action.h>
-#include <action_manager.h>
-#include <action_parser.h>
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/result.h>
-#include <android-base/strings.h>
-#include <apex_file.h>
-#include <builtins.h>
-#include <getopt.h>
-#include <parser.h>
-#include <pwd.h>
-#include <service_list.h>
-#include <service_parser.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <iostream>
-
-using ::apex::proto::ApexManifest;
-
-// Fake getpwnam for host execution, used by the init::ServiceParser.
-passwd* getpwnam(const char*) {
- static char fake_buf[] = "fake";
- static passwd fake_passwd = {
- .pw_name = fake_buf,
- .pw_dir = fake_buf,
- .pw_shell = fake_buf,
- .pw_uid = 123,
- .pw_gid = 123,
- };
- return &fake_passwd;
-}
-
-namespace android {
-namespace apex {
-namespace {
-
-static const std::vector<std::string> partitions = {"system", "system_ext",
- "product", "vendor", "odm"};
-
-void PrintUsage() {
- printf(R"(usage: host_apex_verifier [options]
-
-Tests APEX file(s) for correctness.
-
-Options:
- --deapexer=PATH Use the deapexer binary at this path when extracting APEXes.
- --debugfs=PATH Use the debugfs binary at this path when extracting APEXes.
- --sdk_version=INT The active system SDK version used when filtering versioned
- init.rc files.
- --out_system=DIR Path to the factory APEX directory for the system partition.
- --out_system_ext=DIR Path to the factory APEX directory for the system_ext partition.
- --out_product=DIR Path to the factory APEX directory for the product partition.
- --out_vendor=DIR Path to the factory APEX directory for the vendor partition.
- --out_odm=DIR Path to the factory APEX directory for the odm partition.
-)");
-}
-
-const android::init::BuiltinFunctionMap& ApexInitRcSupportedActionMap() {
- static const android::init::BuiltinFunctionMap functions = {
- // Add any init actions supported inside APEXes here.
- // See system/core/init/builtins.cpp for expected syntax.
- };
- return functions;
-}
-
-// Validate any init rc files inside the APEX.
-void CheckInitRc(const std::string& apex_dir, const ApexManifest& manifest,
- int sdk_version) {
- init::Parser parser;
- init::ServiceList service_list = init::ServiceList();
- parser.AddSectionParser("service", std::make_unique<init::ServiceParser>(
- &service_list, nullptr, std::nullopt));
- const init::BuiltinFunctionMap& function_map = ApexInitRcSupportedActionMap();
- init::Action::set_function_map(&function_map);
- init::ActionManager action_manager = init::ActionManager();
- parser.AddSectionParser(
- "on", std::make_unique<init::ActionParser>(&action_manager, nullptr));
- std::string init_dir_path = apex_dir + "/etc";
- std::vector<std::string> init_configs;
- std::unique_ptr<DIR, decltype(&closedir)> init_dir(
- opendir(init_dir_path.c_str()), closedir);
- if (init_dir) {
- dirent* entry;
- while ((entry = readdir(init_dir.get()))) {
- if (base::EndsWith(entry->d_name, "rc")) {
- init_configs.push_back(init_dir_path + "/" + entry->d_name);
- }
- }
- }
- // TODO(b/225380016): Extend this tool to check all init.rc files
- // in the APEX, possibly including different requirements depending
- // on the SDK version.
- for (const auto& c :
- parser.FilterVersionedConfigs(init_configs, sdk_version)) {
- parser.ParseConfigFile(c);
- }
-
- for (const auto& service : service_list) {
- // Ensure the service path points inside this APEX.
- auto service_path = service->args()[0];
- if (!base::StartsWith(service_path, "/apex/" + manifest.name())) {
- LOG(FATAL) << "Service " << service->name()
- << " has path outside of the APEX: " << service_path;
- }
- LOG(INFO) << service->name() << ": " << service_path;
- }
-
- // The parser will fail if there are any unsupported actions.
- if (parser.parse_error_count() > 0) {
- LOG(FATAL) << "Failed to parse APEX init rc file(s)";
- }
-}
-
-// Extract and validate a single APEX.
-void ScanApex(const std::string& deapexer, const std::string& debugfs,
- int sdk_version, const std::string& apex_path) {
- LOG(INFO) << "Checking APEX " << apex_path;
-
- auto apex = OR_FATAL(ApexFile::Open(apex_path));
- ApexManifest manifest = apex.GetManifest();
-
- auto extracted_apex = TemporaryDir();
- std::string extracted_apex_dir = extracted_apex.path;
- std::string deapexer_command = deapexer + " --debugfs_path " + debugfs +
- " extract " + apex_path + " " +
- extracted_apex_dir;
- auto code = system(deapexer_command.c_str());
- if (code != 0) {
- LOG(FATAL) << "Error running deapexer command \"" << deapexer_command
- << "\": " << code;
- }
-
- CheckInitRc(extracted_apex_dir, manifest, sdk_version);
-}
-
-// Scan the factory APEX files in the partition apex dir.
-// Scans APEX files directly, rather than flattened ${PRODUCT_OUT}/apex/
-// directories. This allows us to check:
-// - Prebuilt APEXes which do not flatten to that path.
-// - Multi-installed APEXes, where only the default
-// APEX may flatten to that path.
-// - Extracted target_files archives which may not contain
-// flattened <PARTITON>/apex/ directories.
-void ScanPartitionApexes(const std::string& deapexer,
- const std::string& debugfs, int sdk_version,
- const std::string& partition_dir) {
- LOG(INFO) << "Scanning partition factory APEX dir " << partition_dir;
-
- std::unique_ptr<DIR, decltype(&closedir)> apex_dir(
- opendir(partition_dir.c_str()), closedir);
- if (!apex_dir) {
- LOG(WARNING) << "Unable to open dir " << partition_dir;
- return;
- }
-
- dirent* entry;
- while ((entry = readdir(apex_dir.get()))) {
- if (base::EndsWith(entry->d_name, ".apex") ||
- base::EndsWith(entry->d_name, ".capex")) {
- ScanApex(deapexer, debugfs, sdk_version,
- partition_dir + "/" + entry->d_name);
- }
- }
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- android::base::InitLogging(argv, &android::base::StdioLogger);
-
- std::string deapexer, debugfs;
- int sdk_version = INT_MAX;
- std::map<std::string, std::string> partition_map;
-
- while (true) {
- static const struct option long_options[] = {
- {"help", no_argument, nullptr, 'h'},
- {"deapexer", required_argument, nullptr, 0},
- {"debugfs", required_argument, nullptr, 0},
- {"sdk_version", required_argument, nullptr, 0},
- {"out_system", required_argument, nullptr, 0},
- {"out_system_ext", required_argument, nullptr, 0},
- {"out_product", required_argument, nullptr, 0},
- {"out_vendor", required_argument, nullptr, 0},
- {"out_odm", required_argument, nullptr, 0},
- {nullptr, 0, nullptr, 0},
- };
-
- int option_index;
- int arg = getopt_long(argc, argv, "h", long_options, &option_index);
-
- if (arg == -1) {
- break;
- }
-
- switch (arg) {
- case 0:
- if (long_options[option_index].name == "deapexer") {
- deapexer = optarg;
- }
- if (long_options[option_index].name == "debugfs") {
- debugfs = optarg;
- }
- if (long_options[option_index].name == "sdk_version") {
- if (!base::ParseInt(optarg, &sdk_version)) {
- PrintUsage();
- return EXIT_FAILURE;
- }
- }
- for (const auto& p : partitions) {
- if (long_options[option_index].name == "out_" + p) {
- partition_map[p] = optarg;
- }
- }
- break;
- case 'h':
- PrintUsage();
- return EXIT_SUCCESS;
- default:
- LOG(ERROR) << "getopt returned invalid result: " << arg;
- return EXIT_FAILURE;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc != 0 || deapexer.empty() || debugfs.empty()) {
- PrintUsage();
- return EXIT_FAILURE;
- }
-
- for (const auto& p : partition_map) {
- ScanPartitionApexes(deapexer, debugfs, sdk_version, p.second);
- }
-
- return EXIT_SUCCESS;
-}
-
-} // namespace apex
-} // namespace android
-
-int main(int argc, char** argv) { return android::apex::main(argc, argv); }