summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:04:35 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:04:35 +0000
commit72642b73a754d41245839523c215258315d750e5 (patch)
tree8d461616163abf73c8b0cd55b31cdbc40e0c2836
parent019ff3c01d4839dbe9d87a3866f78949aca40585 (diff)
parent3b0ffb30ee3666352c7932b283f464880cf24a45 (diff)
downloadapex-aml_tz2_304500300.tar.gz
Change-Id: Ia8d138ec480f72157c64e4205bf1080c4887ebd7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb15
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb7
-rw-r--r--.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb7
-rw-r--r--Android.bp68
-rw-r--r--PREUPLOAD.cfg3
-rw-r--r--apexd/Android.bp220
-rw-r--r--apexd/ApexInfoList.xsd38
-rw-r--r--apexd/OWNERS1
-rw-r--r--apexd/aidl/android/apex/ApexSessionInfo.aidl1
-rw-r--r--apexd/aidl/android/apex/IApexService.aidl48
-rw-r--r--apexd/apex-info-list-api/current.txt45
-rw-r--r--apexd/apex-info-list-api/last_current.txt45
-rw-r--r--apexd/apex-info-list-api/last_removed.txt0
-rw-r--r--apexd/apex-info-list-api/removed.txt1
-rw-r--r--apexd/apex_constants.h22
-rw-r--r--apexd/apex_database.cpp106
-rw-r--r--apexd/apex_database.h174
-rw-r--r--apexd/apex_database_test.cpp32
-rw-r--r--apexd/apex_file.cpp303
-rw-r--r--apexd/apex_file.h45
-rw-r--r--apexd/apex_file_repository.cpp280
-rw-r--r--apexd/apex_file_repository.h139
-rw-r--r--apexd/apex_file_repository_test.cpp506
-rw-r--r--apexd/apex_file_test.cpp306
-rw-r--r--apexd/apex_manifest.cpp5
-rw-r--r--apexd/apex_manifest.h10
-rw-r--r--apexd/apex_manifest_test.cpp2
-rw-r--r--apexd/apex_preinstalled_data.cpp134
-rw-r--r--apexd/apex_preinstalled_data.h34
-rw-r--r--apexd/apex_shim.cpp2
-rw-r--r--apexd/apexd.cpp2695
-rw-r--r--apexd/apexd.h165
-rw-r--r--apexd/apexd_checkpoint.h2
-rw-r--r--apexd/apexd_checkpoint_vold.cpp11
-rw-r--r--apexd/apexd_checkpoint_vold.h2
-rw-r--r--apexd/apexd_lifecycle.h48
-rw-r--r--apexd/apexd_loop.cpp285
-rw-r--r--apexd/apexd_loop.h14
-rw-r--r--apexd/apexd_main.cpp73
-rw-r--r--apexd/apexd_prepostinstall.cpp106
-rw-r--r--apexd/apexd_prepostinstall.h16
-rw-r--r--apexd/apexd_private.h15
-rw-r--r--apexd/apexd_prop.cpp (renamed from apexd/apexd_lifecycle.cpp)31
-rw-r--r--apexd/apexd_prop.h32
-rw-r--r--apexd/apexd_rollback_utils.h28
-rw-r--r--apexd/apexd_session.cpp139
-rw-r--r--apexd/apexd_session.h21
-rw-r--r--apexd/apexd_session_test.cpp126
-rw-r--r--apexd/apexd_test.cpp3603
-rw-r--r--apexd/apexd_test_utils.h230
-rw-r--r--apexd/apexd_testdata/Android.bp348
-rw-r--r--apexd/apexd_testdata/AppInRebootlessApex_AndroidManifest.xml20
-rw-r--r--apexd/apexd_testdata/com.android.apex.compressed.avbpubkeybin1032 -> 0 bytes
-rw-r--r--apexd/apexd_testdata/com.android.apex.compressed.pem51
-rw-r--r--apexd/apexd_testdata/manifest_compressed.json4
-rw-r--r--apexd/apexd_testdata/manifest_compressed_sharedlibs.json5
-rw-r--r--apexd/apexd_testdata/manifest_compressed_v2.json4
-rw-r--r--apexd/apexd_testdata/manifest_rebootless.json9
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_add_native_lib.json10
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_jni_libs.json12
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_provides_native_libs.json12
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_provides_sharedlibs.json10
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_remove_native_lib.json8
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_requires_shared_apex_libs.json12
-rw-r--r--apexd/apexd_testdata/manifest_rebootless_v2.json9
-rw-r--r--apexd/apexd_testdata/sharedlibs.apexbin313995 -> 0 bytes
-rw-r--r--apexd/apexd_utils.h217
-rw-r--r--apexd/apexd_utils_test.cpp284
-rw-r--r--apexd/apexd_verity.cpp22
-rw-r--r--apexd/apexd_verity_test.cpp24
-rw-r--r--apexd/apexservice.cpp353
-rw-r--r--apexd/apexservice_test.cpp476
-rw-r--r--apexd/sysprop/Android.bp4
-rw-r--r--apexd/sysprop/ApexProperties.sysprop16
-rw-r--r--apexd/sysprop/api/com.android.sysprop.apex-current.txt8
-rw-r--r--apexer/Android.bp79
-rw-r--r--apexer/TEST_MAPPING5
-rw-r--r--apexer/apexer.py185
-rw-r--r--apexer/apexer_test.py71
-rwxr-xr-xapexer/runtests.sh16
-rw-r--r--apexer/testdata/Android.bp9
-rw-r--r--docs/README.md291
-rw-r--r--docs/compressed-apex-format.pngbin26768 -> 0 bytes
-rw-r--r--docs/howto.md556
-rw-r--r--library_linking_strategy.cc17
-rw-r--r--libs/libapexutil/Android.bp10
-rw-r--r--libs/libapexutil/apexutil.cpp3
-rw-r--r--proto/Android.bp24
-rw-r--r--proto/apex_build_info.proto3
-rw-r--r--proto/apex_manifest.proto31
-rw-r--r--proto/session_state.proto3
-rw-r--r--pylintrc447
-rw-r--r--shim/Android.bp44
-rw-r--r--shim/build/Android.bp107
-rw-r--r--shim/build/AndroidManifestNotPreInstalled.xml8
-rw-r--r--shim/build/manifest_not_pre_installed.json3
-rw-r--r--shim/build/manifest_v2_rebootless.json5
-rw-r--r--shim/build/manifest_v2_with_post_install_hook.json3
-rw-r--r--shim/build/manifest_v2_with_pre_install_hook.json3
-rw-r--r--shim/build/manifest_v3_rebootless.json5
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v1.apexbin336254 -> 334278 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2.apexbin336247 -> 334283 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_file.apexbin314398 -> 310721 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_additional_folder.apexbin314344 -> 310665 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apexbin318414 -> 314739 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apexbin315946 -> 312267 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_package_name.apexbin314454 -> 334237 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_no_hashtree.apexbin332138 -> 334269 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_rebootless.apexbin314480 -> 0 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_sdk_target_p.apexbin336238 -> 334274 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apexbin314434 -> 0 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob.apexbin339487 -> 337179 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot.apexbin343583 -> 341275 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apexbin343583 -> 341275 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_payload.apexbin323943 -> 326078 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_post_install_hook.apexbin314426 -> 310743 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_with_pre_install_hook.apexbin314421 -> 310746 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_without_apk_in_apex.apexbin314436 -> 310758 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v2_wrong_sha.apexbin314436 -> 310755 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v3.apexbin336252 -> 334277 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v3_rebootless.apexbin314479 -> 0 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob.apexbin339489 -> 337179 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim.v3_signed_bob_rot.apexbin343585 -> 341275 bytes
-rw-r--r--shim/prebuilts/arm/com.android.apex.cts.shim_not_pre_installed.apexbin314421 -> 310791 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v1.apexbin336251 -> 334280 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2.apexbin336245 -> 334281 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_file.apexbin314398 -> 310721 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_additional_folder.apexbin314344 -> 310665 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apexbin318414 -> 314739 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apexbin315946 -> 312267 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_package_name.apexbin314454 -> 334236 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_no_hashtree.apexbin332138 -> 334272 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_rebootless.apexbin314480 -> 0 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_sdk_target_p.apexbin336239 -> 334275 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apexbin314434 -> 0 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob.apexbin339487 -> 337179 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot.apexbin343583 -> 341275 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apexbin343583 -> 341275 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_payload.apexbin323945 -> 326074 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_post_install_hook.apexbin314426 -> 310743 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_with_pre_install_hook.apexbin314421 -> 310746 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_without_apk_in_apex.apexbin314436 -> 310758 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v2_wrong_sha.apexbin314436 -> 310755 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v3.apexbin336251 -> 334279 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v3_rebootless.apexbin314479 -> 0 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob.apexbin339489 -> 337179 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim.v3_signed_bob_rot.apexbin343585 -> 341275 bytes
-rw-r--r--shim/prebuilts/x86/com.android.apex.cts.shim_not_pre_installed.apexbin314421 -> 310791 bytes
-rw-r--r--tests/Android.bp219
-rw-r--r--tests/TEST_MAPPING93
-rw-r--r--tests/adbd-e2e-tests.xml25
-rw-r--r--tests/apex_compression_platform_tests.xml32
-rw-r--r--tests/app/AndroidManifest.xml33
-rw-r--r--tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java164
-rw-r--r--tests/cellbroadcast-e2e-tests.xml25
-rw-r--r--tests/conscrypt-e2e-tests.xml26
-rw-r--r--tests/extservices-e2e-tests.xml24
-rw-r--r--tests/ipsec-e2e-tests.xml26
-rw-r--r--tests/mediaprovider-e2e-tests.xml25
-rw-r--r--tests/module-test-utils-tests.xml24
-rw-r--r--tests/native/.clang-format1
-rw-r--r--tests/native/Android.bp55
-rw-r--r--tests/native/AndroidTest.xml29
-rw-r--r--tests/native/apex_shared_libraries_test.cpp142
-rw-r--r--tests/neuralnetworks-e2e-tests.xml26
-rw-r--r--tests/permission-e2e-tests.xml26
-rw-r--r--tests/sample_prefer32_binary.cc1
-rw-r--r--tests/shared-libs-apex-tests.xml23
-rw-r--r--tests/src/com/android/tests/apex/AdbdHostTest.java (renamed from tests/testdata/sharedlibs/build/include/sharedlibstest.h)20
-rw-r--r--tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java37
-rw-r--r--tests/src/com/android/tests/apex/ApexRollbackTests.java198
-rw-r--r--tests/src/com/android/tests/apex/ApexdHostTest.java179
-rw-r--r--tests/src/com/android/tests/apex/CellbroadcastHostTest.java28
-rw-r--r--tests/src/com/android/tests/apex/ConscryptHostTest.java (renamed from apexd/aidl/android/apex/CompressedApexInfo.aidl)17
-rw-r--r--tests/src/com/android/tests/apex/ExtServicesHostTest.java (renamed from tests/testdata/sharedlibs/build/sharedlibstest.cpp)18
-rw-r--r--tests/src/com/android/tests/apex/IpSecHostTest.java (renamed from apexd/aidl/android/apex/CompressedApexInfoList.aidl)13
-rw-r--r--tests/src/com/android/tests/apex/MediaProviderHostTest.java28
-rw-r--r--tests/src/com/android/tests/apex/NeuralNetworksHostTest.java28
-rw-r--r--tests/src/com/android/tests/apex/PermissionHostTest.java30
-rw-r--r--tests/src/com/android/tests/apex/SharedLibsApexTest.java534
-rw-r--r--tests/src/com/android/tests/apex/StatsdHostTest.java30
-rw-r--r--tests/src/com/android/tests/apex/WifiHostTest.java29
-rw-r--r--tests/src/com/android/tests/apex/host/ApexCompressionTests.java438
-rw-r--r--tests/src/com/android/tests/util/ModuleTestUtilsTest.java71
-rw-r--r--tests/statsd-e2e-tests.xml25
-rw-r--r--tests/testdata/init.rc2
-rw-r--r--tests/testdata/sharedlibs/README.md13
-rw-r--r--tests/testdata/sharedlibs/build/Android.bp86
-rwxr-xr-xtests/testdata/sharedlibs/build/build_artifacts.sh206
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/Android.bp96
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/bar_test.cc13
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pem51
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pk8bin2375 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.x509.pem34
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.bar/manifest.json4
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/Android.bp77
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/baz_test.cc13
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pem51
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pk8bin2374 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.x509.pem34
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.baz/manifest.json4
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/Android.bp77
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pem51
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pk8bin2375 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.x509.pem34
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/foo_test.cc13
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.foo/manifest.json4
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/Android.bp77
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pem51
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pk8bin2375 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.x509.pem34
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/manifest.json4
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.pony/pony_test.cc13
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/Android.bp74
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pem51
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pk8bin2374 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.x509.pem34
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/manifest.json4
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/Android.bp66
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pem51
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pk8bin2374 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.x509.pem34
-rw-r--r--tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/manifest.json4
-rw-r--r--tests/testdata/sharedlibs/build/noop.cc9
-rw-r--r--tests/testdata/sharedlibs/build/shared_libs_repack.py421
-rw-r--r--tests/testdata/sharedlibs/prebuilts/Android.bp301
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v1.libvX.apexbin653957 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v2.libvY.apexbin653957 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v1.libvX.apexbin334169 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v2.libvY.apexbin334169 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.baz_stripped.v1.libvX.apexbin334171 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v1.libvX.apexbin653959 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v2.libvY.apexbin653959 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v1.libvX.apexbin334171 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v2.libvY.apexbin334171 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony.v1.libvZ.apexbin653955 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony_stripped.v1.libvZ.apexbin334167 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v1.libvX.apexbin661523 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v2.libvY.apexbin661523 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apexbin661495 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v1.libvX.apexbin1387020 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v2.libvY.apexbin1387020 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v1.libvX.apexbin333744 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v2.libvY.apexbin333744 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.baz_stripped.v1.libvX.apexbin334161 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v1.libvX.apexbin879233 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v2.libvY.apexbin879233 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v1.libvX.apexbin334161 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v2.libvY.apexbin334161 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony.v1.libvZ.apexbin879229 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony_stripped.v1.libvZ.apexbin334157 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v1.libvX.apexbin1398028 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v2.libvY.apexbin1398028 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apexbin882665 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v1.libvX.apexbin883333 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v2.libvY.apexbin883333 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v1.libvX.apexbin334169 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v2.libvY.apexbin334169 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.baz_stripped.v1.libvX.apexbin334171 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v1.libvX.apexbin883335 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v2.libvY.apexbin883335 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v1.libvX.apexbin334171 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v2.libvY.apexbin334171 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony.v1.libvZ.apexbin883331 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony_stripped.v1.libvZ.apexbin334167 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v1.libvX.apexbin890899 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v2.libvY.apexbin890899 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apexbin890871 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v1.libvX.apexbin1636876 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v2.libvY.apexbin1636876 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v1.libvX.apexbin333744 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v2.libvY.apexbin333744 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.baz_stripped.v1.libvX.apexbin334161 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v1.libvX.apexbin903809 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v2.libvY.apexbin903809 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v1.libvX.apexbin334161 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v2.libvY.apexbin334161 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony.v1.libvZ.apexbin903805 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony_stripped.v1.libvZ.apexbin334157 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v1.libvX.apexbin1651980 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v2.libvY.apexbin1651980 -> 0 bytes
-rw-r--r--tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apexbin911337 -> 0 bytes
-rw-r--r--tests/util/com/android/tests/util/ModuleTestUtils.java247
-rw-r--r--tests/wifi-e2e-tests.xml25
-rw-r--r--tools/Android.bp57
-rw-r--r--tools/apex_compression_test.py323
-rw-r--r--tools/apex_compression_tool.py199
-rw-r--r--tools/create_apex_skeleton.sh73
-rw-r--r--tools/deapexer.py168
340 files changed, 3144 insertions, 17239 deletions
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
deleted file mode 100644
index f87c6b9a..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_arm64/com.android.apex.cts.shim_not_pre_installed.apex"
- }
- dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim_not_pre_installed.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 03cf8a05..5bef6b27 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v1.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 c93ee730..f2032412 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_file.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 d5922e10..d5b1515a 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_folder.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 18e12ee1..5c1ecd8d 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 00f9f6cb..a3e05b58 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 861ffa32..d4f42de6 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_certificate.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 79de3751..30c1658b 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_package_name.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 91f5ef2e..7a4ba73a 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_no_hashtree.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index e8f22833..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_arm64/com.android.apex.cts.shim.v2_rebootless.apex"
- }
- dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim.v2_rebootless.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 e56d8552..e046e3ab 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index ec3b1d67..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
- }
- dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 a8b55abf..6ea9a6b5 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 23567d8b..fe76dce4 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 84c7328d..c90ffbbe 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 ed4ca4b8..779f4993 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 5fb0fb28..0bf9288a 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 38f20a00..5a1baf9b 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 ac823c9b..316c8d12 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 0281ed48..3d5c0e90 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v2_wrong_sha.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 50c821d1..e03ee6e7 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v3.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index f900c468..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_arm64/com.android.apex.cts.shim.v3_rebootless.apex"
- }
- dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim.v3_rebootless.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 d908d0e9..daecf3c3 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 cb1a634b..420522bb 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index 0d09fcba..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_x86_64/com.android.apex.cts.shim_not_pre_installed.apex"
- }
- dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim_not_pre_installed.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 742bca47..239132ac 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v1.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 783107cf..f84e0c89 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_file.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 5ab45ea3..635e2bbd 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_folder.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 aee50ef4..cea53405 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 9eb21eea..2622af8f 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 670489d5..c25509a2 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_certificate.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 c5d28ffe..ab8601fc 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_package_name.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 17ae6c5d..f1ccd780 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_no_hashtree.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index c817a79e..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_rebootless.apex"
- }
- dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim.v2_rebootless.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 b1210498..1f24dedd 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index 39e49e1f..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
- }
- dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 2056dc18..e8c48e1e 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 229b0f31..faf0e28b 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 fc464db4..5f1e6642 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 cffcd608..aef234a7 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 c2168d82..87b7c50f 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 1f2469a6..727bce0d 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 986a4595..23155ba5 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 d53ab6c4..2190954d 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_wrong_sha.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 ca8bade1..e7006ae6 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v3.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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
deleted file mode 100644
index e2c369f7..00000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
- android_build_drop {
- build_id: "7552332"
- target: "CtsShim"
- source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_rebootless.apex"
- }
- dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim.v3_rebootless.apex"
- version: ""
- version_group: ""
- git_project: "platform/system/apex"
- 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 ea066941..bdcb62fb 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
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 3d41a84e..4f258589 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: "7552332"
+ build_id: "6508977"
target: "CtsShim"
source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
}
@@ -8,8 +8,5 @@ drops {
version: ""
version_group: ""
git_project: "platform/system/apex"
- git_branch: "sc-dev"
- transform: TRANSFORM_NONE
- transform_options {
- }
+ git_branch: "rvc-dev"
}
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index b198f250..00000000
--- a/Android.bp
+++ /dev/null
@@ -1,68 +0,0 @@
-// This introduces the module type library_linking_strategy_cc_defaults
-// To use in other Android.bp files, add the following lines:
-// soong_config_module_type_import {
-// from: "system/apex/Android.bp",
-// module_types: ["library_linking_strategy_cc_defaults"],
-// }
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "shared_libs",
- "static_libs",
- "stl",
- ],
-}
-
-// TODO(b/178585590): delete this after testing linking strategy
-soong_config_module_type {
- name: "library_linking_strategy_apex_defaults",
- module_type: "apex_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "manifest",
- "min_sdk_version",
- ],
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_sample_defaults",
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {
- static_libs: [
- "libbase",
- "liblog",
- ],
- stl: "c++_static",
- },
- conditions_default: {
- shared_libs: [
- "libbase",
- "liblog",
- ],
- },
- },
- },
-}
-
-cc_binary {
- name: "library_linking_strategy_sample_binary",
- srcs: ["library_linking_strategy.cc"],
- defaults: ["library_linking_strategy_sample_defaults"],
-}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index ccaf5feb..4c6fbd61 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,7 +6,6 @@ clang_format = true
commit_msg_changeid_field = true
commit_msg_test_field = true
gofmt = true
-pylint3 = true
[Builtin Hooks Options]
-clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp \ No newline at end of file
diff --git a/apexd/Android.bp b/apexd/Android.bp
index ba2de033..e8d221d5 100644
--- a/apexd/Android.bp
+++ b/apexd/Android.bp
@@ -1,46 +1,25 @@
// List of clang-tidy checks that are reported as errors.
// Please keep this list ordered lexicographically.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
tidy_errors = [
- "android-*",
- "bugprone-infinite-loop",
- "bugprone-macro-parentheses",
- "bugprone-misplaced-widening-cast",
- "bugprone-move-forwarding-reference",
- "bugprone-sizeof-container",
- "bugprone-sizeof-expression",
- "bugprone-string-constructor",
- "bugprone-terminating-continue",
- "bugprone-undefined-memory-manipulation",
- "bugprone-undelegated-constructor",
- // "bugprone-unhandled-self-assignment", // found in apex_manifest.proto
- "bugprone-unused-raii",
"cert-err34-c",
"google-default-arguments",
- // "google-explicit-constructor", // found in com_android_apex.h
- "google-readability-avoid-underscore-in-googletest-name",
- "google-readability-todo",
+ "google-explicit-constructor",
"google-runtime-int",
"google-runtime-member-string-references",
"misc-move-const-arg",
"misc-move-forwarding-reference",
- // "misc-unused-parameters", // found in apexd_utils.h
+ "misc-unused-parameters",
"misc-unused-using-decls",
"misc-use-after-move",
- // "modernize-pass-by-value", // found in apex_database.h
+ "modernize-pass-by-value",
"performance-faster-string-find",
"performance-for-range-copy",
"performance-implicit-conversion-in-loop",
"performance-inefficient-vector-operation",
"performance-move-const-arg",
- // "performance-move-constructor-init", // found in apexd_loop.h
+ "performance-move-constructor-init",
"performance-noexcept-move-constructor",
- "performance-unnecessary-copy-initialization",
"performance-unnecessary-value-param",
- // "readability-avoid-const-params-in-decls", // found in apexd.h
]
cc_defaults {
@@ -68,8 +47,8 @@ cc_defaults {
tidy_checks: tidy_errors,
tidy_checks_as_errors: tidy_errors,
tidy_flags: [
- "-format-style=file",
- "-header-filter=system/apex/",
+ "-format-style='file'",
+ "--header-filter='system/apex/'",
],
}
@@ -79,6 +58,7 @@ cc_defaults {
defaults: ["libapex-deps"],
shared_libs: [
"libbinder",
+ "libselinux",
"liblog",
"liblogwrap",
],
@@ -89,7 +69,6 @@ cc_defaults {
"libext2_uuid",
"libverity_tree",
"libvold_binder",
- "libxml2",
],
whole_static_libs: ["com.android.sysprop.apex"],
}
@@ -102,8 +81,6 @@ aidl_interface {
"aidl/android/apex/ApexInfoList.aidl",
"aidl/android/apex/ApexSessionInfo.aidl",
"aidl/android/apex/ApexSessionParams.aidl",
- "aidl/android/apex/CompressedApexInfo.aidl",
- "aidl/android/apex/CompressedApexInfoList.aidl",
"aidl/android/apex/IApexService.aidl",
],
local_include_dir: "aidl",
@@ -150,15 +127,14 @@ cc_library_static {
srcs: [
"apex_database.cpp",
"apexd.cpp",
- "apexd_lifecycle.cpp",
"apexd_loop.cpp",
"apexd_prepostinstall.cpp",
"apexd_private.cpp",
+ "apexd_prop.cpp",
"apexd_session.cpp",
"apexd_verity.cpp",
],
export_include_dirs: ["."],
- generated_sources: ["apex-info-list"],
// Don't add shared/static libs here; add to libapexd_defaults instead.
}
@@ -194,9 +170,6 @@ cc_library_static {
static_libs: [
"libapexd",
],
- cflags: [
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
- ],
}
cc_defaults {
@@ -207,7 +180,6 @@ cc_defaults {
"libcutils",
"libprotobuf-cpp-full",
"libziparchive",
- "libselinux",
],
static_libs: [
"lib_apex_session_state_proto",
@@ -217,7 +189,6 @@ cc_defaults {
static: {
whole_static_libs: ["libc++fs"],
},
- cpp_std: "experimental",
shared: {
static_libs: ["libc++fs"],
},
@@ -231,8 +202,8 @@ cc_library_static {
],
srcs: [
"apex_file.cpp",
- "apex_file_repository.cpp",
"apex_manifest.cpp",
+ "apex_preinstalled_data.cpp",
"apex_shim.cpp",
],
host_supported: true,
@@ -252,7 +223,7 @@ cc_library_static {
genrule {
// Generates an apex which has a different manifest outside the filesystem
// image.
- name: "gen_manifest_mismatch_apex",
+ name: "gen_bad_apexes",
out: ["apex.apexd_test_manifest_mismatch.apex"],
srcs: [":apex.apexd_test"],
tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
@@ -266,38 +237,6 @@ genrule {
}
genrule {
- // Generates an apex which has a different manifest outside the filesystem
- // image.
- name: "gen_manifest_mismatch_apex_no_hashtree",
- out: ["apex.apexd_test_no_hashtree_manifest_mismatch.apex"],
- srcs: [":apex.apexd_test_no_hashtree"],
- tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "$(location conv_apex_manifest) setprop version 137 $(genDir)/apex_manifest.pb && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/apex.apexd_test_no_hashtree_manifest_mismatch.apex"
-}
-
-genrule {
- // Generates an apex with a corrupted filesystem superblock, which should cause
- // Apex::Open to fail
- name: "gen_corrupt_superblock_apex",
- out: ["apex.apexd_test_corrupt_superblock_apex.apex"],
- srcs: [":apex.apexd_test"],
- tools: ["soong_zip", "zipalign"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "dd if=/dev/zero of=$(genDir)/apex_payload.img conv=notrunc bs=1024 seek=1 count=1 && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/apex.apexd_test_corrupt_superblock_apex.apex"
-}
-
-genrule {
// Generates an apex with a corrupted filesystem image, which should cause
// dm-verity verification to fail
name: "gen_corrupt_apex",
@@ -313,93 +252,6 @@ genrule {
"$(genDir)/apex.apexd_test_corrupt_apex.apex"
}
-genrule {
- // Extract the root digest with avbtool
- name: "apex.apexd_test_digest",
- out: ["apex.apexd_test_digest.txt"],
- srcs: [":apex.apexd_test"],
- 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 {
- // Extract the root digest with avbtool
- name: "apex.apexd_test_f2fs_digest",
- out: ["apex.apexd_test_f2fs_digest.txt"],
- srcs: [":apex.apexd_test_f2fs"],
- 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",
- out: ["apex.apexd_test_different_key.apex"],
- srcs: [":apex.apexd_test_no_inst_key"],
- tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "$(location conv_apex_manifest) setprop name com.android.apex.test_package $(genDir)/apex_manifest.pb && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/apex.apexd_test_different_key.apex"
-}
-
-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_v2",
- out: ["apex.apexd_test_different_key_v2.apex"],
- srcs: [":apex.apexd_test_no_inst_key"],
- tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "$(location conv_apex_manifest) setprop name com.android.apex.test_package $(genDir)/apex_manifest.pb && " +
- "$(location conv_apex_manifest) setprop version 2 $(genDir)/apex_manifest.pb && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/apex.apexd_test_different_key_v2.apex"
-}
-
-genrule {
- // Generates an apex which has a different manifest outside the filesystem
- // image.
- name: "gen_manifest_mismatch_rebootless_apex",
- out: ["test.rebootless_apex_manifest_mismatch.apex"],
- srcs: [":test.rebootless_apex_v1"],
- tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "$(location conv_apex_manifest) setprop version 137 $(genDir)/apex_manifest.pb && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/test.rebootless_apex_manifest_mismatch.apex"
-}
-
-genrule {
- // Generates an apex with a corrupted filesystem image, which should cause
- // dm-verity verification to fail
- name: "gen_corrupt_rebootless_apex",
- out: ["test.rebootless_apex_corrupted.apex"],
- srcs: [":test.rebootless_apex_v1"],
- tools: ["soong_zip", "zipalign"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "dd if=/dev/zero of=$(genDir)/apex_payload.img conv=notrunc bs=1024 seek=16 count=1 && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/test.rebootless_apex_corrupted.apex"
-}
-
cc_test {
name: "ApexTestCases",
defaults: [
@@ -414,32 +266,18 @@ cc_test {
],
data: [
":apex.apexd_test",
- ":apex.apexd_test_f2fs",
- ":apex.apexd_test_digest",
- ":apex.apexd_test_f2fs_digest",
":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",
- ":gen_key_mismatch_apex",
- ":gen_key_mismatch_apex_v2",
- ":gen_key_mismatch_capex",
- ":gen_manifest_mismatch_apex",
- ":gen_manifest_mismatch_apex_no_hashtree",
- ":gen_corrupt_superblock_apex",
+ ":gen_bad_apexes",
":gen_corrupt_apex",
- ":gen_capex_not_decompressible",
- ":gen_capex_without_apex",
- ":gen_capex_with_v2_apex",
- ":gen_key_mismatch_with_original_capex",
":com.android.apex.cts.shim.v1_prebuilt",
":com.android.apex.cts.shim.v2_prebuilt",
":com.android.apex.cts.shim.v2_wrong_sha_prebuilt",
@@ -447,41 +285,13 @@ cc_test {
":com.android.apex.cts.shim.v2_additional_folder_prebuilt",
":com.android.apex.cts.shim.v2_with_pre_install_hook_prebuilt",
":com.android.apex.cts.shim.v2_with_post_install_hook_prebuilt",
- ":com.android.apex.compressed_sharedlibs",
- ":com.android.apex.compressed.v1",
- ":com.android.apex.compressed.v1_different_digest",
- ":com.android.apex.compressed.v1_different_digest_original",
- ":com.android.apex.compressed.v1_original",
- ":com.android.apex.compressed.v2",
- ":com.android.apex.compressed.v2_original",
- ":gen_manifest_mismatch_compressed_apex_v2",
"apexd_testdata/com.android.apex.test_package.avbpubkey",
- "apexd_testdata/com.android.apex.compressed.avbpubkey",
- ":com.android.apex.test.sharedlibs_generated.v1.libvX_prebuilt",
- ":com.android.apex.test.sharedlibs_generated.v2.libvY_prebuilt",
- ":test.rebootless_apex_v1",
- ":test.rebootless_apex_v2",
- ":test.rebootless_apex_v2_no_hashtree",
- ":gen_manifest_mismatch_rebootless_apex",
- ":gen_corrupt_rebootless_apex",
- ":test.rebootless_apex_provides_sharedlibs",
- ":test.rebootless_apex_provides_native_libs",
- ":test.rebootless_apex_requires_shared_apex_libs",
- ":test.rebootless_apex_jni_libs",
- ":test.rebootless_apex_add_native_lib",
- ":test.rebootless_apex_remove_native_lib",
- ":test.rebootless_apex_app_in_apex",
- ":test.rebootless_apex_priv_app_in_apex",
],
srcs: [
"apex_database_test.cpp",
"apex_file_test.cpp",
- "apex_file_repository_test.cpp",
"apex_manifest_test.cpp",
- "apexd_test.cpp",
- "apexd_session_test.cpp",
"apexd_verity_test.cpp",
- "apexd_utils_test.cpp",
"apexservice_test.cpp",
],
host_supported: false,
@@ -498,7 +308,6 @@ cc_test {
"libfs_mgr",
"libutils",
],
- generated_sources: ["apex-info-list"],
test_suites: ["device-tests"],
test_config: "AndroidTest.xml",
}
@@ -521,10 +330,3 @@ cc_test {
test_config: "flattened_apex_test_config.xml",
}
-xsd_config {
- name: "apex-info-list",
- srcs: ["ApexInfoList.xsd"],
- package_name: "com.android.apex",
- api_dir: "apex-info-list-api",
- gen_writer: true,
-}
diff --git a/apexd/ApexInfoList.xsd b/apexd/ApexInfoList.xsd
deleted file mode 100644
index 440b975f..00000000
--- a/apexd/ApexInfoList.xsd
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <xs:element name="apex-info-list">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="apex-info" minOccurs="1" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="apex-info">
- <xs:complexType>
- <xs:attribute name="moduleName" type="xs:string" use="required"/>
- <xs:attribute name="modulePath" type="xs:string" use="required"/>
- <xs:attribute name="preinstalledModulePath" type="xs:string"/>
- <xs:attribute name="versionCode" type="xs:long" use="required"/>
- <xs:attribute name="versionName" type="xs:string" use="required"/>
- <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:complexType>
- </xs:element>
-</xs:schema>
diff --git a/apexd/OWNERS b/apexd/OWNERS
new file mode 100644
index 00000000..ed9813ee
--- /dev/null
+++ b/apexd/OWNERS
@@ -0,0 +1 @@
+agampe@google.com
diff --git a/apexd/aidl/android/apex/ApexSessionInfo.aidl b/apexd/aidl/android/apex/ApexSessionInfo.aidl
index 65da1135..a7a6daf2 100644
--- a/apexd/aidl/android/apex/ApexSessionInfo.aidl
+++ b/apexd/aidl/android/apex/ApexSessionInfo.aidl
@@ -29,5 +29,4 @@ parcelable ApexSessionInfo {
boolean isReverted;
boolean isRevertFailed;
@utf8InCpp String crashingNativeProcess;
- @utf8InCpp String errorMessage;
}
diff --git a/apexd/aidl/android/apex/IApexService.aidl b/apexd/aidl/android/apex/IApexService.aidl
index 2d77a822..3626d9ac 100644
--- a/apexd/aidl/android/apex/IApexService.aidl
+++ b/apexd/aidl/android/apex/IApexService.aidl
@@ -20,7 +20,6 @@ import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
-import android.apex.CompressedApexInfoList;
interface IApexService {
void submitStagedSession(in ApexSessionParams params, out ApexInfoList packages);
@@ -37,9 +36,9 @@ interface IApexService {
/**
* Copies the CE apex data directory for the given user to the backup
- * location.
+ * location, and returns the inode of the snapshot directory.
*/
- void snapshotCeData(int user_id, int rollback_id, in @utf8InCpp String apex_name);
+ long snapshotCeData(int user_id, int rollback_id, in @utf8InCpp String apex_name);
/**
* Restores the snapshot of the CE apex data directory for the given user and
@@ -53,11 +52,6 @@ interface IApexService {
void destroyDeSnapshots(int rollback_id);
/**
- * Deletes credential-encrypted snapshots for the given user, for the given rollback id.
- */
- void destroyCeSnapshots(int user_id, int rollback_id);
-
- /**
* Deletes all credential-encrypted snapshots for the given user, except for
* those listed in retain_rollback_ids.
*/
@@ -121,42 +115,4 @@ interface IApexService {
* on user builds. Only root is allowed to call this method.
*/
void remountPackages();
- /**
- * Forces apexd to recollect pre-installed data from the given |paths|.
- *
- * Not meant for use outside of testing. This call will not be functional
- * on user builds. Only root is allowed to call this method.
- */
- void recollectPreinstalledData(in @utf8InCpp List<String> paths);
- /**
- * Forces apexd to recollect data apex from the given |path|.
- *
- * Not meant for use outside of testing. This call will not be functional
- * on user builds. Only root is allowed to call this method.
- */
- void recollectDataApex(in @utf8InCpp String path, in@utf8InCpp String decompression_dir);
-
- /**
- * Informs apexd that the boot has completed.
- */
- void markBootCompleted();
-
- /**
- * Assuming the provided compressed APEX will be installed on next boot,
- * calculate how much space will be required for decompression
- */
- long calculateSizeForCompressedApex(in CompressedApexInfoList compressed_apex_info_list);
-
- /**
- * Reserve space on /data partition for compressed APEX decompression. Returns error if
- * reservation fails. If empty list is passed, then reserved space is deallocated.
- */
- void reserveSpaceForCompressedApex(in CompressedApexInfoList compressed_apex_info_list);
-
- /**
- * Performs a non-staged install of the given APEX.
- * Note: don't confuse this to preInstall and postInstall binder calls which are only used to
- * test corresponding features of APEX packages.
- */
- ApexInfo installAndActivatePackage(in @utf8InCpp String packagePath);
}
diff --git a/apexd/apex-info-list-api/current.txt b/apexd/apex-info-list-api/current.txt
deleted file mode 100644
index 8db5a9a0..00000000
--- a/apexd/apex-info-list-api/current.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-// Signature format: 2.0
-package com.android.apex {
-
- public class ApexInfo {
- ctor public ApexInfo();
- method public boolean getIsActive();
- method public boolean getIsFactory();
- method public long getLastUpdateMillis();
- method public String getModuleName();
- method public String getModulePath();
- method public String getPreinstalledModulePath();
- method public long getVersionCode();
- method public String getVersionName();
- method public void setIsActive(boolean);
- method public void setIsFactory(boolean);
- method public void setLastUpdateMillis(long);
- method public void setModuleName(String);
- method public void setModulePath(String);
- method public void setPreinstalledModulePath(String);
- method public void setVersionCode(long);
- method public void setVersionName(String);
- }
-
- public class ApexInfoList {
- ctor public ApexInfoList();
- method public java.util.List<com.android.apex.ApexInfo> getApexInfo();
- }
-
- public class XmlParser {
- ctor public XmlParser();
- method public static com.android.apex.ApexInfo readApexInfo(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static com.android.apex.ApexInfoList readApexInfoList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- }
-
- public class XmlWriter implements java.io.Closeable {
- ctor public XmlWriter(java.io.PrintWriter);
- method public void close();
- method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfoList) throws java.io.IOException;
- method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfo) throws java.io.IOException;
- }
-
-}
-
diff --git a/apexd/apex-info-list-api/last_current.txt b/apexd/apex-info-list-api/last_current.txt
deleted file mode 100644
index 8db5a9a0..00000000
--- a/apexd/apex-info-list-api/last_current.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-// Signature format: 2.0
-package com.android.apex {
-
- public class ApexInfo {
- ctor public ApexInfo();
- method public boolean getIsActive();
- method public boolean getIsFactory();
- method public long getLastUpdateMillis();
- method public String getModuleName();
- method public String getModulePath();
- method public String getPreinstalledModulePath();
- method public long getVersionCode();
- method public String getVersionName();
- method public void setIsActive(boolean);
- method public void setIsFactory(boolean);
- method public void setLastUpdateMillis(long);
- method public void setModuleName(String);
- method public void setModulePath(String);
- method public void setPreinstalledModulePath(String);
- method public void setVersionCode(long);
- method public void setVersionName(String);
- }
-
- public class ApexInfoList {
- ctor public ApexInfoList();
- method public java.util.List<com.android.apex.ApexInfo> getApexInfo();
- }
-
- public class XmlParser {
- ctor public XmlParser();
- method public static com.android.apex.ApexInfo readApexInfo(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static com.android.apex.ApexInfoList readApexInfoList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- }
-
- public class XmlWriter implements java.io.Closeable {
- ctor public XmlWriter(java.io.PrintWriter);
- method public void close();
- method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfoList) throws java.io.IOException;
- method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfo) throws java.io.IOException;
- }
-
-}
-
diff --git a/apexd/apex-info-list-api/last_removed.txt b/apexd/apex-info-list-api/last_removed.txt
deleted file mode 100644
index e69de29b..00000000
--- a/apexd/apex-info-list-api/last_removed.txt
+++ /dev/null
diff --git a/apexd/apex-info-list-api/removed.txt b/apexd/apex-info-list-api/removed.txt
deleted file mode 100644
index d802177e..00000000
--- a/apexd/apex-info-list-api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apex_constants.h b/apexd/apex_constants.h
index 798afd5a..4e989431 100644
--- a/apexd/apex_constants.h
+++ b/apexd/apex_constants.h
@@ -17,7 +17,6 @@
#pragma once
#include <string>
-#include <unordered_set>
#include <vector>
namespace android {
@@ -27,8 +26,6 @@ static constexpr const char* kApexDataDir = "/data/apex";
static constexpr const char* kActiveApexPackagesDataDir = "/data/apex/active";
static constexpr const char* kApexBackupDir = "/data/apex/backup";
static constexpr const char* kApexHashTreeDir = "/data/apex/hashtree";
-static constexpr const char* kApexDecompressedDir = "/data/apex/decompressed";
-static constexpr const char* kOtaReservedDir = "/data/apex/ota_reserved";
static constexpr const char* kApexPackageSystemDir = "/system/apex";
static constexpr const char* kApexPackageSystemExtDir = "/system_ext/apex";
static constexpr const char* kApexPackageVendorDir = "/vendor/apex";
@@ -42,7 +39,6 @@ static constexpr const char* kApexRoot = "/apex";
static constexpr const char* kStagedSessionsDir = "/data/app-staging";
static constexpr const char* kApexDataSubDir = "apexdata";
-static constexpr const char* kApexSharedLibsSubDir = "sharedlibs";
static constexpr const char* kApexSnapshotSubDir = "apexrollback";
static constexpr const char* kPreRestoreSuffix = "-prerestore";
@@ -51,26 +47,8 @@ static constexpr const char* kDeNDataDir = "/data/misc_de";
static constexpr const char* kCeDataDir = "/data/misc_ce";
static constexpr const char* kApexPackageSuffix = ".apex";
-static constexpr const char* kCompressedApexPackageSuffix = ".capex";
-static constexpr const char* kDecompressedApexPackageSuffix =
- ".decompressed.apex";
-static constexpr const char* kOtaApexPackageSuffix = ".ota.apex";
static constexpr const char* kManifestFilenameJson = "apex_manifest.json";
static constexpr const char* kManifestFilenamePb = "apex_manifest.pb";
-
-static constexpr const char* kApexInfoList = "apex-info-list.xml";
-
-// These should be in-sync with system/sepolicy/private/property_contexts
-static constexpr const char* kApexStatusSysprop = "apexd.status";
-static constexpr const char* kApexStatusStarting = "starting";
-static constexpr const char* kApexStatusActivated = "activated";
-static constexpr const char* kApexStatusReady = "ready";
-
-// Banned APEX names
-static const std::unordered_set<std::string> kBannedApexName = {
- kApexSharedLibsSubDir, // To avoid conflicts with predefined
- // /apex/sharedlibs directory
-};
} // namespace apex
} // namespace android
diff --git a/apexd/apex_database.cpp b/apexd/apex_database.cpp
index 7a1ee360..d027f95c 100644
--- a/apexd/apex_database.cpp
+++ b/apexd/apex_database.cpp
@@ -35,9 +35,6 @@
#include <utility>
using android::base::ConsumeSuffix;
-using android::base::EndsWith;
-using android::base::ErrnoError;
-using android::base::Error;
using android::base::ParseInt;
using android::base::ReadFileToString;
using android::base::Result;
@@ -79,12 +76,12 @@ class BlockDevice {
fs::path DevPath() const { return kDevBlock / name; }
Result<std::string> GetProperty(const std::string& property) const {
- auto property_file = SysPath() / property;
- std::string property_value;
- if (!ReadFileToString(property_file, &property_value)) {
+ auto propertyFile = SysPath() / property;
+ std::string propertyValue;
+ if (!ReadFileToString(propertyFile, &propertyValue)) {
return ErrnoError() << "Fail to read";
}
- return Trim(property_value);
+ return Trim(propertyValue);
}
std::vector<BlockDevice> GetSlaves() const {
@@ -103,17 +100,17 @@ class BlockDevice {
}
};
-std::pair<fs::path, fs::path> ParseMountInfo(const std::string& mount_info) {
- const auto& tokens = Split(mount_info, " ");
+std::pair<fs::path, fs::path> parseMountInfo(const std::string& mountInfo) {
+ const auto& tokens = Split(mountInfo, " ");
if (tokens.size() < 2) {
return std::make_pair("", "");
}
return std::make_pair(tokens[0], tokens[1]);
}
-std::pair<std::string, int> ParseMountPoint(const std::string& mount_point) {
- auto package_id = fs::path(mount_point).filename();
- auto split = Split(package_id, "@");
+std::pair<std::string, int> parseMountPoint(const std::string& mountPoint) {
+ auto packageId = fs::path(mountPoint).filename();
+ auto split = Split(packageId, "@");
if (split.size() == 2) {
int version;
if (!ParseInt(split[1], &version)) {
@@ -121,17 +118,14 @@ std::pair<std::string, int> ParseMountPoint(const std::string& mount_point) {
}
return std::make_pair(split[0], version);
}
- return std::make_pair(package_id, -1);
+ return std::make_pair(packageId, -1);
}
-bool IsActiveMountPoint(const std::string& mount_point) {
- return (mount_point.find('@') == std::string::npos);
+bool isActiveMountPoint(const std::string& mountPoint) {
+ return (mountPoint.find('@') == std::string::npos);
}
Result<void> PopulateLoopInfo(const BlockDevice& top_device,
- const std::string& active_apex_dir,
- const std::string& decompression_dir,
- const std::string& apex_hash_tree_dir,
MountedApexData* apex_data) {
std::vector<BlockDevice> slaves = top_device.GetSlaves();
if (slaves.size() != 1 && slaves.size() != 2) {
@@ -153,22 +147,18 @@ Result<void> PopulateLoopInfo(const BlockDevice& top_device,
// Enforce following invariant:
// * slaves[0] always represents a data loop device
// * if size = 2 then slaves[1] represents an external hashtree loop device
- auto is_data_loop_device = [&](const std::string& backing_file) {
- return StartsWith(backing_file, active_apex_dir) ||
- StartsWith(backing_file, decompression_dir);
- };
if (slaves.size() == 2) {
- if (!is_data_loop_device(backing_files[0])) {
+ if (!StartsWith(backing_files[0], kActiveApexPackagesDataDir)) {
std::swap(slaves[0], slaves[1]);
std::swap(backing_files[0], backing_files[1]);
}
}
- if (!is_data_loop_device(backing_files[0])) {
+ if (!StartsWith(backing_files[0], kActiveApexPackagesDataDir)) {
return Error() << "Data loop device " << slaves[0].DevPath()
<< " has unexpected backing file " << backing_files[0];
}
if (slaves.size() == 2) {
- if (!StartsWith(backing_files[1], apex_hash_tree_dir)) {
+ if (!StartsWith(backing_files[1], kApexHashTreeDir)) {
return Error() << "Hashtree loop device " << slaves[1].DevPath()
<< " has unexpected backing file " << backing_files[1];
}
@@ -181,7 +171,7 @@ Result<void> PopulateLoopInfo(const BlockDevice& top_device,
// This is not the right place to do this normalization, but proper solution
// will require some refactoring first. :(
-// TODO(b/158469911): introduce MountedApexDataBuilder and delegate all
+// TODO(ioffe): introduce MountedApexDataBuilder and delegate all
// building/normalization logic to it.
void NormalizeIfDeleted(MountedApexData* apex_data) {
std::string_view full_path = apex_data->full_path;
@@ -198,22 +188,18 @@ void NormalizeIfDeleted(MountedApexData* apex_data) {
apex_data->full_path = full_path;
}
-Result<MountedApexData> ResolveMountInfo(
- const BlockDevice& block, const std::string& mount_point,
- const std::string& active_apex_dir, const std::string& decompression_dir,
- const std::string& apex_hash_tree_dir) {
- bool temp_mount = EndsWith(mount_point, ".tmp");
+Result<MountedApexData> resolveMountInfo(const BlockDevice& block,
+ const std::string& mountPoint) {
// Now, see if it is dm-verity or loop mounted
switch (block.GetType()) {
case LoopDevice: {
- auto backing_file = block.GetProperty("loop/backing_file");
- if (!backing_file.ok()) {
- return backing_file.error();
+ auto backingFile = block.GetProperty("loop/backing_file");
+ if (!backingFile.ok()) {
+ return backingFile.error();
}
- auto result = MountedApexData(block.DevPath(), *backing_file, mount_point,
+ auto result = MountedApexData(block.DevPath(), *backingFile, mountPoint,
/* device_name= */ "",
- /* hashtree_loop_name= */ "",
- /* is_temp_mount */ temp_mount);
+ /* hashtree_loop_name= */ "");
NormalizeIfDeleted(&result);
return result;
}
@@ -223,12 +209,9 @@ Result<MountedApexData> ResolveMountInfo(
return name.error();
}
MountedApexData result;
- result.mount_point = mount_point;
+ result.mount_point = mountPoint;
result.device_name = *name;
- result.is_temp_mount = temp_mount;
- auto status = PopulateLoopInfo(block, active_apex_dir, decompression_dir,
- apex_hash_tree_dir, &result);
- if (!status.ok()) {
+ if (auto status = PopulateLoopInfo(block, &result); !status.ok()) {
return status.error();
}
NormalizeIfDeleted(&result);
@@ -263,45 +246,40 @@ Result<MountedApexData> ResolveMountInfo(
// By synchronizing the mounts info with Database on startup,
// Apexd serves the correct package list even on the devices
// which are not ro.apex.updatable.
-void MountedApexDatabase::PopulateFromMounts(
- const std::string& active_apex_dir, const std::string& decompression_dir,
- const std::string& apex_hash_tree_dir) REQUIRES(!mounted_apexes_mutex_) {
+void MountedApexDatabase::PopulateFromMounts() {
LOG(INFO) << "Populating APEX database from mounts...";
- std::unordered_map<std::string, int> active_versions;
+ std::unordered_map<std::string, int> activeVersions;
std::ifstream mounts("/proc/mounts");
std::string line;
- std::lock_guard lock(mounted_apexes_mutex_);
while (std::getline(mounts, line)) {
- auto [block, mount_point] = ParseMountInfo(line);
- // TODO(b/158469914): distinguish between temp and non-temp mounts
- if (fs::path(mount_point).parent_path() != kApexRoot) {
+ auto [block, mountPoint] = parseMountInfo(line);
+ // TODO(jooyung): ignore tmp mount?
+ if (fs::path(mountPoint).parent_path() != kApexRoot) {
continue;
}
- if (IsActiveMountPoint(mount_point)) {
+ if (isActiveMountPoint(mountPoint)) {
continue;
}
- auto mount_data =
- ResolveMountInfo(BlockDevice(block), mount_point, active_apex_dir,
- decompression_dir, apex_hash_tree_dir);
- if (!mount_data.ok()) {
- LOG(WARNING) << "Can't resolve mount info " << mount_data.error();
+ auto mountData = resolveMountInfo(BlockDevice(block), mountPoint);
+ if (!mountData.ok()) {
+ LOG(WARNING) << "Can't resolve mount info " << mountData.error();
continue;
}
- auto [package, version] = ParseMountPoint(mount_point);
- AddMountedApexLocked(package, false, *mount_data);
+ auto [package, version] = parseMountPoint(mountPoint);
+ AddMountedApex(package, false, *mountData);
- auto active = active_versions[package] < version;
+ auto active = activeVersions[package] < version;
if (active) {
- active_versions[package] = version;
- SetLatestLocked(package, mount_data->full_path);
+ activeVersions[package] = version;
+ SetLatest(package, mountData->full_path);
}
- LOG(INFO) << "Found " << mount_point << " backed by"
- << (mount_data->deleted ? " deleted " : " ") << "file "
- << mount_data->full_path;
+ LOG(INFO) << "Found " << mountPoint << " backed by"
+ << (mountData->deleted ? " deleted " : " ") << "file "
+ << mountData->full_path;
}
LOG(INFO) << mounted_apexes_.size() << " packages restored.";
diff --git a/apexd/apex_database.h b/apexd/apex_database.h
index 113b88ec..1fb5bd3a 100644
--- a/apexd/apex_database.h
+++ b/apexd/apex_database.h
@@ -18,14 +18,10 @@
#define ANDROID_APEXD_APEX_DATABASE_H_
#include <map>
-#include <mutex>
-#include <optional>
#include <string>
#include <unordered_set>
#include <android-base/logging.h>
-#include <android-base/result.h>
-#include <android-base/thread_annotations.h>
namespace android {
namespace apex {
@@ -44,21 +40,17 @@ class MountedApexDatabase {
std::string hashtree_loop_name;
// Whenever apex file specified in full_path was deleted.
bool deleted;
- // Whether the mount is a temp mount or not.
- bool is_temp_mount;
MountedApexData() {}
MountedApexData(const std::string& loop_name, const std::string& full_path,
const std::string& mount_point,
const std::string& device_name,
- const std::string& hashtree_loop_name,
- bool is_temp_mount = false)
+ const std::string& hashtree_loop_name)
: loop_name(loop_name),
full_path(full_path),
mount_point(mount_point),
device_name(device_name),
- hashtree_loop_name(hashtree_loop_name),
- is_temp_mount(is_temp_mount) {}
+ hashtree_loop_name(hashtree_loop_name) {}
inline bool operator<(const MountedApexData& rhs) const {
int compare_val = loop_name.compare(rhs.loop_name);
@@ -89,10 +81,42 @@ class MountedApexDatabase {
}
};
+ inline void CheckAtMostOneLatest() {
+ for (const auto& apex_set : mounted_apexes_) {
+ size_t count = 0;
+ for (const auto& pair : apex_set.second) {
+ if (pair.second) {
+ count++;
+ }
+ }
+ CHECK_LE(count, 1u) << apex_set.first;
+ }
+ }
+
+ inline void CheckUniqueLoopDm() {
+ std::unordered_set<std::string> loop_devices;
+ std::unordered_set<std::string> dm_devices;
+ for (const auto& apex_set : mounted_apexes_) {
+ for (const auto& pair : apex_set.second) {
+ if (pair.first.loop_name != "") {
+ CHECK(loop_devices.insert(pair.first.loop_name).second)
+ << "Duplicate loop device: " << pair.first.loop_name;
+ }
+ if (pair.first.device_name != "") {
+ CHECK(dm_devices.insert(pair.first.device_name).second)
+ << "Duplicate dm device: " << pair.first.device_name;
+ }
+ if (pair.first.hashtree_loop_name != "") {
+ CHECK(loop_devices.insert(pair.first.hashtree_loop_name).second)
+ << "Duplicate loop device: " << pair.first.hashtree_loop_name;
+ }
+ }
+ }
+ }
+
template <typename... Args>
- inline void AddMountedApexLocked(const std::string& package, bool latest,
- Args&&... args)
- REQUIRES(mounted_apexes_mutex_) {
+ inline void AddMountedApex(const std::string& package, bool latest,
+ Args&&... args) {
auto it = mounted_apexes_.find(package);
if (it == mounted_apexes_.end()) {
auto insert_it =
@@ -109,18 +133,8 @@ class MountedApexDatabase {
CheckUniqueLoopDm();
}
- template <typename... Args>
- inline void AddMountedApex(const std::string& package, bool latest,
- Args&&... args) REQUIRES(!mounted_apexes_mutex_) {
- std::lock_guard lock(mounted_apexes_mutex_);
- AddMountedApexLocked(package, latest, args...);
- }
-
inline void RemoveMountedApex(const std::string& package,
- const std::string& full_path,
- bool match_temp_mounts = false)
- REQUIRES(!mounted_apexes_mutex_) {
- std::lock_guard lock(mounted_apexes_mutex_);
+ const std::string& full_path) {
auto it = mounted_apexes_.find(package);
if (it == mounted_apexes_.end()) {
return;
@@ -129,8 +143,7 @@ class MountedApexDatabase {
auto& pkg_map = it->second;
for (auto pkg_it = pkg_map.begin(); pkg_it != pkg_map.end(); ++pkg_it) {
- if (pkg_it->first.full_path == full_path &&
- pkg_it->first.is_temp_mount == match_temp_mounts) {
+ if (pkg_it->first.full_path == full_path) {
pkg_map.erase(pkg_it);
return;
}
@@ -138,15 +151,7 @@ class MountedApexDatabase {
}
inline void SetLatest(const std::string& package,
- const std::string& full_path)
- REQUIRES(!mounted_apexes_mutex_) {
- std::lock_guard lock(mounted_apexes_mutex_);
- SetLatestLocked(package, full_path);
- }
-
- inline void SetLatestLocked(const std::string& package,
- const std::string& full_path)
- REQUIRES(mounted_apexes_mutex_) {
+ const std::string& full_path) {
auto it = mounted_apexes_.find(package);
CHECK(it != mounted_apexes_.end());
@@ -168,108 +173,47 @@ class MountedApexDatabase {
LOG(FATAL) << "Did not find " << package << " " << full_path;
}
+ inline void UnsetLatestForall(const std::string& package) {
+ auto it = mounted_apexes_.find(package);
+ if (it == mounted_apexes_.end()) {
+ return;
+ }
+ for (auto& data : it->second) {
+ data.second = false;
+ }
+ }
+
template <typename T>
- inline void ForallMountedApexes(const std::string& package, const T& handler,
- bool match_temp_mounts = false) const
- REQUIRES(!mounted_apexes_mutex_) {
- std::lock_guard lock(mounted_apexes_mutex_);
+ inline void ForallMountedApexes(const std::string& package,
+ const T& handler) const {
auto it = mounted_apexes_.find(package);
if (it == mounted_apexes_.end()) {
return;
}
for (auto& pair : it->second) {
- if (pair.first.is_temp_mount == match_temp_mounts) {
- handler(pair.first, pair.second);
- }
+ handler(pair.first, pair.second);
}
}
template <typename T>
- inline void ForallMountedApexes(const T& handler,
- bool match_temp_mounts = false) const
- REQUIRES(!mounted_apexes_mutex_) {
- std::lock_guard lock(mounted_apexes_mutex_);
+ inline void ForallMountedApexes(const T& handler) const {
for (const auto& pkg : mounted_apexes_) {
for (const auto& pair : pkg.second) {
- if (pair.first.is_temp_mount == match_temp_mounts) {
- handler(pkg.first, pair.first, pair.second);
- }
+ handler(pkg.first, pair.first, pair.second);
}
}
}
- inline std::optional<MountedApexData> GetLatestMountedApex(
- const std::string& package) REQUIRES(!mounted_apexes_mutex_) {
- std::optional<MountedApexData> ret;
- ForallMountedApexes(package,
- [&ret](const MountedApexData& data, bool latest) {
- if (latest) {
- ret.emplace(data);
- }
- });
- return ret;
- }
-
- void PopulateFromMounts(const std::string& active_apex_dir,
- const std::string& decompression_dir,
- const std::string& apex_hash_tree_dir);
-
- // Resets state of the database. Should only be used in testing.
- inline void Reset() REQUIRES(!mounted_apexes_mutex_) {
- std::lock_guard lock(mounted_apexes_mutex_);
- mounted_apexes_.clear();
- }
+ void PopulateFromMounts();
private:
// A map from package name to mounted apexes.
// Note: using std::maps to
// a) so we do not have to worry about iterator invalidation.
// b) do not have to const_cast (over std::set)
- // TODO(b/158467745): This structure (and functions) need to be guarded by
- // locks.
- std::map<std::string, std::map<MountedApexData, bool>> mounted_apexes_
- GUARDED_BY(mounted_apexes_mutex_);
-
- // To fix thread safety negative capability warning
- class Mutex : public std::mutex {
- public:
- // for negative capabilities
- const Mutex& operator!() const { return *this; }
- };
- mutable Mutex mounted_apexes_mutex_;
-
- inline void CheckAtMostOneLatest() REQUIRES(mounted_apexes_mutex_) {
- for (const auto& apex_set : mounted_apexes_) {
- size_t count = 0;
- for (const auto& pair : apex_set.second) {
- if (pair.second) {
- count++;
- }
- }
- CHECK_LE(count, 1u) << apex_set.first;
- }
- }
-
- inline void CheckUniqueLoopDm() REQUIRES(mounted_apexes_mutex_) {
- std::unordered_set<std::string> loop_devices;
- std::unordered_set<std::string> dm_devices;
- for (const auto& apex_set : mounted_apexes_) {
- for (const auto& pair : apex_set.second) {
- if (pair.first.loop_name != "") {
- CHECK(loop_devices.insert(pair.first.loop_name).second)
- << "Duplicate loop device: " << pair.first.loop_name;
- }
- if (pair.first.device_name != "") {
- CHECK(dm_devices.insert(pair.first.device_name).second)
- << "Duplicate dm device: " << pair.first.device_name;
- }
- if (pair.first.hashtree_loop_name != "") {
- CHECK(loop_devices.insert(pair.first.hashtree_loop_name).second)
- << "Duplicate loop device: " << pair.first.hashtree_loop_name;
- }
- }
- }
- }
+ // TODO: Eventually this structure (and functions) need to be guarded by
+ // locks.
+ std::map<std::string, std::map<MountedApexData, bool>> mounted_apexes_;
};
} // namespace apex
diff --git a/apexd/apex_database_test.cpp b/apexd/apex_database_test.cpp
index 8c3a98d0..522619fc 100644
--- a/apexd/apex_database_test.cpp
+++ b/apexd/apex_database_test.cpp
@@ -35,7 +35,6 @@ TEST(MountedApexDataTest, LinearOrder) {
constexpr const char* kDm[] = {"dm1", "dm2", "dm3"};
constexpr const char* kHashtreeLoopName[] = {"hash-loop1", "hash-loop2",
"hash-loop3"};
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
constexpr size_t kCount = arraysize(kLoopName) * arraysize(kPath) *
arraysize(kMount) * arraysize(kDm);
@@ -201,37 +200,6 @@ TEST(ApexDatabaseTest, MountMultiple) {
kDeviceName[3], kHashtreeLoopName[3]));
}
-TEST(ApexDatabaseTest, GetLatestMountedApex) {
- constexpr const char* kPackage = "package";
- constexpr const char* kLoopName = "loop";
- constexpr const char* kPath = "path";
- constexpr const char* kMountPoint = "mount";
- constexpr const char* kDeviceName = "dev";
- constexpr const char* kHashtreeLoopName = "hash-loop";
-
- MountedApexDatabase db;
- ASSERT_EQ(CountPackages(db), 0u);
-
- db.AddMountedApex(kPackage, true, kLoopName, kPath, kMountPoint, kDeviceName,
- kHashtreeLoopName);
-
- auto ret = db.GetLatestMountedApex(kPackage);
- MountedApexData expected(kLoopName, kPath, kMountPoint, kDeviceName,
- kHashtreeLoopName);
- ASSERT_TRUE(ret.has_value());
- ASSERT_EQ(ret->loop_name, std::string(kLoopName));
- ASSERT_EQ(ret->full_path, std::string(kPath));
- ASSERT_EQ(ret->mount_point, std::string(kMountPoint));
- ASSERT_EQ(ret->device_name, std::string(kDeviceName));
- ASSERT_EQ(ret->hashtree_loop_name, std::string(kHashtreeLoopName));
-}
-
-TEST(ApexDatabaseTest, GetLatestMountedApexReturnsNullopt) {
- MountedApexDatabase db;
- auto ret = db.GetLatestMountedApex("no-such-name");
- ASSERT_FALSE(ret.has_value());
-}
-
#pragma clang diagnostic push
// error: 'ReturnSentinel' was marked unused but was used
// [-Werror,-Wused-but-marked-unused]
diff --git a/apexd/apex_file.cpp b/apexd/apex_file.cpp
index c043defa..f91b5d18 100644
--- a/apexd/apex_file.cpp
+++ b/apexd/apex_file.cpp
@@ -23,108 +23,61 @@
#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 <google/protobuf/util/message_differencer.h>
#include <libavb/libavb.h>
-#include <ziparchive/zip_archive.h>
#include "apex_constants.h"
+#include "apex_preinstalled_data.h"
#include "apexd_utils.h"
+#include "string_log.h"
-using android::base::borrowed_fd;
-using android::base::ErrnoError;
+using android::base::EndsWith;
using android::base::Error;
using android::base::ReadFullyAtOffset;
-using android::base::RemoveFileIfExists;
using android::base::Result;
+using android::base::StartsWith;
using android::base::unique_fd;
-using ::apex::proto::ApexManifest;
+using google::protobuf::util::MessageDifferencer;
namespace android {
namespace apex {
namespace {
constexpr const char* kImageFilename = "apex_payload.img";
-constexpr const char* kCompressedApexFilename = "original_apex";
constexpr const char* kBundledPublicKeyFilename = "apex_pubkey";
-struct FsMagic {
- const char* type;
- int32_t offset;
- int16_t len;
- const char* magic;
-};
-constexpr const FsMagic kFsType[] = {{"f2fs", 1024, 4, "\x10\x20\xf5\xf2"},
- {"ext4", 1024 + 0x38, 2, "\123\357"}};
-
-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)) {
- return ErrnoError() << "Couldn't read filesystem magic";
- }
- if (memcmp(buf, fs.magic, fs.len) == 0) {
- return std::string(fs.type);
- }
- }
- return Error() << "Couldn't find filesystem magic";
-}
-
} // namespace
Result<ApexFile> ApexFile::Open(const std::string& path) {
- std::optional<int32_t> image_offset;
- std::optional<size_t> image_size;
+ int32_t image_offset;
+ size_t image_size;
std::string manifest_content;
std::string pubkey;
- std::optional<std::string> fs_type;
- ZipEntry entry;
-
- unique_fd fd(open(path.c_str(), O_RDONLY | O_BINARY | O_CLOEXEC));
- if (fd < 0) {
- 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, false);
+ int ret = OpenArchive(path.c_str(), &handle);
if (ret < 0) {
return Error() << "Failed to open package " << path << ": "
<< ErrorCodeString(ret);
}
- bool is_compressed = true;
- ret = FindEntry(handle, kCompressedApexFilename, &entry);
+ // Locate the mountable image within the zipfile and store offset and size.
+ ZipEntry entry;
+ ret = FindEntry(handle, kImageFilename, &entry);
if (ret < 0) {
- is_compressed = false;
- }
-
- if (!is_compressed) {
- // Locate the mountable image within the zipfile and store offset and size.
- ret = FindEntry(handle, kImageFilename, &entry);
- if (ret < 0) {
- return Error() << "Could not find entry \"" << kImageFilename
- << "\" or \"" << kCompressedApexFilename
- << "\" in package " << path << ": "
- << ErrorCodeString(ret);
- }
- image_offset = entry.offset;
- image_size = entry.uncompressed_length;
-
- auto fs_type_result = RetrieveFsType(fd, image_offset.value());
- if (!fs_type_result.ok()) {
- return Error() << "Failed to retrieve filesystem type for " << path
- << ": " << fs_type_result.error();
- }
- fs_type = std::move(*fs_type_result);
+ return Error() << "Could not find entry \"" << kImageFilename
+ << "\" in package " << path << ": " << ErrorCodeString(ret);
}
+ image_offset = entry.offset;
+ image_size = entry.uncompressed_length;
ret = FindEntry(handle, kManifestFilenamePb, &entry);
if (ret < 0) {
@@ -159,20 +112,8 @@ Result<ApexFile> ApexFile::Open(const std::string& path) {
return manifest.error();
}
- if (is_compressed && manifest->providesharedapexlibs()) {
- return Error() << "Apex providing sharedlibs shouldn't be compressed";
- }
-
- // b/179211712 the stored path should be the realpath, otherwise the path we
- // get by scanning the directory would be different from the path we get
- // by reading /proc/mounts, if the apex file is on a symlink dir.
- std::string realpath;
- if (!android::base::Realpath(path, &realpath)) {
- return ErrnoError() << "can't get realpath of " << path;
- }
-
- return ApexFile(realpath, image_offset, image_size, std::move(*manifest),
- pubkey, fs_type, is_compressed);
+ return ApexFile(path, image_offset, image_size, std::move(*manifest), pubkey,
+ isPathForBuiltinApexes(path));
}
// AVB-related code.
@@ -181,7 +122,7 @@ namespace {
static constexpr int kVbMetaMaxSize = 64 * 1024;
-std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
+std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) {
std::ostringstream s;
s << std::hex << std::setfill('0');
@@ -191,32 +132,28 @@ std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
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;
+std::string getSalt(const AvbHashtreeDescriptor& desc,
+ const uint8_t* trailingData) {
+ const uint8_t* desc_salt = trailingData + desc.partition_name_len;
- return BytesToHex(desc_salt, desc.salt_len);
+ return bytes_to_hex(desc_salt, desc.salt_len);
}
-std::string GetDigest(const AvbHashtreeDescriptor& desc,
- const uint8_t* trailing_data) {
+std::string getDigest(const AvbHashtreeDescriptor& desc,
+ const uint8_t* trailingData) {
const uint8_t* desc_digest =
- trailing_data + desc.partition_name_len + desc.salt_len;
+ trailingData + desc.partition_name_len + desc.salt_len;
- return BytesToHex(desc_digest, desc.root_digest_len);
+ return bytes_to_hex(desc_digest, desc.root_digest_len);
}
-Result<std::unique_ptr<AvbFooter>> GetAvbFooter(const ApexFile& apex,
+Result<std::unique_ptr<AvbFooter>> getAvbFooter(const ApexFile& apex,
const unique_fd& fd) {
std::array<uint8_t, AVB_FOOTER_SIZE> footer_data;
auto footer = std::make_unique<AvbFooter>();
// The AVB footer is located in the last part of the image
- if (!apex.GetImageOffset() || !apex.GetImageSize()) {
- return Error() << "Cannot check avb footer without image offset and size";
- }
- off_t offset = apex.GetImageSize().value() + apex.GetImageOffset().value() -
- AVB_FOOTER_SIZE;
+ off_t offset = apex.GetImageSize() + apex.GetImageOffset() - AVB_FOOTER_SIZE;
int ret = lseek(fd, offset, SEEK_SET);
if (ret == -1) {
return ErrnoError() << "Couldn't seek to AVB footer";
@@ -242,10 +179,8 @@ bool CompareKeys(const uint8_t* key, size_t length,
memcmp(&public_key_content[0], key, length) == 0;
}
-// Verifies correctness of vbmeta and returns public key it was signed with.
-Result<std::span<const uint8_t>> VerifyVbMetaSignature(const ApexFile& apex,
- const uint8_t* data,
- size_t length) {
+Result<void> verifyVbMetaSignature(const ApexFile& apex, const uint8_t* data,
+ size_t length) {
const uint8_t* pk;
size_t pk_len;
AvbVBMetaVerifyResult res;
@@ -266,46 +201,49 @@ Result<std::span<const uint8_t>> VerifyVbMetaSignature(const ApexFile& apex,
return Error() << "Error verifying " << apex.GetPath() << ": "
<< "unsupported version";
default:
- return Error() << "Unknown vmbeta_image_verify return value : " << res;
+ return Errorf("Unknown vmbeta_image_verify return value");
}
- return std::span<const uint8_t>(pk, pk_len);
+ Result<const std::string> public_key = getApexKey(apex.GetManifest().name());
+ if (public_key.ok()) {
+ // TODO(b/115718846)
+ // We need to decide whether we need rollback protection, and whether
+ // we can use the rollback protection provided by libavb.
+ if (!CompareKeys(pk, pk_len, *public_key)) {
+ return Error() << "Error verifying " << apex.GetPath() << ": "
+ << "public key doesn't match the pre-installed one";
+ }
+ } else {
+ return public_key.error();
+ }
+ LOG(VERBOSE) << apex.GetPath() << ": public key matches.";
+ return {};
}
-Result<std::unique_ptr<uint8_t[]>> VerifyVbMeta(const ApexFile& apex,
+Result<std::unique_ptr<uint8_t[]>> verifyVbMeta(const ApexFile& apex,
const unique_fd& fd,
- const AvbFooter& footer,
- const std::string& public_key) {
+ const AvbFooter& footer) {
if (footer.vbmeta_size > kVbMetaMaxSize) {
return Errorf("VbMeta size in footer exceeds kVbMetaMaxSize.");
}
- if (!apex.GetImageOffset()) {
- return Error() << "Cannot check VbMeta size without image offset";
- }
-
- off_t offset = apex.GetImageOffset().value() + footer.vbmeta_offset;
+ off_t offset = apex.GetImageOffset() + footer.vbmeta_offset;
std::unique_ptr<uint8_t[]> vbmeta_buf(new uint8_t[footer.vbmeta_size]);
if (!ReadFullyAtOffset(fd, vbmeta_buf.get(), footer.vbmeta_size, offset)) {
return ErrnoError() << "Couldn't read AVB meta-data";
}
- Result<std::span<const uint8_t>> st =
- VerifyVbMetaSignature(apex, vbmeta_buf.get(), footer.vbmeta_size);
+ Result<void> st =
+ verifyVbMetaSignature(apex, vbmeta_buf.get(), footer.vbmeta_size);
if (!st.ok()) {
return st.error();
}
- if (!CompareKeys(st->data(), st->size(), public_key)) {
- return Error() << "Error verifying " << apex.GetPath() << " : "
- << "public key doesn't match the pre-installed one";
- }
-
return vbmeta_buf;
}
-Result<const AvbHashtreeDescriptor*> FindDescriptor(uint8_t* vbmeta_data,
+Result<const AvbHashtreeDescriptor*> findDescriptor(uint8_t* vbmeta_data,
size_t vbmeta_size) {
const AvbDescriptor** descriptors;
size_t num_descriptors;
@@ -339,127 +277,118 @@ Result<const AvbHashtreeDescriptor*> FindDescriptor(uint8_t* vbmeta_data,
return Errorf("Couldn't find any AVB hashtree descriptors.");
}
-Result<std::unique_ptr<AvbHashtreeDescriptor>> VerifyDescriptor(
+Result<std::unique_ptr<AvbHashtreeDescriptor>> verifyDescriptor(
const AvbHashtreeDescriptor* desc) {
- auto verified_desc = std::make_unique<AvbHashtreeDescriptor>();
+ auto verifiedDesc = std::make_unique<AvbHashtreeDescriptor>();
if (!avb_hashtree_descriptor_validate_and_byteswap(desc,
- verified_desc.get())) {
+ verifiedDesc.get())) {
return Errorf("Couldn't validate AvbDescriptor.");
}
- return verified_desc;
+ return verifiedDesc;
}
} // namespace
-Result<ApexVerityData> ApexFile::VerifyApexVerity(
- const std::string& public_key) const {
- if (IsCompressed()) {
- return Error() << "Cannot verify ApexVerity of compressed APEX";
- }
-
- ApexVerityData verity_data;
+Result<ApexVerityData> ApexFile::VerifyApexVerity() const {
+ ApexVerityData verityData;
unique_fd fd(open(GetPath().c_str(), O_RDONLY | O_CLOEXEC));
if (fd.get() == -1) {
return ErrnoError() << "Failed to open " << GetPath();
}
- Result<std::unique_ptr<AvbFooter>> footer = GetAvbFooter(*this, fd);
+ Result<std::unique_ptr<AvbFooter>> footer = getAvbFooter(*this, fd);
if (!footer.ok()) {
return footer.error();
}
Result<std::unique_ptr<uint8_t[]>> vbmeta_data =
- VerifyVbMeta(*this, fd, **footer, public_key);
+ verifyVbMeta(*this, fd, **footer);
if (!vbmeta_data.ok()) {
return vbmeta_data.error();
}
Result<const AvbHashtreeDescriptor*> descriptor =
- FindDescriptor(vbmeta_data->get(), (*footer)->vbmeta_size);
+ findDescriptor(vbmeta_data->get(), (*footer)->vbmeta_size);
if (!descriptor.ok()) {
return descriptor.error();
}
- Result<std::unique_ptr<AvbHashtreeDescriptor>> verified_descriptor =
- VerifyDescriptor(*descriptor);
- if (!verified_descriptor.ok()) {
- return verified_descriptor.error();
+ Result<std::unique_ptr<AvbHashtreeDescriptor>> verifiedDescriptor =
+ verifyDescriptor(*descriptor);
+ if (!verifiedDescriptor.ok()) {
+ return verifiedDescriptor.error();
}
- verity_data.desc = std::move(*verified_descriptor);
+ verityData.desc = std::move(*verifiedDescriptor);
// This area is now safe to access, because we just verified it
- const uint8_t* trailing_data =
+ const uint8_t* trailingData =
(const uint8_t*)*descriptor + sizeof(AvbHashtreeDescriptor);
- verity_data.hash_algorithm =
+ verityData.hash_algorithm =
reinterpret_cast<const char*>((*descriptor)->hash_algorithm);
- verity_data.salt = GetSalt(*verity_data.desc, trailing_data);
- verity_data.root_digest = GetDigest(*verity_data.desc, trailing_data);
+ verityData.salt = getSalt(*verityData.desc, trailingData);
+ verityData.root_digest = getDigest(*verityData.desc, trailingData);
- return verity_data;
+ return verityData;
}
-Result<void> ApexFile::Decompress(const std::string& dest_path) const {
- const std::string& src_path = GetPath();
-
- LOG(INFO) << "Decompressing" << src_path << " to " << dest_path;
-
- // We should decompress compressed APEX files only
- if (!IsCompressed()) {
- return ErrnoError() << "Cannot decompress an uncompressed APEX";
+Result<void> ApexFile::VerifyManifestMatches(
+ const std::string& mount_path) const {
+ Result<ApexManifest> verifiedManifest =
+ ReadManifest(mount_path + "/" + kManifestFilenamePb);
+ if (!verifiedManifest.ok()) {
+ return verifiedManifest.error();
}
- // Get file descriptor of the compressed apex file
- unique_fd src_fd(open(src_path.c_str(), O_RDONLY | O_CLOEXEC));
- if (src_fd.get() == -1) {
- return ErrnoError() << "Failed to open compressed APEX " << GetPath();
- }
-
- // Open it as a zip file
- ZipArchiveHandle handle;
- int ret = OpenArchiveFd(src_fd.get(), src_path.c_str(), &handle, false);
- if (ret < 0) {
- return Error() << "Failed to open package " << src_path << ": "
- << ErrorCodeString(ret);
+ if (!MessageDifferencer::Equals(manifest_, *verifiedManifest)) {
+ return Errorf(
+ "Manifest inside filesystem does not match manifest outside it");
}
- auto handle_guard =
- android::base::make_scope_guard([&handle] { CloseArchive(handle); });
- // Find the original apex file inside the zip and extract to dest
- ZipEntry entry;
- ret = FindEntry(handle, kCompressedApexFilename, &entry);
- if (ret < 0) {
- return Error() << "Could not find entry \"" << kCompressedApexFilename
- << "\" in package " << src_path << ": "
- << ErrorCodeString(ret);
- }
+ return {};
+}
- // Open destination file descriptor
- unique_fd dest_fd(
- open(dest_path.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL, 0644));
- if (dest_fd.get() == -1) {
- return ErrnoError() << "Failed to open decompression destination "
- << dest_path.c_str();
- }
+Result<std::vector<std::string>> FindApexes(
+ const std::vector<std::string>& paths) {
+ std::vector<std::string> result;
+ for (const auto& path : paths) {
+ auto exist = PathExists(path);
+ if (!exist.ok()) {
+ return exist.error();
+ }
+ if (!*exist) continue;
- // Prepare a guard that deletes the extracted file if anything goes wrong
- auto decompressed_guard = android::base::make_scope_guard(
- [&dest_path] { RemoveFileIfExists(dest_path); });
+ const auto& apexes = FindApexFilesByName(path);
+ if (!apexes.ok()) {
+ return apexes;
+ }
- // Extract the original_apex to dest_path
- ret = ExtractEntryToFile(handle, &entry, dest_fd.get());
- if (ret < 0) {
- return Error() << "Could not decompress to file " << dest_path << " "
- << ErrorCodeString(ret);
+ result.insert(result.end(), apexes->begin(), apexes->end());
}
+ return result;
+}
- // Verification complete. Accept the decompressed file
- decompressed_guard.Disable();
- LOG(VERBOSE) << "Decompressed " << src_path << " to " << dest_path;
+Result<std::vector<std::string>> FindApexFilesByName(const std::string& path) {
+ auto filter_fn = [](const std::filesystem::directory_entry& entry) {
+ std::error_code ec;
+ if (entry.is_regular_file(ec) &&
+ EndsWith(entry.path().filename().string(), kApexPackageSuffix)) {
+ return true; // APEX file, take.
+ }
+ return false;
+ };
+ return ReadDir(path, filter_fn);
+}
- return {};
+bool isPathForBuiltinApexes(const std::string& path) {
+ for (const auto& dir : kApexPackageBuiltinDirs) {
+ if (StartsWith(path, dir)) {
+ return true;
+ }
+ }
+ return false;
}
} // namespace apex
diff --git a/apexd/apex_file.h b/apexd/apex_file.h
index 60d5feb2..0476911c 100644
--- a/apexd/apex_file.h
+++ b/apexd/apex_file.h
@@ -23,7 +23,9 @@
#include <android-base/result.h>
#include <libavb/libavb.h>
+#include <ziparchive/zip_archive.h>
+#include "apex_constants.h"
#include "apex_manifest.h"
namespace android {
@@ -44,42 +46,43 @@ class ApexFile {
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<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_; }
+ int32_t GetImageOffset() const { return image_offset_; }
+ size_t GetImageSize() const { return image_size_; }
+ const ApexManifest& GetManifest() const { return manifest_; }
const std::string& GetBundledPublicKey() const { return apex_pubkey_; }
- const std::optional<std::string>& GetFsType() const { return fs_type_; }
- android::base::Result<ApexVerityData> VerifyApexVerity(
- const std::string& public_key) const;
- bool IsCompressed() const { return is_compressed_; }
- android::base::Result<void> Decompress(const std::string& output_path) const;
+ bool IsBuiltin() const { return is_builtin_; }
+ android::base::Result<ApexVerityData> VerifyApexVerity() const;
+ android::base::Result<void> VerifyManifestMatches(
+ const std::string& mount_path) const;
private:
- ApexFile(const std::string& apex_path,
- 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)
+ ApexFile(const std::string& apex_path, int32_t image_offset,
+ size_t image_size, ApexManifest manifest,
+ const std::string& apex_pubkey, bool is_builtin)
: apex_path_(apex_path),
image_offset_(image_offset),
image_size_(image_size),
manifest_(std::move(manifest)),
apex_pubkey_(apex_pubkey),
- fs_type_(fs_type),
- is_compressed_(is_compressed) {}
+ is_builtin_(is_builtin) {}
std::string apex_path_;
- std::optional<int32_t> image_offset_;
- std::optional<size_t> image_size_;
- ::apex::proto::ApexManifest manifest_;
+ int32_t image_offset_;
+ size_t image_size_;
+ ApexManifest manifest_;
std::string apex_pubkey_;
- std::optional<std::string> fs_type_;
- bool is_compressed_;
+ bool is_builtin_;
};
+android::base::Result<std::vector<std::string>> FindApexes(
+ const std::vector<std::string>& paths);
+android::base::Result<std::vector<std::string>> FindApexFilesByName(
+ const std::string& path);
+
+bool isPathForBuiltinApexes(const std::string& path);
+
} // namespace apex
} // namespace android
diff --git a/apexd/apex_file_repository.cpp b/apexd/apex_file_repository.cpp
deleted file mode 100644
index c50d136f..00000000
--- a/apexd/apex_file_repository.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "apexd"
-
-#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 "apex_constants.h"
-#include "apex_file.h"
-#include "apexd_utils.h"
-
-using android::base::EndsWith;
-using android::base::Error;
-using android::base::GetProperty;
-using android::base::Result;
-
-namespace android {
-namespace apex {
-
-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) {
- LOG(WARNING) << dir << " does not exist. Skipping";
- return {};
- }
-
- Result<std::vector<std::string>> all_apex_files = FindFilesBySuffix(
- dir, {kApexPackageSuffix, kCompressedApexPackageSuffix});
- if (!all_apex_files.ok()) {
- return all_apex_files.error();
- }
-
- // TODO(b/179248390): scan parallelly if possible
- for (const auto& file : *all_apex_files) {
- LOG(INFO) << "Found pre-installed APEX " << file;
- Result<ApexFile> apex_file = ApexFile::Open(file);
- if (!apex_file.ok()) {
- return Error() << "Failed to open " << file << " : " << apex_file.error();
- }
-
- const std::string& name = apex_file->GetManifest().name();
- auto it = pre_installed_store_.find(name);
- if (it == pre_installed_store_.end()) {
- pre_installed_store_.emplace(name, std::move(*apex_file));
- } else if (it->second.GetPath() != apex_file->GetPath()) {
- auto level = base::FATAL;
- // On some development (non-REL) builds the VNDK apex could be in /vendor.
- // When testing CTS-on-GSI on these builds, there would be two VNDK apexes
- // in the system, one in /system and one in /vendor.
- static constexpr char kVndkApexModuleNamePrefix[] = "com.android.vndk.";
- static constexpr char kPlatformVersionCodenameProperty[] =
- "ro.build.version.codename";
- if (android::base::StartsWith(name, kVndkApexModuleNamePrefix) &&
- GetProperty(kPlatformVersionCodenameProperty, "REL") != "REL") {
- level = android::base::INFO;
- }
- LOG(level) << "Found two apex packages " << it->second.GetPath()
- << " and " << apex_file->GetPath()
- << " with the same module name " << name;
- } else if (it->second.GetBundledPublicKey() !=
- apex_file->GetBundledPublicKey()) {
- LOG(FATAL) << "Public key of apex package " << it->second.GetPath()
- << " (" << name << ") has unexpectedly changed";
- }
- }
- return {};
-}
-
-ApexFileRepository& ApexFileRepository::GetInstance() {
- static ApexFileRepository instance;
- return instance;
-}
-
-android::base::Result<void> ApexFileRepository::AddPreInstalledApex(
- const std::vector<std::string>& prebuilt_dirs) {
- for (const auto& dir : prebuilt_dirs) {
- if (auto result = ScanBuiltInDir(dir); !result.ok()) {
- return result.error();
- }
- }
- return {};
-}
-
-// TODO(b/179497746): AddDataApex should not concern with filtering out invalid
-// apex.
-Result<void> ApexFileRepository::AddDataApex(const std::string& data_dir) {
- LOG(INFO) << "Scanning " << data_dir << " for data ApexFiles";
- if (access(data_dir.c_str(), F_OK) != 0 && errno == ENOENT) {
- LOG(WARNING) << data_dir << " does not exist. Skipping";
- return {};
- }
-
- Result<std::vector<std::string>> active_apex =
- FindFilesBySuffix(data_dir, {kApexPackageSuffix});
- if (!active_apex.ok()) {
- return active_apex.error();
- }
-
- // TODO(b/179248390): scan parallelly if possible
- for (const auto& file : *active_apex) {
- LOG(INFO) << "Found updated apex " << file;
- Result<ApexFile> apex_file = ApexFile::Open(file);
- if (!apex_file.ok()) {
- LOG(ERROR) << "Failed to open " << file << " : " << apex_file.error();
- continue;
- }
-
- const std::string& name = apex_file->GetManifest().name();
- if (!HasPreInstalledVersion(name)) {
- LOG(ERROR) << "Skipping " << file << " : no preisntalled apex";
- // Ignore data apex without corresponding pre-installed apex
- continue;
- }
- auto pre_installed_public_key = GetPublicKey(name);
- if (!pre_installed_public_key.ok() ||
- apex_file->GetBundledPublicKey() != *pre_installed_public_key) {
- // Ignore data apex if public key doesn't match with pre-installed apex
- LOG(ERROR) << "Skipping " << file
- << " : public key doesn't match pre-installed one";
- continue;
- }
-
- if (EndsWith(apex_file->GetPath(), kDecompressedApexPackageSuffix)) {
- LOG(WARNING) << "Skipping " << file
- << " : Non-decompressed APEX should not have "
- << kDecompressedApexPackageSuffix << " suffix";
- continue;
- }
-
- auto it = data_store_.find(name);
- if (it == data_store_.end()) {
- data_store_.emplace(name, std::move(*apex_file));
- continue;
- }
-
- const auto& existing_version = it->second.GetManifest().version();
- const auto new_version = apex_file->GetManifest().version();
- // If multiple data apexs are preset, select the one with highest version
- bool prioritize_higher_version = new_version > existing_version;
- // For same version, non-decompressed apex gets priority
- if (prioritize_higher_version) {
- it->second = std::move(*apex_file);
- }
- }
- return {};
-}
-
-// TODO(b/179497746): remove this method when we add api for fetching ApexFile
-// by name
-Result<const std::string> ApexFileRepository::GetPublicKey(
- const std::string& name) const {
- auto it = pre_installed_store_.find(name);
- if (it == pre_installed_store_.end()) {
- return Error() << "No preinstalled apex found for package " << name;
- }
- return it->second.GetBundledPublicKey();
-}
-
-// TODO(b/179497746): remove this method when we add api for fetching ApexFile
-// by name
-Result<const std::string> ApexFileRepository::GetPreinstalledPath(
- const std::string& name) const {
- auto it = pre_installed_store_.find(name);
- if (it == pre_installed_store_.end()) {
- return Error() << "No preinstalled data found for package " << name;
- }
- return it->second.GetPath();
-}
-
-// TODO(b/179497746): remove this method when we add api for fetching ApexFile
-// by name
-Result<const std::string> ApexFileRepository::GetDataPath(
- const std::string& name) const {
- auto it = data_store_.find(name);
- if (it == data_store_.end()) {
- return Error() << "No data apex found for package " << name;
- }
- return it->second.GetPath();
-}
-
-bool ApexFileRepository::HasPreInstalledVersion(const std::string& name) const {
- return pre_installed_store_.find(name) != pre_installed_store_.end();
-}
-
-bool ApexFileRepository::HasDataVersion(const std::string& name) const {
- return data_store_.find(name) != data_store_.end();
-}
-
-// ApexFile is considered a decompressed APEX if it is located in decompression
-// dir
-bool ApexFileRepository::IsDecompressedApex(const ApexFile& apex) const {
- return apex.GetPath().starts_with(decompression_dir_);
-}
-
-bool ApexFileRepository::IsPreInstalledApex(const ApexFile& apex) const {
- auto it = pre_installed_store_.find(apex.GetManifest().name());
- if (it == pre_installed_store_.end()) {
- return false;
- }
- return it->second.GetPath() == apex.GetPath() || IsDecompressedApex(apex);
-}
-
-std::vector<ApexFileRef> ApexFileRepository::GetPreInstalledApexFiles() const {
- std::vector<ApexFileRef> result;
- for (const auto& it : pre_installed_store_) {
- result.emplace_back(std::cref(it.second));
- }
- return std::move(result);
-}
-
-std::vector<ApexFileRef> ApexFileRepository::GetDataApexFiles() const {
- std::vector<ApexFileRef> result;
- for (const auto& it : data_store_) {
- result.emplace_back(std::cref(it.second));
- }
- return std::move(result);
-}
-
-// Group pre-installed APEX and data APEX by name
-std::unordered_map<std::string, std::vector<ApexFileRef>>
-ApexFileRepository::AllApexFilesByName() const {
- // Collect all apex files
- std::vector<ApexFileRef> all_apex_files;
- auto pre_installed_apexs = GetPreInstalledApexFiles();
- auto data_apexs = GetDataApexFiles();
- std::move(pre_installed_apexs.begin(), pre_installed_apexs.end(),
- std::back_inserter(all_apex_files));
- std::move(data_apexs.begin(), data_apexs.end(),
- std::back_inserter(all_apex_files));
-
- // Group them by name
- std::unordered_map<std::string, std::vector<ApexFileRef>> result;
- for (const auto& apex_file_ref : all_apex_files) {
- const ApexFile& apex_file = apex_file_ref.get();
- const std::string& package_name = apex_file.GetManifest().name();
- if (result.find(package_name) == result.end()) {
- result[package_name] = std::vector<ApexFileRef>{};
- }
- result[package_name].emplace_back(apex_file_ref);
- }
-
- return std::move(result);
-}
-
-ApexFileRef ApexFileRepository::GetDataApex(const std::string& name) const {
- auto it = data_store_.find(name);
- CHECK(it != data_store_.end());
- return std::cref(it->second);
-}
-
-ApexFileRef ApexFileRepository::GetPreInstalledApex(
- const std::string& name) const {
- auto it = pre_installed_store_.find(name);
- CHECK(it != pre_installed_store_.end());
- return std::cref(it->second);
-}
-
-} // namespace apex
-} // namespace android
diff --git a/apexd/apex_file_repository.h b/apexd/apex_file_repository.h
deleted file mode 100644
index e9ccf7ee..00000000
--- a/apexd/apex_file_repository.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <functional>
-#include <string>
-#include <unordered_map>
-#include <vector>
-#include "apex_constants.h"
-#include "apex_file.h"
-
-#include <android-base/result.h>
-
-namespace android {
-namespace apex {
-
-using ApexFileRef = std::reference_wrapper<const android::apex::ApexFile>;
-
-// This class serves as a ApexFile repository for all apexes on device. It also
-// provides information about the ApexFiles it hosts, such as which are
-// pre-installed and which are data. Such information can be used, for example,
-// to verify validity of an apex before trying to mount it.
-//
-// It's expected to have a single instance of this class in a process that
-// mounts apexes (e.g. apexd, otapreopt_chroot).
-class ApexFileRepository final {
- public:
- // c-tor and d-tor are exposed for testing.
- explicit ApexFileRepository(
- const std::string& decompression_dir = kApexDecompressedDir)
- : decompression_dir_(decompression_dir){};
-
- ~ApexFileRepository() {
- pre_installed_store_.clear();
- data_store_.clear();
- };
-
- // Returns a singletone instance of this class.
- static ApexFileRepository& GetInstance();
-
- // Populate instance by collecting pre-installed apex files from the given
- // |prebuilt_dirs|.
- // 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.
- android::base::Result<void> AddPreInstalledApex(
- const std::vector<std::string>& prebuilt_dirs);
-
- // 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
- // finished, all queries to the instance are thread safe.
- android::base::Result<void> AddDataApex(const std::string& data_dir);
-
- // Returns trusted public key for an apex with the given |name|.
- android::base::Result<const std::string> GetPublicKey(
- const std::string& name) const;
-
- // Returns path to the pre-installed version of an apex with the given |name|.
- android::base::Result<const std::string> GetPreinstalledPath(
- const std::string& name) const;
-
- // Returns path to the data version of an apex with the given |name|.
- android::base::Result<const std::string> GetDataPath(
- 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;
-
- // Checks whether there is a data version of an apex with the given |name|.
- bool HasDataVersion(const std::string& name) const;
-
- // Checks if given |apex| is pre-installed.
- bool IsPreInstalledApex(const ApexFile& apex) const;
-
- // Checks if given |apex| is decompressed from a pre-installed APEX
- bool IsDecompressedApex(const ApexFile& apex) const;
-
- // Returns reference to all pre-installed APEX on device
- std::vector<ApexFileRef> GetPreInstalledApexFiles() const;
-
- // Returns reference to all data APEX on device
- std::vector<ApexFileRef> GetDataApexFiles() const;
-
- // Group all ApexFiles on device by their package name
- std::unordered_map<std::string, std::vector<ApexFileRef>> AllApexFilesByName()
- const;
-
- // Returns a pre-installed version of apex with the given name. Caller is
- // expected to check if there is a pre-installed apex with the given name
- // using |HasPreinstalledVersion| function.
- ApexFileRef GetPreInstalledApex(const std::string& name) const;
- // Returns a data version of apex with the given name. Caller is
- // expected to check if there is a data apex with the given name
- // using |HasDataVersion| function.
- ApexFileRef GetDataApex(const std::string& name) const;
-
- // Clears ApexFileRepostiry.
- // Only use in tests.
- void Reset(const std::string& decompression_dir = kApexDecompressedDir) {
- pre_installed_store_.clear();
- data_store_.clear();
- decompression_dir_ = decompression_dir;
- }
-
- private:
- // Non-copyable && non-moveable.
- ApexFileRepository(const ApexFileRepository&) = delete;
- ApexFileRepository& operator=(const ApexFileRepository&) = delete;
- ApexFileRepository& operator=(ApexFileRepository&&) = delete;
- ApexFileRepository(ApexFileRepository&&) = delete;
-
- // Scans apexes in the given directory and adds collected data into
- // |pre_installed_store_|.
- android::base::Result<void> ScanBuiltInDir(const std::string& dir);
-
- std::unordered_map<std::string, ApexFile> pre_installed_store_, data_store_;
- // Decompression directory which will be used to determine if apex is
- // decompressed or not
- std::string decompression_dir_;
-};
-
-} // namespace apex
-} // namespace android
diff --git a/apexd/apex_file_repository_test.cpp b/apexd/apex_file_repository_test.cpp
deleted file mode 100644
index c1f5d533..00000000
--- a/apexd/apex_file_repository_test.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#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"
-
-namespace android {
-namespace apex {
-
-using namespace std::literals;
-
-namespace fs = std::filesystem;
-
-using android::apex::testing::ApexFileEq;
-using android::apex::testing::IsOk;
-using android::base::GetExecutableDirectory;
-using android::base::StringPrintf;
-using ::testing::ByRef;
-using ::testing::UnorderedElementsAre;
-
-static std::string GetTestDataDir() { return GetExecutableDirectory(); }
-static std::string GetTestFile(const std::string& name) {
- return GetTestDataDir() + "/" + name;
-}
-
-namespace {
-// Copies the compressed apex to |built_in_dir| and decompresses it to
-// |decompression_dir
-void PrepareCompressedApex(const std::string& name,
- const std::string& built_in_dir,
- const std::string& decompression_dir) {
- fs::copy(GetTestFile(name), built_in_dir);
- auto compressed_apex =
- ApexFile::Open(StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str()));
-
- const auto& pkg_name = compressed_apex->GetManifest().name();
- const int version = compressed_apex->GetManifest().version();
-
- auto decompression_path =
- StringPrintf("%s/%s@%d%s", decompression_dir.c_str(), pkg_name.c_str(),
- version, kDecompressedApexPackageSuffix);
- compressed_apex->Decompress(decompression_path);
-}
-} // namespace
-
-TEST(ApexFileRepositoryTest, InitializeSuccess) {
- // Prepare test data.
- TemporaryDir built_in_dir, data_dir, decompression_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("apex.apexd_test_different_app.apex"),
- built_in_dir.path);
-
- fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
- fs::copy(GetTestFile("apex.apexd_test_different_app.apex"), data_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- // Now test that apexes were scanned correctly;
- auto test_fn = [&](const std::string& apex_name) {
- auto apex = ApexFile::Open(GetTestFile(apex_name));
- ASSERT_TRUE(IsOk(apex));
-
- {
- auto ret = instance.GetPublicKey(apex->GetManifest().name());
- ASSERT_TRUE(IsOk(ret));
- ASSERT_EQ(apex->GetBundledPublicKey(), *ret);
- }
-
- {
- auto ret = instance.GetPreinstalledPath(apex->GetManifest().name());
- ASSERT_TRUE(IsOk(ret));
- ASSERT_EQ(StringPrintf("%s/%s", built_in_dir.path, apex_name.c_str()),
- *ret);
- }
-
- {
- auto ret = instance.GetDataPath(apex->GetManifest().name());
- ASSERT_TRUE(IsOk(ret));
- ASSERT_EQ(StringPrintf("%s/%s", data_dir.path, apex_name.c_str()), *ret);
- }
-
- ASSERT_TRUE(instance.HasPreInstalledVersion(apex->GetManifest().name()));
- ASSERT_TRUE(instance.HasDataVersion(apex->GetManifest().name()));
- };
-
- test_fn("apex.apexd_test.apex");
- test_fn("apex.apexd_test_different_app.apex");
-
- // Check that second call will succeed as well.
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- test_fn("apex.apexd_test.apex");
- test_fn("apex.apexd_test_different_app.apex");
-}
-
-TEST(ApexFileRepositoryTest, InitializeFailureCorruptApex) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
- fs::copy(GetTestFile("apex.apexd_test_corrupt_superblock_apex.apex"),
- td.path);
-
- ApexFileRepository instance;
- ASSERT_FALSE(IsOk(instance.AddPreInstalledApex({td.path})));
-}
-
-TEST(ApexFileRepositoryTest, InitializeCompressedApexWithoutApex) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("com.android.apex.compressed.v1_without_apex.capex"),
- td.path);
-
- ApexFileRepository instance;
- // Compressed APEX without APEX cannot be opened
- ASSERT_FALSE(IsOk(instance.AddPreInstalledApex({td.path})));
-}
-
-TEST(ApexFileRepositoryTest, InitializeSameNameDifferentPathAborts) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
- fs::copy(GetTestFile("apex.apexd_test.apex"),
- StringPrintf("%s/other.apex", td.path));
-
- ASSERT_DEATH(
- {
- ApexFileRepository instance;
- instance.AddPreInstalledApex({td.path});
- },
- "");
-}
-
-TEST(ApexFileRepositoryTest,
- InitializeSameNameDifferentPathAbortsCompressedApex) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
- StringPrintf("%s/other.capex", td.path));
-
- ASSERT_DEATH(
- {
- ApexFileRepository instance;
- instance.AddPreInstalledApex({td.path});
- },
- "");
-}
-
-TEST(ApexFileRepositoryTest, InitializePublicKeyUnexpectdlyChangedAborts) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
-
- // Check that apex was loaded.
- auto path = instance.GetPreinstalledPath("com.android.apex.test_package");
- ASSERT_TRUE(IsOk(path));
- ASSERT_EQ(StringPrintf("%s/apex.apexd_test.apex", td.path), *path);
-
- auto public_key = instance.GetPublicKey("com.android.apex.test_package");
- ASSERT_TRUE(IsOk(public_key));
-
- // Substitute it with another apex with the same name, but different public
- // key.
- fs::copy(GetTestFile("apex.apexd_test_different_key.apex"), *path,
- fs::copy_options::overwrite_existing);
-
- {
- auto apex = ApexFile::Open(*path);
- ASSERT_TRUE(IsOk(apex));
- // Check module name hasn't changed.
- ASSERT_EQ("com.android.apex.test_package", apex->GetManifest().name());
- // Check public key has changed.
- ASSERT_NE(*public_key, apex->GetBundledPublicKey());
- }
-
- ASSERT_DEATH({ instance.AddPreInstalledApex({td.path}); }, "");
-}
-
-TEST(ApexFileRepositoryTest,
- InitializePublicKeyUnexpectdlyChangedAbortsCompressedApex) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
-
- // Check that apex was loaded.
- auto path = instance.GetPreinstalledPath("com.android.apex.compressed");
- ASSERT_TRUE(IsOk(path));
- ASSERT_EQ(StringPrintf("%s/com.android.apex.compressed.v1.capex", td.path),
- *path);
-
- auto public_key = instance.GetPublicKey("com.android.apex.compressed");
- ASSERT_TRUE(IsOk(public_key));
-
- // Substitute it with another apex with the same name, but different public
- // key.
- fs::copy(GetTestFile("com.android.apex.compressed_different_key.capex"),
- *path, fs::copy_options::overwrite_existing);
-
- {
- auto apex = ApexFile::Open(*path);
- ASSERT_TRUE(IsOk(apex));
- // Check module name hasn't changed.
- ASSERT_EQ("com.android.apex.compressed", apex->GetManifest().name());
- // Check public key has changed.
- ASSERT_NE(*public_key, apex->GetBundledPublicKey());
- }
-
- ASSERT_DEATH({ instance.AddPreInstalledApex({td.path}); }, "");
-}
-
-TEST(ApexFileRepositoryTest, IsPreInstalledApex) {
- // Prepare test data.
- TemporaryDir td;
- fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
-
- auto compressed_apex = ApexFile::Open(
- StringPrintf("%s/com.android.apex.compressed.v1.capex", td.path));
- ASSERT_TRUE(IsOk(compressed_apex));
- ASSERT_TRUE(instance.IsPreInstalledApex(*compressed_apex));
-
- auto apex1 = ApexFile::Open(StringPrintf("%s/apex.apexd_test.apex", td.path));
- ASSERT_TRUE(IsOk(apex1));
- ASSERT_TRUE(instance.IsPreInstalledApex(*apex1));
-
- // It's same apex, but path is different. Shouldn't be treated as
- // pre-installed.
- auto apex2 = ApexFile::Open(GetTestFile("apex.apexd_test.apex"));
- ASSERT_TRUE(IsOk(apex2));
- ASSERT_FALSE(instance.IsPreInstalledApex(*apex2));
-
- auto apex3 =
- ApexFile::Open(GetTestFile("apex.apexd_test_different_app.apex"));
- ASSERT_TRUE(IsOk(apex3));
- ASSERT_FALSE(instance.IsPreInstalledApex(*apex3));
-}
-
-TEST(ApexFileRepositoryTest, IsDecompressedApex) {
- // Prepare instance
- TemporaryDir decompression_dir;
- ApexFileRepository instance(decompression_dir.path);
-
- // Prepare decompressed apex
- std::string filename = "com.android.apex.compressed.v1_original.apex";
- fs::copy(GetTestFile(filename), decompression_dir.path);
- auto decompressed_path =
- StringPrintf("%s/%s", decompression_dir.path, filename.c_str());
- auto decompressed_apex = ApexFile::Open(decompressed_path);
-
- // Any file which is already located in |decompression_dir| should be
- // considered decompressed
- ASSERT_TRUE(instance.IsDecompressedApex(*decompressed_apex));
-
- // Hard links with same file name is not considered decompressed
- TemporaryDir active_dir;
- auto active_path = StringPrintf("%s/%s", active_dir.path, filename.c_str());
- std::error_code ec;
- fs::create_hard_link(decompressed_path, active_path, ec);
- ASSERT_FALSE(ec) << "Failed to create hardlink";
- auto active_apex = ApexFile::Open(active_path);
- ASSERT_FALSE(instance.IsDecompressedApex(*active_apex));
-}
-
-TEST(ApexFileRepositoryTest, AddAndGetDataApex) {
- // Prepare test data.
- TemporaryDir built_in_dir, data_dir, decompression_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
- PrepareCompressedApex("com.android.apex.compressed.v1.capex",
- built_in_dir.path, decompression_dir.path);
- // Add a data apex that has kDecompressedApexPackageSuffix
- fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
- StringPrintf("%s/com.android.apex.compressed@1%s", data_dir.path,
- kDecompressedApexPackageSuffix));
-
- ApexFileRepository instance(decompression_dir.path);
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- // ApexFileRepository should only deal with APEX in /data/apex/active.
- // Decompressed APEX should not be included
- auto data_apexs = instance.GetDataApexFiles();
- auto normal_apex =
- ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
- ASSERT_THAT(data_apexs,
- UnorderedElementsAre(ApexFileEq(ByRef(*normal_apex))));
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexIgnoreCompressedApex) {
- // Prepare test data.
- TemporaryDir data_dir, decompression_dir;
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), data_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto data_apexs = instance.GetDataApexFiles();
- ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexIgnoreIfNotPreInstalled) {
- // Prepare test data.
- TemporaryDir data_dir, decompression_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto data_apexs = instance.GetDataApexFiles();
- ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexPrioritizeHigherVersionApex) {
- // Prepare test data.
- TemporaryDir built_in_dir, data_dir, decompression_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
- fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto data_apexs = instance.GetDataApexFiles();
- auto normal_apex =
- ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
- ASSERT_THAT(data_apexs,
- UnorderedElementsAre(ApexFileEq(ByRef(*normal_apex))));
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexDoesNotScanDecompressedApex) {
- // Prepare test data.
- TemporaryDir built_in_dir, data_dir, decompression_dir;
- PrepareCompressedApex("com.android.apex.compressed.v1.capex",
- built_in_dir.path, decompression_dir.path);
-
- ApexFileRepository instance(decompression_dir.path);
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto data_apexs = instance.GetDataApexFiles();
- ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexIgnoreWrongPublicKey) {
- // Prepare test data.
- TemporaryDir built_in_dir, data_dir, decompression_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("apex.apexd_test_different_key.apex"), data_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto data_apexs = instance.GetDataApexFiles();
- ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, GetPreInstalledApexFiles) {
- // Prepare test data.
- TemporaryDir built_in_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
- built_in_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-
- auto pre_installed_apexs = instance.GetPreInstalledApexFiles();
- auto pre_apex_1 = ApexFile::Open(
- StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
- auto pre_apex_2 = ApexFile::Open(StringPrintf(
- "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));
- ASSERT_THAT(pre_installed_apexs,
- UnorderedElementsAre(ApexFileEq(ByRef(*pre_apex_1)),
- ApexFileEq(ByRef(*pre_apex_2))));
-}
-
-TEST(ApexFileRepositoryTest, AllApexFilesByName) {
- TemporaryDir built_in_dir, decompression_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), built_in_dir.path);
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
- built_in_dir.path);
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-
- TemporaryDir data_dir;
- fs::copy(GetTestFile("com.android.apex.cts.shim.v2.apex"), data_dir.path);
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto result = instance.AllApexFilesByName();
-
- // Verify the contents of result
- auto apexd_test_file = ApexFile::Open(
- StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
- auto shim_v1 = ApexFile::Open(
- StringPrintf("%s/com.android.apex.cts.shim.apex", built_in_dir.path));
- auto compressed_apex = ApexFile::Open(StringPrintf(
- "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));
- auto shim_v2 = ApexFile::Open(
- StringPrintf("%s/com.android.apex.cts.shim.v2.apex", data_dir.path));
-
- ASSERT_EQ(result.size(), 3u);
- ASSERT_THAT(result[apexd_test_file->GetManifest().name()],
- UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file))));
- ASSERT_THAT(result[shim_v1->GetManifest().name()],
- UnorderedElementsAre(ApexFileEq(ByRef(*shim_v1)),
- ApexFileEq(ByRef(*shim_v2))));
- ASSERT_THAT(result[compressed_apex->GetManifest().name()],
- UnorderedElementsAre(ApexFileEq(ByRef(*compressed_apex))));
-}
-
-TEST(ApexFileRepositoryTest, GetDataApex) {
- // Prepare test data.
- TemporaryDir built_in_dir, data_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
- fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
- auto apex =
- ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
- ASSERT_RESULT_OK(apex);
-
- auto ret = instance.GetDataApex("com.android.apex.test_package");
- ASSERT_THAT(ret, ApexFileEq(ByRef(*apex)));
-}
-
-TEST(ApexFileRepositoryTest, GetDataApexNoSuchApexAborts) {
- ASSERT_DEATH(
- {
- ApexFileRepository instance;
- instance.GetDataApex("whatever");
- },
- "");
-}
-
-TEST(ApexFileRepositoryTest, GetPreInstalledApex) {
- // Prepare test data.
- TemporaryDir built_in_dir;
- fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-
- ApexFileRepository instance;
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-
- auto apex = ApexFile::Open(
- StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
- ASSERT_RESULT_OK(apex);
-
- auto ret = instance.GetPreInstalledApex("com.android.apex.test_package");
- ASSERT_THAT(ret, ApexFileEq(ByRef(*apex)));
-}
-
-TEST(ApexFileRepositoryTest, GetPreInstalledApexNoSuchApexAborts) {
- ASSERT_DEATH(
- {
- ApexFileRepository instance;
- instance.GetPreInstalledApex("whatever");
- },
- "");
-}
-
-} // namespace apex
-} // namespace android
diff --git a/apexd/apex_file_test.cpp b/apexd/apex_file_test.cpp
index 3da74484..711d0246 100644
--- a/apexd/apex_file_test.cpp
+++ b/apexd/apex_file_test.cpp
@@ -19,47 +19,31 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/scopeguard.h>
-#include <android-base/strings.h>
-#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libavb/libavb.h>
#include <ziparchive/zip_archive.h>
#include "apex_file.h"
-#include "apexd_test_utils.h"
-#include "apexd_utils.h"
+#include "apex_preinstalled_data.h"
-using android::base::GetExecutableDirectory;
using android::base::Result;
-static const std::string kTestDataDir = GetExecutableDirectory() + "/";
+static std::string testDataDir = android::base::GetExecutableDirectory() + "/";
namespace android {
namespace apex {
namespace {
-struct ApexFileTestParam {
- const char* type;
- const char* prefix;
-};
-
-constexpr const ApexFileTestParam kParameters[] = {
- {"ext4", "apex.apexd_test"}, {"f2fs", "apex.apexd_test_f2fs"}};
-
-class ApexFileTest : public ::testing::TestWithParam<ApexFileTestParam> {};
-
-INSTANTIATE_TEST_SUITE_P(Apex, ApexFileTest, ::testing::ValuesIn(kParameters));
-
-TEST_P(ApexFileTest, GetOffsetOfSimplePackage) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_TRUE(apex_file.ok());
+TEST(ApexFileTest, GetOffsetOfSimplePackage) {
+ const std::string filePath = testDataDir + "apex.apexd_test.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_TRUE(apexFile.ok());
int32_t zip_image_offset;
size_t zip_image_size;
{
ZipArchiveHandle handle;
- int32_t rc = OpenArchive(file_path.c_str(), &handle);
+ int32_t rc = OpenArchive(filePath.c_str(), &handle);
ASSERT_EQ(0, rc);
auto close_guard =
android::base::make_scope_guard([&handle]() { CloseArchive(handle); });
@@ -74,33 +58,34 @@ TEST_P(ApexFileTest, GetOffsetOfSimplePackage) {
EXPECT_EQ(zip_image_size, entry.compressed_length);
}
- EXPECT_EQ(zip_image_offset, apex_file->GetImageOffset().value());
- EXPECT_EQ(zip_image_size, apex_file->GetImageSize().value());
+ EXPECT_EQ(zip_image_offset, apexFile->GetImageOffset());
+ EXPECT_EQ(zip_image_size, apexFile->GetImageSize());
}
TEST(ApexFileTest, GetOffsetMissingFile) {
- const std::string file_path = kTestDataDir + "missing.apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_FALSE(apex_file.ok());
- ASSERT_THAT(apex_file.error().message(),
- ::testing::HasSubstr("Failed to open package"));
+ const std::string filePath = testDataDir + "missing.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_FALSE(apexFile.ok());
+ EXPECT_NE(std::string::npos,
+ apexFile.error().message().find("Failed to open package"))
+ << apexFile.error();
}
-TEST_P(ApexFileTest, GetApexManifest) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
- EXPECT_EQ("com.android.apex.test_package", apex_file->GetManifest().name());
- EXPECT_EQ(1u, apex_file->GetManifest().version());
+TEST(ApexFileTest, GetApexManifest) {
+ const std::string filePath = testDataDir + "apex.apexd_test.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_RESULT_OK(apexFile);
+ EXPECT_EQ("com.android.apex.test_package", apexFile->GetManifest().name());
+ EXPECT_EQ(1u, apexFile->GetManifest().version());
}
-TEST_P(ApexFileTest, VerifyApexVerity) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
+TEST(ApexFileTest, VerifyApexVerity) {
+ ASSERT_RESULT_OK(collectPreinstalledData({"/system_ext/apex"}));
+ const std::string filePath = testDataDir + "apex.apexd_test.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_RESULT_OK(apexFile);
- auto verity_or =
- apex_file->VerifyApexVerity(apex_file->GetBundledPublicKey());
+ auto verity_or = apexFile->VerifyApexVerity();
ASSERT_RESULT_OK(verity_or);
const ApexVerityData& data = *verity_or;
@@ -108,229 +93,52 @@ TEST_P(ApexFileTest, VerifyApexVerity) {
EXPECT_EQ(std::string("368a22e64858647bc45498e92f749f85482ac468"
"50ca7ec8071f49dfa47a243c"),
data.salt);
-
- const std::string digest_path =
- kTestDataDir + GetParam().prefix + "_digest.txt";
- std::string root_digest;
- ASSERT_TRUE(android::base::ReadFileToString(digest_path, &root_digest))
- << "Failed to read " << digest_path;
- root_digest = android::base::Trim(root_digest);
-
- EXPECT_EQ(std::string(root_digest), data.root_digest);
+ EXPECT_EQ(
+ std::string(
+ "8e841019e41e8c40bca6dd6304cbf163ea257ba0a268304832c4105eba1c2747"),
+ data.root_digest);
}
-TEST_P(ApexFileTest, VerifyApexVerityWrongKey) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
+// TODO: May consider packaging a debug key in debug builds (again).
+TEST(ApexFileTest, DISABLED_VerifyApexVerityNoKeyDir) {
+ const std::string filePath = testDataDir + "apex.apexd_test.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_RESULT_OK(apexFile);
- auto verity_or = apex_file->VerifyApexVerity("wrong-key");
+ auto verity_or = apexFile->VerifyApexVerity();
ASSERT_FALSE(verity_or.ok());
}
-TEST_P(ApexFileTest, GetBundledPublicKey) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
-
- const std::string key_path =
- kTestDataDir + "apexd_testdata/com.android.apex.test_package.avbpubkey";
- std::string key_content;
- ASSERT_TRUE(android::base::ReadFileToString(key_path, &key_content))
- << "Failed to read " << key_path;
-
- EXPECT_EQ(key_content, apex_file->GetBundledPublicKey());
-}
-
-TEST(ApexFileTest, CorrutedApexB146895998) {
- const std::string apex_path = kTestDataDir + "corrupted_b146895998.apex";
- Result<ApexFile> apex = ApexFile::Open(apex_path);
- ASSERT_RESULT_OK(apex);
- ASSERT_FALSE(apex->VerifyApexVerity("ignored").ok());
-}
+TEST(ApexFileTest, VerifyApexVerityNoKeyInst) {
+ const std::string filePath = testDataDir + "apex.apexd_test_no_inst_key.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_RESULT_OK(apexFile);
-TEST_P(ApexFileTest, RetrieveFsType) {
- const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_TRUE(apex_file.ok());
-
- EXPECT_EQ(std::string(GetParam().type), apex_file->GetFsType().value());
-}
-
-TEST(ApexFileTest, OpenInvalidFilesystem) {
- const std::string file_path =
- kTestDataDir + "apex.apexd_test_corrupt_superblock_apex.apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_FALSE(apex_file.ok());
- ASSERT_THAT(apex_file.error().message(),
- ::testing::HasSubstr("Failed to retrieve filesystem type"));
-}
-
-TEST(ApexFileTest, OpenCompressedApexFile) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_TRUE(apex_file.ok());
-
- ASSERT_TRUE(apex_file->IsCompressed());
- ASSERT_FALSE(apex_file->GetImageOffset().has_value());
- ASSERT_FALSE(apex_file->GetImageSize().has_value());
- ASSERT_FALSE(apex_file->GetFsType().has_value());
-}
-
-TEST(ApexFileTest, OpenFailureForCompressedApexWithoutApex) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1_without_apex.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_FALSE(apex_file.ok());
- ASSERT_THAT(apex_file.error().message(),
- ::testing::HasSubstr("Could not find entry"));
-}
-
-TEST(ApexFileTest, GetCompressedApexManifest) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
- EXPECT_EQ("com.android.apex.compressed", apex_file->GetManifest().name());
- EXPECT_EQ(1u, apex_file->GetManifest().version());
+ auto verity_or = apexFile->VerifyApexVerity();
+ ASSERT_FALSE(verity_or.ok());
}
-TEST(ApexFileTest, GetBundledPublicKeyOfCompressedApex) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
+TEST(ApexFileTest, GetBundledPublicKey) {
+ const std::string filePath = testDataDir + "apex.apexd_test.apex";
+ Result<ApexFile> apexFile = ApexFile::Open(filePath);
+ ASSERT_RESULT_OK(apexFile);
- const std::string key_path =
- kTestDataDir + "apexd_testdata/com.android.apex.compressed.avbpubkey";
- std::string key_content;
- ASSERT_TRUE(android::base::ReadFileToString(key_path, &key_content))
- << "Failed to read " << key_path;
+ const std::string keyPath =
+ testDataDir + "apexd_testdata/com.android.apex.test_package.avbpubkey";
+ std::string keyContent;
+ ASSERT_TRUE(android::base::ReadFileToString(keyPath, &keyContent))
+ << "Failed to read " << keyPath;
- EXPECT_EQ(key_content, apex_file->GetBundledPublicKey());
+ EXPECT_EQ(keyContent, apexFile->GetBundledPublicKey());
}
-TEST(ApexFileTest, CannotVerifyApexVerityForCompressedApex) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- auto apex = ApexFile::Open(file_path);
+TEST(ApexFileTest, CorrutedApex_b146895998) {
+ const std::string apex_path = testDataDir + "corrupted_b146895998.apex";
+ Result<ApexFile> apex = ApexFile::Open(apex_path);
ASSERT_RESULT_OK(apex);
- auto result = apex->VerifyApexVerity(apex->GetBundledPublicKey());
- ASSERT_FALSE(result.ok());
- ASSERT_THAT(
- result.error().message(),
- ::testing::HasSubstr("Cannot verify ApexVerity of compressed APEX"));
+ ASSERT_FALSE(apex->VerifyApexVerity());
}
-TEST(ApexFileTest, DecompressCompressedApex) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
-
- // Create a temp dir for decompression
- TemporaryDir tmp_dir;
-
- const std::string package_name = apex_file->GetManifest().name();
- const std::string decompression_file_path =
- tmp_dir.path + package_name + ".capex";
-
- auto result = apex_file->Decompress(decompression_file_path);
- ASSERT_RESULT_OK(result);
-
- // Assert output path is not empty
- auto exists = PathExists(decompression_file_path);
- ASSERT_RESULT_OK(exists);
- ASSERT_TRUE(*exists) << decompression_file_path << " does not exist";
-
- // Assert that decompressed apex is same as original apex
- const std::string original_apex_file_path =
- kTestDataDir + "com.android.apex.compressed.v1_original.apex";
- auto comparison_result =
- CompareFiles(original_apex_file_path, decompression_file_path);
- ASSERT_RESULT_OK(comparison_result);
- ASSERT_TRUE(*comparison_result);
-}
-
-TEST(ApexFileTest, DecompressFailForNormalApex) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1_original.apex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
- ASSERT_RESULT_OK(apex_file);
-
- TemporaryFile decompression_file;
-
- auto result = apex_file->Decompress(decompression_file.path);
- ASSERT_FALSE(result.ok());
- ASSERT_THAT(result.error().message(),
- ::testing::HasSubstr("Cannot decompress an uncompressed APEX"));
-}
-
-TEST(ApexFileTest, DecompressFailIfDecompressionPathExists) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
-
- // Attempt to decompress in a path that already exists
- TemporaryFile decompression_file;
- auto exists = PathExists(decompression_file.path);
- ASSERT_RESULT_OK(exists);
- ASSERT_TRUE(*exists) << decompression_file.path << " does not exist";
-
- auto result = apex_file->Decompress(decompression_file.path);
- ASSERT_FALSE(result.ok());
- ASSERT_THAT(result.error().message(),
- ::testing::HasSubstr("Failed to open decompression destination"));
-}
-
-TEST(ApexFileTest, GetPathReturnsRealpath) {
- const std::string real_path = kTestDataDir + "apex.apexd_test.apex";
- const std::string symlink_path =
- kTestDataDir + "apex.apexd_test.symlink.apex";
-
- // In case the link already exists
- int ret = unlink(symlink_path.c_str());
- ASSERT_TRUE(ret == 0 || errno == ENOENT)
- << "failed to unlink " << symlink_path;
-
- ret = symlink(real_path.c_str(), symlink_path.c_str());
- ASSERT_EQ(0, ret) << "failed to create symlink at " << symlink_path;
-
- // Open with the symlink. Realpath is expected.
- Result<ApexFile> apex_file = ApexFile::Open(symlink_path);
- ASSERT_RESULT_OK(apex_file);
- ASSERT_EQ(real_path, apex_file->GetPath());
-}
-
-TEST(ApexFileTest, CompressedSharedLibsApexIsRejected) {
- const std::string file_path =
- kTestDataDir + "com.android.apex.compressed_sharedlibs.capex";
- Result<ApexFile> apex_file = ApexFile::Open(file_path);
-
- ASSERT_FALSE(apex_file.ok());
- ASSERT_THAT(apex_file.error().message(),
- ::testing::HasSubstr("Apex providing sharedlibs shouldn't "
- "be compressed"));
-}
-
-// Check if CAPEX contains originalApexDigest in its manifest
-TEST(ApexFileTest, OriginalApexDigest) {
- const std::string capex_path =
- kTestDataDir + "com.android.apex.compressed.v1.capex";
- auto capex = ApexFile::Open(capex_path);
- ASSERT_TRUE(capex.ok());
- const std::string decompressed_apex_path =
- kTestDataDir + "com.android.apex.compressed.v1_original.apex";
- auto decompressed_apex = ApexFile::Open(decompressed_apex_path);
- ASSERT_TRUE(decompressed_apex.ok());
- // Validate root digest
- auto digest = decompressed_apex->VerifyApexVerity(
- decompressed_apex->GetBundledPublicKey());
- ASSERT_TRUE(digest.ok());
- ASSERT_EQ(digest->root_digest,
- capex->GetManifest().capexmetadata().originalapexdigest());
-}
} // namespace
} // namespace apex
} // namespace android
diff --git a/apexd/apex_manifest.cpp b/apexd/apex_manifest.cpp
index bfba216e..1994633c 100644
--- a/apexd/apex_manifest.cpp
+++ b/apexd/apex_manifest.cpp
@@ -22,7 +22,6 @@
using android::base::Error;
using android::base::Result;
-using ::apex::proto::ApexManifest;
namespace android {
namespace apex {
@@ -47,8 +46,8 @@ Result<ApexManifest> ParseManifest(const std::string& content) {
return apex_manifest;
}
-std::string GetPackageId(const ApexManifest& apex_manifest) {
- return apex_manifest.name() + "@" + std::to_string(apex_manifest.version());
+std::string GetPackageId(const ApexManifest& apexManifest) {
+ return apexManifest.name() + "@" + std::to_string(apexManifest.version());
}
Result<ApexManifest> ReadManifest(const std::string& path) {
diff --git a/apexd/apex_manifest.h b/apexd/apex_manifest.h
index 5bdd43bd..f2996483 100644
--- a/apexd/apex_manifest.h
+++ b/apexd/apex_manifest.h
@@ -23,16 +23,16 @@
#include <string>
+using ::apex::proto::ApexManifest;
+
namespace android {
namespace apex {
// Parses and validates APEX manifest.
-android::base::Result<::apex::proto::ApexManifest> ParseManifest(
- const std::string& content);
+android::base::Result<ApexManifest> ParseManifest(const std::string& content);
// Returns package id of an ApexManifest
-std::string GetPackageId(const ::apex::proto::ApexManifest& apex_manifest);
+std::string GetPackageId(const ApexManifest& apex_manifest);
// Reads and parses APEX manifest from the file on disk.
-android::base::Result<::apex::proto::ApexManifest> ReadManifest(
- const std::string& path);
+android::base::Result<ApexManifest> ReadManifest(const std::string& path);
} // namespace apex
} // namespace android
diff --git a/apexd/apex_manifest_test.cpp b/apexd/apex_manifest_test.cpp
index f5bc93ca..5a4e3da5 100644
--- a/apexd/apex_manifest_test.cpp
+++ b/apexd/apex_manifest_test.cpp
@@ -22,8 +22,6 @@
#include "apex_manifest.h"
-using ::apex::proto::ApexManifest;
-
namespace android {
namespace apex {
diff --git a/apexd/apex_preinstalled_data.cpp b/apexd/apex_preinstalled_data.cpp
new file mode 100644
index 00000000..d62c28c5
--- /dev/null
+++ b/apexd/apex_preinstalled_data.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "apexd"
+
+#include "apex_preinstalled_data.h"
+
+#include <unordered_map>
+
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <android-base/strings.h>
+
+#include "apex_constants.h"
+#include "apex_file.h"
+#include "apexd_utils.h"
+#include "string_log.h"
+
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+namespace apex {
+
+namespace {
+
+struct ApexPreinstalledData {
+ std::string name;
+ std::string key;
+ std::string path;
+};
+
+std::unordered_map<std::string, ApexPreinstalledData> gScannedPreinstalledData;
+
+Result<std::vector<ApexPreinstalledData>> collectPreinstalleDataFromDir(
+ const std::string& dir) {
+ LOG(INFO) << "Scanning " << dir << " for preinstalled data";
+ std::vector<ApexPreinstalledData> ret;
+ if (access(dir.c_str(), F_OK) != 0 && errno == ENOENT) {
+ LOG(INFO) << "... does not exist. Skipping";
+ return ret;
+ }
+ const bool scanBuiltinApexes = isPathForBuiltinApexes(dir);
+ if (!scanBuiltinApexes) {
+ return Error() << "Can't scan preinstalled APEX data from " << dir;
+ }
+ Result<std::vector<std::string>> apex_files = FindApexFilesByName(dir);
+ if (!apex_files.ok()) {
+ return apex_files.error();
+ }
+
+ for (const auto& file : *apex_files) {
+ Result<ApexFile> apex_file = ApexFile::Open(file);
+ if (!apex_file.ok()) {
+ return Error() << "Failed to open " << file << " : " << apex_file.error();
+ }
+ ApexPreinstalledData apexPreInstalledData;
+ apexPreInstalledData.name = apex_file->GetManifest().name();
+ apexPreInstalledData.key = apex_file->GetBundledPublicKey();
+ apexPreInstalledData.path = apex_file->GetPath();
+ ret.push_back(apexPreInstalledData);
+ }
+ return ret;
+}
+
+Result<void> updatePreinstalledData(
+ const std::vector<ApexPreinstalledData>& apexes) {
+ for (const ApexPreinstalledData& apex : apexes) {
+ if (gScannedPreinstalledData.find(apex.name) ==
+ gScannedPreinstalledData.end()) {
+ gScannedPreinstalledData.insert({apex.name, apex});
+ } else {
+ const std::string& existing_key =
+ gScannedPreinstalledData.at(apex.name).key;
+ if (existing_key != apex.key) {
+ return Error() << "Key for package " << apex.name
+ << " does not match with previously scanned key";
+ }
+ }
+ }
+ return {};
+}
+
+} // namespace
+
+Result<void> collectPreinstalledData(const std::vector<std::string>& dirs) {
+ for (const auto& dir : dirs) {
+ Result<std::vector<ApexPreinstalledData>> preinstalledData =
+ collectPreinstalleDataFromDir(dir);
+ if (!preinstalledData.ok()) {
+ return Error() << "Failed to collect keys from " << dir << " : "
+ << preinstalledData.error();
+ }
+ Result<void> st = updatePreinstalledData(*preinstalledData);
+ if (!st.ok()) {
+ return st;
+ }
+ }
+ return {};
+}
+
+Result<const std::string> getApexKey(const std::string& name) {
+ if (gScannedPreinstalledData.find(name) == gScannedPreinstalledData.end()) {
+ return Error() << "No preinstalled data found for package " << name;
+ }
+ return gScannedPreinstalledData[name].key;
+}
+
+Result<const std::string> getApexPreinstalledPath(const std::string& name) {
+ if (gScannedPreinstalledData.find(name) == gScannedPreinstalledData.end()) {
+ return Error() << "No preinstalled data found for package " << name;
+ }
+ return gScannedPreinstalledData[name].path;
+}
+
+bool HasPreInstalledVersion(const std::string& name) {
+ return gScannedPreinstalledData.find(name) != gScannedPreinstalledData.end();
+}
+
+} // namespace apex
+} // namespace android
diff --git a/apexd/apex_preinstalled_data.h b/apexd/apex_preinstalled_data.h
new file mode 100644
index 00000000..1b80aad5
--- /dev/null
+++ b/apexd/apex_preinstalled_data.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <android-base/result.h>
+
+namespace android {
+namespace apex {
+
+android::base::Result<void> collectPreinstalledData(
+ const std::vector<std::string>& apex_dirs);
+android::base::Result<const std::string> getApexKey(const std::string& name);
+android::base::Result<const std::string> getApexPreinstalledPath(
+ const std::string& name);
+bool HasPreInstalledVersion(const std::string& name);
+} // namespace apex
+} // namespace android
diff --git a/apexd/apex_shim.cpp b/apexd/apex_shim.cpp
index 0031c3f7..d1ff90d9 100644
--- a/apexd/apex_shim.cpp
+++ b/apexd/apex_shim.cpp
@@ -33,7 +33,6 @@
using android::base::ErrnoError;
using android::base::Error;
using android::base::Result;
-using ::apex::proto::ApexManifest;
namespace android {
namespace apex {
@@ -127,6 +126,7 @@ Result<void> ValidateShimApex(const std::string& mount_point,
// Unfortunately fs::recursive_directory_iterator::operator++ can throw an
// exception, which means that it's impossible to use range-based for loop
// here.
+ // TODO: wrap into a non-throwing iterator to support range-based for loop.
while (iter != fs::end(iter)) {
auto path = iter->path();
// Resolve the mount point to ensure any trailing slash is removed.
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index e0562f02..80e075a1 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -15,26 +15,25 @@
*/
#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_preinstalled_data.h"
#include "apex_shim.h"
#include "apexd_checkpoint.h"
-#include "apexd_lifecycle.h"
#include "apexd_loop.h"
#include "apexd_prepostinstall.h"
+#include "apexd_prop.h"
#include "apexd_rollback_utils.h"
#include "apexd_session.h"
#include "apexd_utils.h"
#include "apexd_verity.h"
-#include "com_android_apex.h"
+#include "string_log.h"
#include <ApexProperties.sysprop.h>
-#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
@@ -44,7 +43,6 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <google/protobuf/util/message_differencer.h>
#include <libavb/libavb.h>
#include <libdm/dm.h>
#include <libdm/dm_table.h>
@@ -53,17 +51,15 @@
#include <dirent.h>
#include <fcntl.h>
-#include <linux/f2fs.h>
#include <linux/loop.h>
+#include <log/log.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
-#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
-#include <algorithm>
#include <algorithm>
#include <array>
@@ -71,40 +67,31 @@
#include <cstdlib>
#include <filesystem>
#include <fstream>
-#include <future>
#include <iomanip>
#include <iterator>
#include <memory>
-#include <mutex>
#include <optional>
-#include <queue>
-#include <sstream>
#include <string>
-#include <string_view>
#include <thread>
#include <unordered_map>
#include <unordered_set>
-using android::base::boot_clock;
-using android::base::ConsumePrefix;
using android::base::ErrnoError;
using android::base::Error;
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;
using android::dm::DmDeviceState;
using android::dm::DmTable;
using android::dm::DmTargetVerity;
-using ::apex::proto::ApexManifest;
+
using apex::proto::SessionState;
-using google::protobuf::util::MessageDifferencer;
namespace android {
namespace apex {
@@ -113,6 +100,12 @@ using MountedApexData = MountedApexDatabase::MountedApexData;
namespace {
+// These should be in-sync with system/sepolicy/public/property_contexts
+static constexpr const char* kApexStatusSysprop = "apexd.status";
+static constexpr const char* kApexStatusStarting = "starting";
+static constexpr const char* kApexStatusActivated = "activated";
+static constexpr const char* kApexStatusReady = "ready";
+
static constexpr const char* kBuildFingerprintSysprop = "ro.build.fingerprint";
// This should be in UAPI, but it's not :-(
@@ -121,20 +114,20 @@ static constexpr const char* kDmVerityRestartOnCorruption =
MountedApexDatabase gMountedApexes;
-std::optional<ApexdConfig> gConfig;
-
CheckpointInterface* gVoldService;
bool gSupportsFsCheckpoints = false;
bool gInFsCheckpointMode = false;
static constexpr size_t kLoopDeviceSetupAttempts = 3u;
-// Please DO NOT add new modules to this list without contacting mainline-modularization@ first.
+bool gBootstrap = false;
static const std::vector<std::string> kBootstrapApexes = ([]() {
std::vector<std::string> ret = {
+ "com.android.art",
"com.android.i18n",
"com.android.runtime",
"com.android.tzdata",
+ "com.android.os.statsd",
};
auto vendor_vndk_ver = GetProperty("ro.vndk.version", "");
@@ -150,39 +143,14 @@ static const std::vector<std::string> kBootstrapApexes = ([]() {
static constexpr const int kNumRetriesWhenCheckpointingEnabled = 1;
-bool IsBootstrapApex(const ApexFile& apex) {
+bool isBootstrapApex(const ApexFile& apex) {
return std::find(kBootstrapApexes.begin(), kBootstrapApexes.end(),
apex.GetManifest().name()) != kBootstrapApexes.end();
}
-void ReleaseF2fsCompressedBlocks(const std::string& file_path) {
- unique_fd fd(
- TEMP_FAILURE_RETRY(open(file_path.c_str(), O_RDONLY | O_CLOEXEC, 0)));
- if (fd.get() == -1) {
- PLOG(ERROR) << "Failed to open " << file_path;
- return;
- }
- unsigned int flags;
- if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
- PLOG(ERROR) << "Failed to call FS_IOC_GETFLAGS on " << file_path;
- return;
- }
- if ((flags & FS_COMPR_FL) == 0) {
- // Doesn't support f2fs-compression.
- return;
- }
- uint64_t blk_cnt;
- if (ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blk_cnt) == -1) {
- PLOG(ERROR) << "Failed to call F2FS_IOC_RELEASE_COMPRESS_BLOCKS on "
- << file_path;
- }
- LOG(INFO) << "Released " << blk_cnt << " compressed blocks from "
- << file_path;
-}
-
// Pre-allocate loop devices so that we don't have to wait for them
// later when actually activating APEXes.
-Result<void> PreAllocateLoopDevices() {
+Result<void> preAllocateLoopDevices() {
auto scan = FindApexes(kApexPackageBuiltinDirs);
if (!scan.ok()) {
return scan.error();
@@ -190,28 +158,28 @@ Result<void> PreAllocateLoopDevices() {
auto size = 0;
for (const auto& path : *scan) {
- auto apex_file = ApexFile::Open(path);
- if (!apex_file.ok()) {
+ auto apexFile = ApexFile::Open(path);
+ if (!apexFile.ok()) {
continue;
}
size++;
// bootstrap Apexes may be activated on separate namespaces.
- if (IsBootstrapApex(*apex_file)) {
+ if (isBootstrapApex(*apexFile)) {
size++;
}
}
- // note: do not call PreAllocateLoopDevices() if size == 0.
+ // note: do not call preAllocateLoopDevices() if size == 0.
// For devices (e.g. ARC) which doesn't support loop-control
- // PreAllocateLoopDevices() can cause problem when it tries
+ // preAllocateLoopDevices() can cause problem when it tries
// to access /dev/loop-control.
if (size == 0) {
return {};
}
- return loop::PreAllocateLoopDevices(size);
+ return loop::preAllocateLoopDevices(size);
}
-std::unique_ptr<DmTable> CreateVerityTable(const ApexVerityData& verity_data,
+std::unique_ptr<DmTable> createVerityTable(const ApexVerityData& verity_data,
const std::string& block_device,
const std::string& hash_device,
bool restart_on_corruption) {
@@ -242,18 +210,9 @@ std::unique_ptr<DmTable> CreateVerityTable(const ApexVerityData& verity_data,
// Deletes a dm-verity device with a given name and path
// Synchronizes on the device actually being deleted from userspace.
-Result<void> DeleteVerityDevice(const std::string& name, bool deferred) {
+Result<void> DeleteVerityDevice(const std::string& name) {
DeviceMapper& dm = DeviceMapper::Instance();
- if (deferred) {
- if (!dm.DeleteDeviceDeferred(name)) {
- return ErrnoError() << "Failed to issue deferred delete of verity device "
- << name;
- }
- return {};
- }
- auto timeout = std::chrono::milliseconds(
- android::sysprop::ApexProperties::dm_delete_timeout().value_or(750));
- if (!dm.DeleteDevice(name, timeout)) {
+ if (!dm.DeleteDevice(name, 750ms)) {
return Error() << "Failed to delete dm-device " << name;
}
return {};
@@ -286,7 +245,7 @@ class DmVerityDevice {
~DmVerityDevice() {
if (!cleared_) {
- Result<void> ret = DeleteVerityDevice(name_, /* deferred= */ false);
+ Result<void> ret = DeleteVerityDevice(name_);
if (!ret.ok()) {
LOG(ERROR) << ret.error();
}
@@ -304,46 +263,32 @@ class DmVerityDevice {
bool cleared_;
};
-Result<DmVerityDevice> CreateVerityDevice(const std::string& name,
+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.
+ // TODO: since apexd tears down devices during unmount, can this happen?
LOG(WARNING) << "Deleting existing dm device " << name;
- auto result = DeleteVerityDevice(name, /* deferred= */ false);
+ const Result<void>& result = DeleteVerityDevice(name);
if (!result.ok()) {
- return result.error();
+ // TODO: should we fail instead?
+ LOG(ERROR) << "Failed to delete device " << name << " : "
+ << 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)) {
+ if (!dm.CreateDevice(name, table, &dev_path, 500ms)) {
return Errorf("Couldn't create verity device.");
}
return DmVerityDevice(name, dev_path);
}
-/**
- * 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.
- * Since a new version of the same package is being installed on this boot, the
- * old one needs to deleted so that we don't end up activating same package
- * twice.
- *
- * @param affected_packages package names of the news apex that are being
- * installed in this boot
- * @param files_to_keep path to the new apex packages in
- * kActiveApexPackagesDataDir
- */
Result<void> RemovePreviouslyActiveApexFiles(
const std::unordered_set<std::string>& affected_packages,
const std::unordered_set<std::string>& files_to_keep) {
- auto all_active_apex_files =
- FindFilesBySuffix(gConfig->active_apex_data_dir, {kApexPackageSuffix});
+ auto all_active_apex_files = FindApexFilesByName(kActiveApexPackagesDataDir);
if (!all_active_apex_files.ok()) {
return all_active_apex_files.error();
@@ -377,14 +322,13 @@ Result<void> RemovePreviouslyActiveApexFiles(
}
// Reads the entire device to verify the image is authenticatic
-Result<void> ReadVerityDevice(const std::string& verity_device,
+Result<void> readVerityDevice(const std::string& verity_device,
uint64_t device_size) {
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(verity_device.c_str(), O_RDONLY | O_CLOEXEC)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(verity_device.c_str(), O_RDONLY)));
if (fd.get() == -1) {
return ErrnoError() << "Can't open " << verity_device;
}
@@ -403,16 +347,9 @@ Result<void> ReadVerityDevice(const std::string& verity_device,
Result<void> VerifyMountedImage(const ApexFile& apex,
const std::string& mount_point) {
- // Verify that apex_manifest.pb inside mounted image matches the one in the
- // outer .apex container.
- Result<ApexManifest> verified_manifest =
- ReadManifest(mount_point + "/" + kManifestFilenamePb);
- if (!verified_manifest.ok()) {
- return verified_manifest.error();
- }
- if (!MessageDifferencer::Equals(*verified_manifest, apex.GetManifest())) {
- return Errorf(
- "Manifest inside filesystem does not match manifest outside it");
+ auto result = apex.VerifyManifestMatches(mount_point);
+ if (!result.ok()) {
+ return result;
}
if (shim::IsShimApex(apex)) {
return shim::ValidateShimApex(mount_point, apex);
@@ -421,18 +358,11 @@ Result<void> VerifyMountedImage(const ApexFile& apex,
}
Result<MountedApexData> MountPackageImpl(const ApexFile& apex,
- const std::string& mount_point,
+ const std::string& mountPoint,
const std::string& device_name,
const std::string& hashtree_file,
- bool verify_image,
- bool temp_mount = false) {
- if (apex.IsCompressed()) {
- return Error() << "Cannot directly mount compressed APEX "
- << apex.GetPath();
- }
-
- LOG(VERBOSE) << "Creating mount point: " << mount_point;
- auto time_started = boot_clock::now();
+ bool verifyImage) {
+ LOG(VERBOSE) << "Creating mount point: " << mountPoint;
// Note: the mount point could exist in case when the APEX was activated
// during the bootstrap phase (e.g., the runtime or tzdata APEX).
// Although we have separate mount namespaces to separate the early activated
@@ -441,34 +371,31 @@ Result<MountedApexData> MountPackageImpl(const ApexFile& apex,
// mounted at / which is (and has to be) a shared mount. Therefore, if apexd
// finds an empty directory under /apex, it's not a problem and apexd can use
// it.
- auto exists = PathExists(mount_point);
+ auto exists = PathExists(mountPoint);
if (!exists.ok()) {
return exists.error();
}
- if (!*exists && mkdir(mount_point.c_str(), kMkdirMode) != 0) {
- return ErrnoError() << "Could not create mount point " << mount_point;
+ if (!*exists && mkdir(mountPoint.c_str(), kMkdirMode) != 0) {
+ return ErrnoError() << "Could not create mount point " << mountPoint;
}
- auto deleter = [&mount_point]() {
- if (rmdir(mount_point.c_str()) != 0) {
- PLOG(WARNING) << "Could not rmdir " << mount_point;
+ auto deleter = [&mountPoint]() {
+ if (rmdir(mountPoint.c_str()) != 0) {
+ PLOG(WARNING) << "Could not rmdir " << mountPoint;
}
};
auto scope_guard = android::base::make_scope_guard(deleter);
- if (!IsEmptyDirectory(mount_point)) {
- return ErrnoError() << mount_point << " is not empty";
+ if (!IsEmptyDirectory(mountPoint)) {
+ return ErrnoError() << mountPoint << " is not empty";
}
const std::string& full_path = apex.GetPath();
- if (!apex.GetImageOffset() || !apex.GetImageSize()) {
- return Error() << "Cannot create mount point without image offset and size";
- }
- loop::LoopbackDeviceUniqueFd loopback_device;
+ loop::LoopbackDeviceUniqueFd loopbackDevice;
for (size_t attempts = 1;; ++attempts) {
- Result<loop::LoopbackDeviceUniqueFd> ret = loop::CreateLoopDevice(
- full_path, apex.GetImageOffset().value(), apex.GetImageSize().value());
+ Result<loop::LoopbackDeviceUniqueFd> ret = loop::createLoopDevice(
+ full_path, apex.GetImageOffset(), apex.GetImageSize());
if (ret.ok()) {
- loopback_device = std::move(*ret);
+ loopbackDevice = std::move(*ret);
break;
}
if (attempts >= kLoopDeviceSetupAttempts) {
@@ -476,43 +403,33 @@ Result<MountedApexData> MountPackageImpl(const ApexFile& apex,
<< ret.error();
}
}
- LOG(VERBOSE) << "Loopback device created: " << loopback_device.name;
+ LOG(VERBOSE) << "Loopback device created: " << loopbackDevice.name;
- auto& instance = ApexFileRepository::GetInstance();
-
- auto public_key = instance.GetPublicKey(apex.GetManifest().name());
- if (!public_key.ok()) {
- return public_key.error();
- }
-
- auto verity_data = apex.VerifyApexVerity(*public_key);
- if (!verity_data.ok()) {
+ auto verityData = apex.VerifyApexVerity();
+ if (!verityData.ok()) {
return Error() << "Failed to verify Apex Verity data for " << full_path
- << ": " << verity_data.error();
+ << ": " << verityData.error();
}
- std::string block_device = loopback_device.name;
- MountedApexData apex_data(loopback_device.name, apex.GetPath(), mount_point,
+ std::string blockDevice = loopbackDevice.name;
+ MountedApexData apex_data(loopbackDevice.name, apex.GetPath(), mountPoint,
/* device_name = */ "",
- /* hashtree_loop_name = */ "",
- /* is_temp_mount */ temp_mount);
+ /* hashtree_loop_name = */ "");
// for APEXes in immutable partitions, we don't need to mount them on
// 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) || instance.IsDecompressedApex(apex);
-
- DmVerityDevice verity_dev;
+ const bool mountOnVerity = !isPathForBuiltinApexes(full_path);
+ DmVerityDevice verityDev;
loop::LoopbackDeviceUniqueFd loop_for_hash;
- if (mount_on_verity) {
- std::string hash_device = loopback_device.name;
- if (verity_data->desc->tree_size == 0) {
- if (auto st = PrepareHashTree(apex, *verity_data, hashtree_file);
+ if (mountOnVerity) {
+ std::string hash_device = loopbackDevice.name;
+ if (verityData->desc->tree_size == 0) {
+ if (auto st = PrepareHashTree(apex, *verityData, hashtree_file);
!st.ok()) {
return st.error();
}
- auto create_loop_status = loop::CreateLoopDevice(hashtree_file, 0, 0);
+ auto create_loop_status = loop::createLoopDevice(hashtree_file, 0, 0);
if (!create_loop_status.ok()) {
return create_loop_status.error();
}
@@ -520,59 +437,54 @@ Result<MountedApexData> MountPackageImpl(const ApexFile& apex,
hash_device = loop_for_hash.name;
apex_data.hashtree_loop_name = hash_device;
}
- auto verity_table =
- CreateVerityTable(*verity_data, loopback_device.name, hash_device,
- /* restart_on_corruption = */ !verify_image);
- Result<DmVerityDevice> verity_dev_res =
- CreateVerityDevice(device_name, *verity_table);
- if (!verity_dev_res.ok()) {
+ auto verityTable =
+ createVerityTable(*verityData, loopbackDevice.name, hash_device,
+ /* restart_on_corruption = */ !verifyImage);
+ Result<DmVerityDevice> verityDevRes =
+ createVerityDevice(device_name, *verityTable);
+ if (!verityDevRes.ok()) {
return Error() << "Failed to create Apex Verity device " << full_path
- << ": " << verity_dev_res.error();
+ << ": " << verityDevRes.error();
}
- verity_dev = std::move(*verity_dev_res);
+ verityDev = std::move(*verityDevRes);
apex_data.device_name = device_name;
- block_device = verity_dev.GetDevPath();
+ blockDevice = verityDev.GetDevPath();
- Result<void> read_ahead_status =
- loop::ConfigureReadAhead(verity_dev.GetDevPath());
- if (!read_ahead_status.ok()) {
- return read_ahead_status.error();
+ Result<void> readAheadStatus =
+ loop::configureReadAhead(verityDev.GetDevPath());
+ if (!readAheadStatus.ok()) {
+ return readAheadStatus.error();
}
}
- // TODO(b/158467418): consider moving this inside RunVerifyFnInsideTempMount.
- if (mount_on_verity && verify_image) {
- Result<void> verity_status =
- ReadVerityDevice(block_device, (*verity_data).desc->image_size);
- if (!verity_status.ok()) {
- return verity_status.error();
+ // TODO: consider moving this inside RunVerifyFnInsideTempMount.
+ if (mountOnVerity && verifyImage) {
+ Result<void> verityStatus =
+ readVerityDevice(blockDevice, (*verityData).desc->image_size);
+ if (!verityStatus.ok()) {
+ return verityStatus.error();
}
}
- uint32_t mount_flags = MS_NOATIME | MS_NODEV | MS_DIRSYNC | MS_RDONLY;
+ uint32_t mountFlags = MS_NOATIME | MS_NODEV | MS_DIRSYNC | MS_RDONLY;
if (apex.GetManifest().nocode()) {
- mount_flags |= MS_NOEXEC;
+ mountFlags |= MS_NOEXEC;
}
- if (!apex.GetFsType()) {
- return Error() << "Cannot mount package without FsType";
- }
- if (mount(block_device.c_str(), mount_point.c_str(),
- apex.GetFsType().value().c_str(), mount_flags, nullptr) == 0) {
- auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
- boot_clock::now() - time_started).count();
+ if (mount(blockDevice.c_str(), mountPoint.c_str(), "ext4", mountFlags,
+ nullptr) == 0) {
LOG(INFO) << "Successfully mounted package " << full_path << " on "
- << mount_point << " duration=" << time_elapsed;
- auto status = VerifyMountedImage(apex, mount_point);
+ << mountPoint;
+ auto status = VerifyMountedImage(apex, mountPoint);
if (!status.ok()) {
- if (umount2(mount_point.c_str(), UMOUNT_NOFOLLOW) != 0) {
- PLOG(ERROR) << "Failed to umount " << mount_point;
+ if (umount2(mountPoint.c_str(), UMOUNT_NOFOLLOW) != 0) {
+ PLOG(ERROR) << "Failed to umount " << mountPoint;
}
return Error() << "Failed to verify " << full_path << ": "
<< status.error();
}
// Time to accept the temporaries as good.
- verity_dev.Release();
- loopback_device.CloseGood();
+ verityDev.Release();
+ loopbackDevice.CloseGood();
loop_for_hash.CloseGood();
scope_guard.Disable(); // Accept the mount.
@@ -583,9 +495,8 @@ Result<MountedApexData> MountPackageImpl(const ApexFile& apex,
}
std::string GetHashTreeFileName(const ApexFile& apex, bool is_new) {
- const std::string& id = GetPackageId(apex.GetManifest());
std::string ret =
- StringPrintf("%s/%s", gConfig->apex_hash_tree_dir, id.c_str());
+ std::string(kApexHashTreeDir) + "/" + GetPackageId(apex.GetManifest());
return is_new ? ret + ".new" : ret;
}
@@ -601,40 +512,28 @@ Result<MountedApexData> VerifyAndTempMountPackage(
return ErrnoError() << "Failed to unlink " << hashtree_file;
}
}
- auto ret =
- MountPackageImpl(apex, mount_point, temp_device_name, hashtree_file,
- /* 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) {
- PLOG(ERROR) << "Failed to unlink " << hashtree_file;
- }
- } else {
- gMountedApexes.AddMountedApex(apex.GetManifest().name(), false, *ret);
- }
- return ret;
+ return MountPackageImpl(apex, mount_point, temp_device_name,
+ GetHashTreeFileName(apex, /* is_new = */ true),
+ /* verifyImage = */ true);
}
-} // namespace
-
-Result<void> Unmount(const MountedApexData& data, bool deferred) {
+Result<void> Unmount(const MountedApexData& data) {
LOG(DEBUG) << "Unmounting " << data.full_path << " from mount point "
- << data.mount_point << " deferred = " << deferred;
+ << data.mount_point;
// Lazily try to umount whatever is mounted.
if (umount2(data.mount_point.c_str(), UMOUNT_NOFOLLOW) != 0 &&
errno != EINVAL && errno != ENOENT) {
return ErrnoError() << "Failed to unmount directory " << data.mount_point;
}
-
- if (!deferred) {
- if (rmdir(data.mount_point.c_str()) != 0) {
- PLOG(ERROR) << "Failed to rmdir " << data.mount_point;
- }
+ // Attempt to delete the folder. If the folder is retained, other
+ // data may be incorrect.
+ if (rmdir(data.mount_point.c_str()) != 0) {
+ PLOG(ERROR) << "Failed to rmdir directory " << data.mount_point;
}
// Try to free up the device-mapper device.
if (!data.device_name.empty()) {
- const auto& result = DeleteVerityDevice(data.device_name, deferred);
+ const auto& result = DeleteVerityDevice(data.device_name);
if (!result.ok()) {
return result;
}
@@ -644,28 +543,19 @@ Result<void> Unmount(const MountedApexData& data, bool deferred) {
auto log_fn = [](const std::string& path, const std::string& /*id*/) {
LOG(VERBOSE) << "Freeing loop device " << path << " for unmount.";
};
-
- // Since we now use LO_FLAGS_AUTOCLEAR when configuring loop devices, in
- // theory we don't need to manually call DestroyLoopDevice here even if
- // |deferred| is false. However we prefer to call it to ensure the invariant
- // of SubmitStagedSession (after it's done, loop devices created for temp
- // mount are freed).
- if (!data.loop_name.empty() && !deferred) {
+ if (!data.loop_name.empty()) {
loop::DestroyLoopDevice(data.loop_name, log_fn);
}
- if (!data.hashtree_loop_name.empty() && !deferred) {
+ if (!data.hashtree_loop_name.empty()) {
loop::DestroyLoopDevice(data.hashtree_loop_name, log_fn);
}
return {};
}
-namespace {
-
template <typename VerifyFn>
Result<void> RunVerifyFnInsideTempMount(const ApexFile& apex,
- const VerifyFn& verify_fn,
- bool unmount_during_cleanup) {
+ const VerifyFn& verify_fn) {
// Temp mount image of this apex to validate it was properly signed;
// this will also read the entire block device through dm-verity, so
// we can be sure there is no corruption.
@@ -681,33 +571,19 @@ Result<void> RunVerifyFnInsideTempMount(const ApexFile& apex,
}
auto cleaner = [&]() {
LOG(DEBUG) << "Unmounting " << temp_mount_point;
- Result<void> result = Unmount(*mount_status, /* deferred= */ false);
+ Result<void> result = Unmount(*mount_status);
if (!result.ok()) {
LOG(WARNING) << "Failed to unmount " << temp_mount_point << " : "
<< result.error();
}
- gMountedApexes.RemoveMountedApex(apex.GetManifest().name(), apex.GetPath(),
- true);
};
auto scope_guard = android::base::make_scope_guard(cleaner);
- auto result = verify_fn(temp_mount_point);
- if (!result.ok()) {
- return result.error();
- }
- if (!unmount_during_cleanup) {
- scope_guard.Disable();
- }
- return {};
+ return verify_fn(temp_mount_point);
}
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");
}
@@ -721,26 +597,9 @@ Result<void> PrePostinstallPackages(const std::vector<ApexFile>& apexes,
}
}
- // 2) If we found hooks, temp mount if required, and run the pre/post-install.
+ // 2) If we found hooks, 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);
+ Result<void> install_status = (*call)(apexes);
if (!install_status.ok()) {
return install_status;
}
@@ -759,23 +618,20 @@ Result<void> PostinstallPackages(const std::vector<ApexFile>& apexes) {
&StagePostInstall);
}
-// Converts a list of apex file paths into a list of ApexFile objects
-//
-// Returns error when trying to open empty set of inputs.
-Result<std::vector<ApexFile>> OpenApexFiles(
- const std::vector<std::string>& paths) {
- if (paths.empty()) {
- return Errorf("Empty set of inputs");
- }
- std::vector<ApexFile> ret;
+template <typename RetType, typename Fn>
+RetType HandlePackages(const std::vector<std::string>& paths, Fn fn) {
+ // 1) Open all APEXes.
+ std::vector<ApexFile> apex_files;
for (const std::string& path : paths) {
Result<ApexFile> apex_file = ApexFile::Open(path);
if (!apex_file.ok()) {
return apex_file.error();
}
- ret.emplace_back(std::move(*apex_file));
+ apex_files.emplace_back(std::move(*apex_file));
}
- return ret;
+
+ // 2) Dispatch.
+ return fn(apex_files);
}
Result<void> ValidateStagingShimApex(const ApexFile& to) {
@@ -788,20 +644,14 @@ Result<void> ValidateStagingShimApex(const ApexFile& to) {
auto verify_fn = [&](const std::string& system_apex_path) {
return shim::ValidateUpdate(system_apex_path, to.GetPath());
};
- return RunVerifyFnInsideTempMount(*system_shim, verify_fn, true);
+ return RunVerifyFnInsideTempMount(*system_shim, verify_fn);
}
// A version of apex verification that happens during boot.
// This function should only verification checks that are necessary to run on
// each boot. Try to avoid putting expensive checks inside this function.
Result<void> VerifyPackageBoot(const ApexFile& apex_file) {
- // TODO(ioffe): why do we need this here?
- auto& instance = ApexFileRepository::GetInstance();
- auto public_key = instance.GetPublicKey(apex_file.GetManifest().name());
- if (!public_key.ok()) {
- return public_key.error();
- }
- Result<ApexVerityData> verity_or = apex_file.VerifyApexVerity(*public_key);
+ Result<ApexVerityData> verity_or = apex_file.VerifyApexVerity();
if (!verity_or.ok()) {
return verity_or.error();
}
@@ -818,48 +668,49 @@ Result<void> VerifyPackageBoot(const ApexFile& apex_file) {
return {};
}
-// A version of apex verification that happens on SubmitStagedSession.
+// 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
// during boot.
-Result<void> VerifyPackageStagedInstall(const ApexFile& apex_file) {
+Result<void> VerifyPackageInstall(const ApexFile& apex_file) {
const auto& verify_package_boot_status = VerifyPackageBoot(apex_file);
if (!verify_package_boot_status.ok()) {
return verify_package_boot_status;
}
+ Result<ApexVerityData> verity_or = apex_file.VerifyApexVerity();
constexpr const auto kSuccessFn = [](const std::string& /*mount_point*/) {
return Result<void>{};
};
- return RunVerifyFnInsideTempMount(apex_file, kSuccessFn, false);
+ return RunVerifyFnInsideTempMount(apex_file, kSuccessFn);
}
template <typename VerifyApexFn>
-Result<std::vector<ApexFile>> VerifyPackages(
+Result<std::vector<ApexFile>> verifyPackages(
const std::vector<std::string>& paths, const VerifyApexFn& verify_apex_fn) {
- Result<std::vector<ApexFile>> apex_files = OpenApexFiles(paths);
- if (!apex_files.ok()) {
- return apex_files.error();
+ if (paths.empty()) {
+ return Errorf("Empty set of inputs");
}
+ LOG(DEBUG) << "verifyPackages() for " << Join(paths, ',');
- LOG(DEBUG) << "VerifyPackages() for " << Join(paths, ',');
-
- for (const ApexFile& apex_file : *apex_files) {
- Result<void> result = verify_apex_fn(apex_file);
- if (!result.ok()) {
- return result.error();
+ auto verify_fn = [&](std::vector<ApexFile>& apexes) {
+ for (const ApexFile& apex_file : apexes) {
+ Result<void> result = verify_apex_fn(apex_file);
+ if (!result.ok()) {
+ return Result<std::vector<ApexFile>>(result.error());
+ }
}
- }
- return std::move(*apex_files);
+ return Result<std::vector<ApexFile>>(std::move(apexes));
+ };
+ return HandlePackages<Result<std::vector<ApexFile>>>(paths, verify_fn);
}
-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
+Result<ApexFile> verifySessionDir(const int session_id) {
+ std::string sessionDirPath = std::string(kStagedSessionsDir) + "/session_" +
+ std::to_string(session_id);
+ LOG(INFO) << "Scanning " << sessionDirPath
<< " looking for packages to be validated";
- Result<std::vector<std::string>> scan =
- FindFilesBySuffix(session_dir_path, {kApexPackageSuffix});
+ Result<std::vector<std::string>> scan = FindApexFilesByName(sessionDirPath);
if (!scan.ok()) {
LOG(WARNING) << scan.error();
return scan.error();
@@ -870,7 +721,7 @@ Result<ApexFile> VerifySessionDir(const int session_id) {
"More than one APEX package found in the same session directory.");
}
- auto verified = VerifyPackages(*scan, VerifyPackageStagedInstall);
+ auto verified = verifyPackages(*scan, VerifyPackageInstall);
if (!verified.ok()) {
return verified.error();
}
@@ -891,27 +742,25 @@ Result<void> DeleteBackup() {
}
Result<void> BackupActivePackages() {
- LOG(DEBUG) << "Initializing backup of " << gConfig->active_apex_data_dir;
+ LOG(DEBUG) << "Initializing backup of " << kActiveApexPackagesDataDir;
// Previous restore might've delete backups folder.
- auto create_status = CreateDirIfNeeded(kApexBackupDir, 0700);
+ auto create_status = createDirIfNeeded(kApexBackupDir, 0700);
if (!create_status.ok()) {
return Error() << "Backup failed : " << create_status.error();
}
- auto apex_active_exists =
- PathExists(std::string(gConfig->active_apex_data_dir));
+ auto apex_active_exists = PathExists(std::string(kActiveApexPackagesDataDir));
if (!apex_active_exists.ok()) {
return Error() << "Backup failed : " << apex_active_exists.error();
}
if (!*apex_active_exists) {
- LOG(DEBUG) << gConfig->active_apex_data_dir
+ LOG(DEBUG) << kActiveApexPackagesDataDir
<< " does not exist. Nothing to backup";
return {};
}
- auto active_packages =
- FindFilesBySuffix(gConfig->active_apex_data_dir, {kApexPackageSuffix});
+ auto active_packages = FindApexFilesByName(kActiveApexPackagesDataDir);
if (!active_packages.ok()) {
return Error() << "Backup failed : " << active_packages.error();
}
@@ -952,7 +801,7 @@ Result<void> BackupActivePackages() {
}
Result<void> RestoreActivePackages() {
- LOG(DEBUG) << "Initializing restore of " << gConfig->active_apex_data_dir;
+ LOG(DEBUG) << "Initializing restore of " << kActiveApexPackagesDataDir;
auto backup_exists = PathExists(std::string(kApexBackupDir));
if (!backup_exists.ok()) {
@@ -963,38 +812,37 @@ Result<void> RestoreActivePackages() {
}
struct stat stat_data;
- if (stat(gConfig->active_apex_data_dir, &stat_data) != 0) {
- return ErrnoError() << "Failed to access " << gConfig->active_apex_data_dir;
+ if (stat(kActiveApexPackagesDataDir, &stat_data) != 0) {
+ return ErrnoError() << "Failed to access " << kActiveApexPackagesDataDir;
}
- LOG(DEBUG) << "Deleting existing packages in "
- << gConfig->active_apex_data_dir;
+ LOG(DEBUG) << "Deleting existing packages in " << kActiveApexPackagesDataDir;
auto delete_status =
- DeleteDirContent(std::string(gConfig->active_apex_data_dir));
+ DeleteDirContent(std::string(kActiveApexPackagesDataDir));
if (!delete_status.ok()) {
return delete_status;
}
LOG(DEBUG) << "Renaming " << kApexBackupDir << " to "
- << gConfig->active_apex_data_dir;
- if (rename(kApexBackupDir, gConfig->active_apex_data_dir) != 0) {
+ << kActiveApexPackagesDataDir;
+ if (rename(kApexBackupDir, kActiveApexPackagesDataDir) != 0) {
return ErrnoError() << "Failed to rename " << kApexBackupDir << " to "
- << gConfig->active_apex_data_dir;
+ << kActiveApexPackagesDataDir;
}
LOG(DEBUG) << "Restoring original permissions for "
- << gConfig->active_apex_data_dir;
- if (chmod(gConfig->active_apex_data_dir, stat_data.st_mode & ALLPERMS) != 0) {
+ << kActiveApexPackagesDataDir;
+ if (chmod(kActiveApexPackagesDataDir, stat_data.st_mode & ALLPERMS) != 0) {
+ // TODO: should we wipe out /data/apex/active if chmod fails?
return ErrnoError() << "Failed to restore original permissions for "
- << gConfig->active_apex_data_dir;
+ << kActiveApexPackagesDataDir;
}
return {};
}
-Result<void> UnmountPackage(const ApexFile& apex, bool allow_latest,
- bool deferred) {
- LOG(INFO) << "Unmounting " << GetPackageId(apex.GetManifest());
+Result<void> UnmountPackage(const ApexFile& apex, bool allow_latest) {
+ LOG(VERBOSE) << "Unmounting " << GetPackageId(apex.GetManifest());
const ApexManifest& manifest = apex.GetManifest();
@@ -1013,39 +861,33 @@ Result<void> UnmountPackage(const ApexFile& apex, bool allow_latest,
return Error() << "Did not find " << apex.GetPath();
}
- // Concept of latest sharedlibs apex is somewhat blurred. Since this is only
- // used in testing, it is ok to always allow unmounting sharedlibs apex.
- if (latest && !manifest.providesharedapexlibs()) {
+ if (latest) {
if (!allow_latest) {
return Error() << "Package " << apex.GetPath() << " is active";
}
std::string mount_point = apexd_private::GetActiveMountPoint(manifest);
- LOG(INFO) << "Unmounting " << mount_point;
+ LOG(VERBOSE) << "Unmounting and deleting " << mount_point;
if (umount2(mount_point.c_str(), UMOUNT_NOFOLLOW) != 0) {
return ErrnoError() << "Failed to unmount " << mount_point;
}
-
- if (!deferred) {
- if (rmdir(mount_point.c_str()) != 0) {
- PLOG(ERROR) << "Failed to rmdir " << mount_point;
- }
+ if (rmdir(mount_point.c_str()) != 0) {
+ PLOG(ERROR) << "Could not rmdir " << mount_point;
+ // Continue here.
}
}
// Clean up gMountedApexes now, even though we're not fully done.
gMountedApexes.RemoveMountedApex(manifest.name(), apex.GetPath());
- return Unmount(*data, deferred);
+ return Unmount(*data);
}
} // namespace
-void SetConfig(const ApexdConfig& config) { gConfig = config; }
-
-Result<void> MountPackage(const ApexFile& apex, const std::string& mount_point,
- const std::string& device_name) {
- auto ret = MountPackageImpl(apex, mount_point, device_name,
- GetHashTreeFileName(apex, /* is_new= */ false),
- /* verify_image = */ false);
+Result<void> MountPackage(const ApexFile& apex, const std::string& mountPoint) {
+ auto ret =
+ MountPackageImpl(apex, mountPoint, GetPackageId(apex.GetManifest()),
+ GetHashTreeFileName(apex, /* is_new = */ false),
+ /* verifyImage = */ false);
if (!ret.ok()) {
return ret.error();
}
@@ -1056,41 +898,15 @@ Result<void> MountPackage(const ApexFile& apex, const std::string& mount_point,
namespace apexd_private {
-Result<void> UnmountTempMount(const ApexFile& apex) {
- const ApexManifest& manifest = apex.GetManifest();
- LOG(VERBOSE) << "Unmounting all temp mounts for package " << manifest.name();
-
- bool finished_unmounting = false;
- // If multiple temp mounts exist, ensure that all are unmounted.
- while (!finished_unmounting) {
- Result<MountedApexData> data =
- apexd_private::GetTempMountedApexData(manifest.name());
- if (!data.ok()) {
- finished_unmounting = true;
- } else {
- gMountedApexes.RemoveMountedApex(manifest.name(), data->full_path, true);
- Unmount(*data, /* deferred= */ false);
- }
- }
- return {};
+Result<MountedApexData> TempMountPackage(const ApexFile& apex,
+ const std::string& mount_point) {
+ // TODO(ioffe): consolidate these two methods.
+ return android::apex::VerifyAndTempMountPackage(apex, mount_point);
}
-Result<MountedApexData> GetTempMountedApexData(const std::string& package) {
- bool found = false;
- Result<MountedApexData> mount_data;
- gMountedApexes.ForallMountedApexes(
- package,
- [&](const MountedApexData& data, [[maybe_unused]] bool latest) {
- if (!found) {
- mount_data = data;
- found = true;
- }
- },
- true);
- if (found) {
- return mount_data;
- }
- return Error() << "No temp mount data found for " << package;
+Result<void> Unmount(const MountedApexData& data) {
+ // TODO(ioffe): consolidate these two methods.
+ return android::apex::Unmount(data);
}
bool IsMounted(const std::string& full_path) {
@@ -1119,219 +935,77 @@ std::string GetActiveMountPoint(const ApexManifest& manifest) {
} // namespace apexd_private
-Result<void> ResumeRevertIfNeeded() {
+Result<void> resumeRevertIfNeeded() {
auto sessions =
ApexSession::GetSessionsInState(SessionState::REVERT_IN_PROGRESS);
if (sessions.empty()) {
return {};
}
- return RevertActiveSessions("", "");
-}
-
-Result<void> ActivateSharedLibsPackage(const std::string& mount_point) {
- for (const auto& lib_path : {"lib", "lib64"}) {
- std::string apex_lib_path = mount_point + "/" + lib_path;
- auto lib_dir = PathExists(apex_lib_path);
- if (!lib_dir.ok() || !*lib_dir) {
- continue;
- }
-
- auto iter = std::filesystem::directory_iterator(apex_lib_path);
- std::error_code ec;
-
- while (iter != std::filesystem::end(iter)) {
- const auto& lib_entry = *iter;
- if (!lib_entry.is_directory()) {
- iter = iter.increment(ec);
- if (ec) {
- return Error() << "Failed to scan " << apex_lib_path << " : "
- << ec.message();
- }
- continue;
- }
-
- const auto library_name = lib_entry.path().filename();
- const std::string library_symlink_dir =
- StringPrintf("%s/%s/%s/%s", kApexRoot, kApexSharedLibsSubDir,
- lib_path, library_name.c_str());
-
- auto symlink_dir = PathExists(library_symlink_dir);
- if (!symlink_dir.ok() || !*symlink_dir) {
- std::filesystem::create_directory(library_symlink_dir, ec);
- if (ec) {
- return Error() << "Failed to create directory " << library_symlink_dir
- << ": " << ec.message();
- }
- }
-
- auto inner_iter =
- std::filesystem::directory_iterator(lib_entry.path().string());
-
- while (inner_iter != std::filesystem::end(inner_iter)) {
- const auto& lib_items = *inner_iter;
- const auto hash_value = lib_items.path().filename();
- const std::string library_symlink_hash = StringPrintf(
- "%s/%s", library_symlink_dir.c_str(), hash_value.c_str());
-
- auto hash_dir = PathExists(library_symlink_hash);
- if (hash_dir.ok() && *hash_dir) {
- // Compare file size for two library files with same name and hash
- // value
- auto existing_file_path =
- library_symlink_hash + "/" + library_name.string();
- auto existing_file_size = GetFileSize(existing_file_path);
- if (!existing_file_size.ok()) {
- return existing_file_size.error();
- }
-
- auto new_file_path =
- lib_items.path().string() + "/" + library_name.string();
- auto new_file_size = GetFileSize(new_file_path);
- if (!new_file_size.ok()) {
- return new_file_size.error();
- }
-
- if (*existing_file_size != *new_file_size) {
- return Error() << "There are two libraries with same hash and "
- "different file size : "
- << existing_file_path << " and " << new_file_path;
- }
-
- inner_iter = inner_iter.increment(ec);
- if (ec) {
- return Error() << "Failed to scan " << lib_entry.path().string()
- << " : " << ec.message();
- }
- continue;
- }
- std::filesystem::create_directory_symlink(lib_items.path(),
- library_symlink_hash, ec);
- if (ec) {
- return Error() << "Failed to create symlink from " << lib_items.path()
- << " to " << library_symlink_hash << ec.message();
- }
-
- inner_iter = inner_iter.increment(ec);
- if (ec) {
- return Error() << "Failed to scan " << lib_entry.path().string()
- << " : " << ec.message();
- }
- }
-
- iter = iter.increment(ec);
- if (ec) {
- return Error() << "Failed to scan " << apex_lib_path << " : "
- << ec.message();
- }
- }
- }
-
- return {};
+ return revertActiveSessions("");
}
-bool IsValidPackageName(const std::string& package_name) {
- return kBannedApexName.count(package_name) == 0;
-}
-
-Result<void> ActivatePackageImpl(const ApexFile& apex_file,
- const std::string& device_name) {
+Result<void> activatePackageImpl(const ApexFile& apex_file) {
const ApexManifest& manifest = apex_file.GetManifest();
- if (!IsValidPackageName(manifest.name())) {
- return Errorf("Package name {} is not allowed.", manifest.name());
- }
-
- // Validate upgraded shim apex
- if (shim::IsShimApex(apex_file) &&
- !ApexFileRepository::GetInstance().IsPreInstalledApex(apex_file)) {
- // This is not cheap for shim apex, but it is fine here since we have
- // upgraded shim apex only during CTS tests.
- Result<void> result = VerifyPackageBoot(apex_file);
- if (!result.ok()) {
- LOG(ERROR) << "Failed to validate shim apex: " << apex_file.GetPath();
- return result;
- }
+ if (gBootstrap && !isBootstrapApex(apex_file)) {
+ return {};
}
// See whether we think it's active, and do not allow to activate the same
// version. Also detect whether this is the highest version.
// We roll this into a single check.
bool is_newest_version = true;
+ bool found_other_version = false;
bool version_found_mounted = false;
{
uint64_t new_version = manifest.version();
bool version_found_active = false;
gMountedApexes.ForallMountedApexes(
manifest.name(), [&](const MountedApexData& data, bool latest) {
- Result<ApexFile> other_apex = ApexFile::Open(data.full_path);
- if (!other_apex.ok()) {
+ Result<ApexFile> otherApex = ApexFile::Open(data.full_path);
+ if (!otherApex.ok()) {
return;
}
- if (static_cast<uint64_t>(other_apex->GetManifest().version()) ==
+ found_other_version = true;
+ if (static_cast<uint64_t>(otherApex->GetManifest().version()) ==
new_version) {
version_found_mounted = true;
version_found_active = latest;
}
- if (static_cast<uint64_t>(other_apex->GetManifest().version()) >
+ if (static_cast<uint64_t>(otherApex->GetManifest().version()) >
new_version) {
is_newest_version = false;
}
});
- // If the package provides shared libraries to other APEXs, we need to
- // activate all versions available (i.e. preloaded on /system/apex and
- // available on /data/apex/active). The reason is that there might be some
- // APEXs loaded from /system/apex that reference the libraries contained on
- // the preloaded version of the apex providing shared libraries.
- if (version_found_active && !manifest.providesharedapexlibs()) {
+ if (version_found_active) {
LOG(DEBUG) << "Package " << manifest.name() << " with version "
<< manifest.version() << " already active";
return {};
}
}
- const std::string& mount_point =
- apexd_private::GetPackageMountPoint(manifest);
+ const std::string& mountPoint = apexd_private::GetPackageMountPoint(manifest);
if (!version_found_mounted) {
- auto mount_status = MountPackage(apex_file, mount_point, device_name);
- if (!mount_status.ok()) {
- return mount_status;
+ auto mountStatus = MountPackage(apex_file, mountPoint);
+ if (!mountStatus.ok()) {
+ return mountStatus;
}
}
- // For packages providing shared libraries, avoid creating a bindmount since
- // there is no use for the /apex/<package_name> directory. However, mark the
- // highest version as latest so that the latest version of the package can be
- // properly reported to PackageManager.
- if (manifest.providesharedapexlibs()) {
- if (is_newest_version) {
- gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
- }
- } else {
- bool mounted_latest = false;
- // Bind mount the latest version to /apex/<package_name>, unless the
- // package provides shared libraries to other APEXs.
- if (is_newest_version) {
- const Result<void>& update_st = apexd_private::BindMount(
- apexd_private::GetActiveMountPoint(manifest), mount_point);
- mounted_latest = update_st.has_value();
- if (!update_st.ok()) {
- return Error() << "Failed to update package " << manifest.name()
- << " to version " << manifest.version() << " : "
- << update_st.error();
- }
- }
- if (mounted_latest) {
- gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
+ bool mounted_latest = false;
+ if (is_newest_version) {
+ const Result<void>& update_st = apexd_private::BindMount(
+ apexd_private::GetActiveMountPoint(manifest), mountPoint);
+ mounted_latest = update_st.has_value();
+ if (!update_st.ok()) {
+ return Error() << "Failed to update package " << manifest.name()
+ << " to version " << manifest.version() << " : "
+ << update_st.error();
}
}
-
- if (manifest.providesharedapexlibs()) {
- const auto& handle_shared_libs_apex =
- ActivateSharedLibsPackage(mount_point);
- if (!handle_shared_libs_apex.ok()) {
- return handle_shared_libs_apex;
- }
+ if (mounted_latest) {
+ gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
}
LOG(DEBUG) << "Successfully activated " << apex_file.GetPath()
@@ -1340,30 +1014,28 @@ Result<void> ActivatePackageImpl(const ApexFile& apex_file,
return {};
}
-Result<void> ActivatePackage(const std::string& full_path) {
+Result<void> activatePackage(const std::string& full_path) {
LOG(INFO) << "Trying to activate " << full_path;
Result<ApexFile> apex_file = ApexFile::Open(full_path);
if (!apex_file.ok()) {
return apex_file.error();
}
- return ActivatePackageImpl(*apex_file,
- GetPackageId(apex_file->GetManifest()));
+ return activatePackageImpl(*apex_file);
}
-Result<void> DeactivatePackage(const std::string& full_path) {
+Result<void> deactivatePackage(const std::string& full_path) {
LOG(INFO) << "Trying to deactivate " << full_path;
- Result<ApexFile> apex_file = ApexFile::Open(full_path);
- if (!apex_file.ok()) {
- return apex_file.error();
+ Result<ApexFile> apexFile = ApexFile::Open(full_path);
+ if (!apexFile.ok()) {
+ return apexFile.error();
}
- return UnmountPackage(*apex_file, /* allow_latest= */ true,
- /* deferred= */ false);
+ return UnmountPackage(*apexFile, /* allow_latest= */ true);
}
-std::vector<ApexFile> GetActivePackages() {
+std::vector<ApexFile> getActivePackages() {
std::vector<ApexFile> ret;
gMountedApexes.ForallMountedApexes(
[&](const std::string&, const MountedApexData& data, bool latest) {
@@ -1371,84 +1043,20 @@ std::vector<ApexFile> GetActivePackages() {
return;
}
- Result<ApexFile> apex_file = ApexFile::Open(data.full_path);
- if (!apex_file.ok()) {
+ Result<ApexFile> apexFile = ApexFile::Open(data.full_path);
+ if (!apexFile.ok()) {
+ // TODO: Fail?
return;
}
- ret.emplace_back(std::move(*apex_file));
+ ret.emplace_back(std::move(*apexFile));
});
return ret;
}
-std::vector<ApexFile> CalculateInactivePackages(
- const std::vector<ApexFile>& active) {
- std::vector<ApexFile> inactive = GetFactoryPackages();
- auto new_end = std::remove_if(
- inactive.begin(), inactive.end(), [&active](const ApexFile& apex) {
- return std::any_of(active.begin(), active.end(),
- [&apex](const ApexFile& active_apex) {
- return apex.GetPath() == active_apex.GetPath();
- });
- });
- inactive.erase(new_end, inactive.end());
- return std::move(inactive);
-}
-
-Result<void> EmitApexInfoList(bool is_bootstrap) {
- // on a non-updatable device, we don't have APEX database to emit
- if (!android::sysprop::ApexProperties::updatable().value_or(false)) {
- return {};
- }
-
- // Apexd runs both in "bootstrap" and "default" mount namespace.
- // To expose /apex/apex-info-list.xml separately in each mount namespaces,
- // we write /apex/.<namespace>-apex-info-list .xml file first and then
- // bind mount it to the canonical file (/apex/apex-info-list.xml).
- const std::string file_name =
- fmt::format("{}/.{}-{}", kApexRoot,
- is_bootstrap ? "bootstrap" : "default", kApexInfoList);
-
- unique_fd fd(TEMP_FAILURE_RETRY(
- open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
- if (fd.get() == -1) {
- return ErrnoErrorf("Can't open {}", file_name);
- }
-
- const std::vector<ApexFile> active(GetActivePackages());
-
- std::vector<ApexFile> inactive;
- // we skip for non-activated built-in apexes in bootstrap mode
- // in order to avoid boottime increase
- if (!is_bootstrap) {
- inactive = CalculateInactivePackages(active);
- }
-
- std::stringstream xml;
- CollectApexInfoList(xml, active, inactive);
-
- if (!android::base::WriteStringToFd(xml.str(), fd)) {
- return ErrnoErrorf("Can't write to {}", file_name);
- }
-
- fd.reset();
-
- const std::string mount_point =
- fmt::format("{}/{}", kApexRoot, kApexInfoList);
- if (access(mount_point.c_str(), F_OK) != 0) {
- close(open(mount_point.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
- 0644));
- }
- if (mount(file_name.c_str(), mount_point.c_str(), nullptr, MS_BIND,
- nullptr) == -1) {
- return ErrnoErrorf("Can't bind mount {} to {}", file_name, mount_point);
- }
- return RestoreconPath(file_name);
-}
-
namespace {
std::unordered_map<std::string, uint64_t> GetActivePackagesMap() {
- std::vector<ApexFile> active_packages = GetActivePackages();
+ std::vector<ApexFile> active_packages = getActivePackages();
std::unordered_map<std::string, uint64_t> ret;
for (const auto& package : active_packages) {
const ApexManifest& manifest = package.GetManifest();
@@ -1459,50 +1067,28 @@ std::unordered_map<std::string, uint64_t> GetActivePackagesMap() {
} // namespace
-std::vector<ApexFile> GetFactoryPackages() {
+std::vector<ApexFile> getFactoryPackages() {
std::vector<ApexFile> ret;
-
- // Decompressed APEX is considered factory package
- std::vector<std::string> decompressed_pkg_names;
- auto active_pkgs = GetActivePackages();
- for (ApexFile& apex : active_pkgs) {
- if (ApexFileRepository::GetInstance().IsDecompressedApex(apex)) {
- decompressed_pkg_names.push_back(apex.GetManifest().name());
- ret.emplace_back(std::move(apex));
- }
- }
-
- for (const auto& dir : gConfig->apex_built_in_dirs) {
- auto all_apex_files = FindFilesBySuffix(
- dir, {kApexPackageSuffix, kCompressedApexPackageSuffix});
- if (!all_apex_files.ok()) {
- LOG(ERROR) << all_apex_files.error();
+ for (const auto& dir : kApexPackageBuiltinDirs) {
+ auto apex_files = FindApexFilesByName(dir);
+ if (!apex_files.ok()) {
+ LOG(ERROR) << apex_files.error();
continue;
}
-
- for (const std::string& path : *all_apex_files) {
+ for (const std::string& path : *apex_files) {
Result<ApexFile> apex_file = ApexFile::Open(path);
if (!apex_file.ok()) {
LOG(ERROR) << apex_file.error();
- continue;
- }
- // Ignore compressed APEX if it has been decompressed already
- if (apex_file->IsCompressed() &&
- std::find(decompressed_pkg_names.begin(),
- decompressed_pkg_names.end(),
- apex_file->GetManifest().name()) !=
- decompressed_pkg_names.end()) {
- continue;
+ } else {
+ ret.emplace_back(std::move(*apex_file));
}
-
- ret.emplace_back(std::move(*apex_file));
}
}
return ret;
}
-Result<ApexFile> GetActivePackage(const std::string& packageName) {
- std::vector<ApexFile> packages = GetActivePackages();
+Result<ApexFile> getActivePackage(const std::string& packageName) {
+ std::vector<ApexFile> packages = getActivePackages();
for (ApexFile& apex : packages) {
if (apex.GetManifest().name() == packageName) {
return std::move(apex);
@@ -1517,7 +1103,7 @@ Result<ApexFile> GetActivePackage(const std::string& packageName) {
*
* Returns without error only if session was successfully aborted.
**/
-Result<void> AbortStagedSession(int session_id) {
+Result<void> abortStagedSession(int session_id) {
auto session = ApexSession::GetSession(session_id);
if (!session.ok()) {
return Error() << "No session found with id " << session_id;
@@ -1532,29 +1118,23 @@ Result<void> AbortStagedSession(int session_id) {
}
}
+// TODO(ioffe): cleanup activation logic to avoid unnecessary scanning.
namespace {
-// 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) {
+Result<std::vector<ApexFile>> ScanApexFiles(const char* apex_package_dir) {
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);
+ Result<std::vector<std::string>> scan = FindApexFilesByName(apex_package_dir);
if (!scan.ok()) {
return Error() << "Failed to scan " << apex_package_dir << " : "
<< scan.error();
}
std::vector<ApexFile> ret;
for (const auto& name : *scan) {
+ LOG(INFO) << "Found " << name;
Result<ApexFile> apex_file = ApexFile::Open(name);
if (!apex_file.ok()) {
LOG(ERROR) << "Failed to scan " << name << " : " << apex_file.error();
@@ -1565,152 +1145,64 @@ Result<std::vector<ApexFile>> ScanApexFiles(const char* apex_package_dir,
return ret;
}
-std::vector<Result<void>> ActivateApexWorker(
- bool is_ota_chroot, std::queue<const ApexFile*>& apex_queue,
- std::mutex& mutex) {
- std::vector<Result<void>> ret;
-
- while (true) {
- const ApexFile* apex;
- {
- std::lock_guard lock(mutex);
- if (apex_queue.empty()) break;
- apex = apex_queue.front();
- apex_queue.pop();
+Result<void> ActivateApexPackages(const std::vector<ApexFile>& apexes) {
+ const auto& packages_with_code = GetActivePackagesMap();
+ size_t failed_cnt = 0;
+ size_t skipped_cnt = 0;
+ size_t activated_cnt = 0;
+ for (const auto& apex : apexes) {
+ uint64_t new_version = static_cast<uint64_t>(apex.GetManifest().version());
+ const auto& it = packages_with_code.find(apex.GetManifest().name());
+ if (it != packages_with_code.end() && it->second >= new_version) {
+ LOG(INFO) << "Skipping activation of " << apex.GetPath()
+ << " same package with higher version " << it->second
+ << " is already active";
+ skipped_cnt++;
+ continue;
}
- std::string device_name = GetPackageId(apex->GetManifest());
- if (is_ota_chroot) {
- device_name += ".chroot";
- }
- if (auto res = ActivatePackageImpl(*apex, device_name); !res.ok()) {
- ret.push_back(Error() << "Failed to activate " << apex->GetPath() << " : "
- << res.error());
+ if (auto res = activatePackageImpl(apex); !res.ok()) {
+ LOG(ERROR) << "Failed to activate " << apex.GetPath() << " : "
+ << res.error();
+ failed_cnt++;
} else {
- ret.push_back({});
- }
- }
-
- return ret;
-}
-
-Result<void> ActivateApexPackages(const std::vector<ApexFileRef>& apexes,
- bool is_ota_chroot) {
- std::queue<const ApexFile*> apex_queue;
- std::mutex apex_queue_mutex;
-
- for (const ApexFile& apex : apexes) {
- apex_queue.emplace(&apex);
- }
-
- // Creates threads as many as half number of cores for the performance.
- size_t worker_num = std::max(get_nprocs_conf() >> 1, 1);
- worker_num = std::min(apex_queue.size(), worker_num);
-
- // On -eng builds there might be two different pre-installed art apexes.
- // Attempting to activate them in parallel will result in UB (e.g.
- // apexd-bootstrap might crash). In order to avoid this, for the time being on
- // -eng builds activate apexes sequentially.
- // TODO(b/176497601): remove this.
- if (GetProperty("ro.build.type", "") == "eng") {
- worker_num = 1;
- }
-
- std::vector<std::future<std::vector<Result<void>>>> futures;
- futures.reserve(worker_num);
- for (size_t i = 0; i < worker_num; i++) {
- futures.push_back(std::async(std::launch::async, ActivateApexWorker,
- std::ref(is_ota_chroot), std::ref(apex_queue),
- std::ref(apex_queue_mutex)));
- }
-
- size_t activated_cnt = 0;
- size_t failed_cnt = 0;
- std::string error_message;
- for (size_t i = 0; i < futures.size(); i++) {
- for (const auto& res : futures[i].get()) {
- if (res.ok()) {
- ++activated_cnt;
- } else {
- ++failed_cnt;
- LOG(ERROR) << res.error();
- if (failed_cnt == 1) {
- error_message = res.error().message();
- }
- }
+ activated_cnt++;
}
}
-
if (failed_cnt > 0) {
- return Error() << "Failed to activate " << failed_cnt
- << " APEX packages. One of the errors: " << error_message;
+ return Error() << "Failed to activate " << failed_cnt << " APEX packages";
}
- LOG(INFO) << "Activated " << activated_cnt << " packages.";
+ LOG(INFO) << "Activated " << activated_cnt
+ << " packages. Skipped: " << skipped_cnt;
return {};
}
-// A fallback function in case some of the apexes failed to activate. For all
-// 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,
- 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();
- std::vector<ApexFileRef> fallback_apexes;
- for (const auto& apex_ref : apexes) {
- const auto& apex = apex_ref.get();
- if (apex.GetManifest().providesharedapexlibs()) {
- // We must mount both versions of sharedlibs apex anyway. Not much we can
- // do here.
- continue;
- }
- if (file_repository.IsPreInstalledApex(apex)) {
- // We tried to activate pre-installed apex in the first place. No need to
- // try again.
- continue;
- }
- const std::string& name = apex.GetManifest().name();
- if (activated_apexes.find(name) == activated_apexes.end()) {
- fallback_apexes.push_back(file_repository.GetPreInstalledApex(name));
- }
- }
-
- // Process compressed APEX, if any
- std::vector<ApexFileRef> compressed_apex;
- for (auto it = fallback_apexes.begin(); it != fallback_apexes.end();) {
- if (it->get().IsCompressed()) {
- compressed_apex.emplace_back(*it);
- it = fallback_apexes.erase(it);
- } else {
- it++;
- }
- }
- std::vector<ApexFile> decompressed_apex;
- if (!compressed_apex.empty()) {
- decompressed_apex =
- ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ false);
- for (const ApexFile& apex_file : decompressed_apex) {
- fallback_apexes.emplace_back(std::cref(apex_file));
- }
- }
- return ActivateApexPackages(fallback_apexes, is_ota_chroot);
+bool ShouldActivateApexOnData(const ApexFile& apex) {
+ return HasPreInstalledVersion(apex.GetManifest().name());
}
} // namespace
+Result<void> scanPackagesDirAndActivate(const char* apex_package_dir) {
+ auto apexes = ScanApexFiles(apex_package_dir);
+ if (!apexes) {
+ return apexes.error();
+ }
+ return ActivateApexPackages(*apexes);
+}
+
/**
* Snapshots data from base_dir/apexdata/<apex name> to
* base_dir/apexrollback/<rollback id>/<apex name>.
*/
-Result<void> SnapshotDataDirectory(const std::string& base_dir,
+Result<void> snapshotDataDirectory(const std::string& base_dir,
const int rollback_id,
const std::string& apex_name,
bool pre_restore = false) {
auto rollback_path =
StringPrintf("%s/%s/%d%s", base_dir.c_str(), kApexSnapshotSubDir,
rollback_id, pre_restore ? kPreRestoreSuffix : "");
- const Result<void> result = CreateDirIfNeeded(rollback_path, 0700);
+ const Result<void> result = createDirIfNeeded(rollback_path, 0700);
if (!result.ok()) {
return Error() << "Failed to create snapshot directory for rollback "
<< rollback_id << " : " << result.error();
@@ -1728,7 +1220,7 @@ Result<void> SnapshotDataDirectory(const std::string& base_dir,
* to base_dir/apexdata/<apex name>.
* Note the snapshot will be deleted after restoration succeeded.
*/
-Result<void> RestoreDataDirectory(const std::string& base_dir,
+Result<void> restoreDataDirectory(const std::string& base_dir,
const int rollback_id,
const std::string& apex_name,
bool pre_restore = false) {
@@ -1752,13 +1244,13 @@ Result<void> RestoreDataDirectory(const std::string& base_dir,
return {};
}
-void SnapshotOrRestoreDeIfNeeded(const std::string& base_dir,
+void snapshotOrRestoreDeIfNeeded(const std::string& base_dir,
const ApexSession& session) {
if (session.HasRollbackEnabled()) {
for (const auto& apex_name : session.GetApexNames()) {
Result<void> result =
- SnapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name);
- if (!result.ok()) {
+ snapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name);
+ if (!result) {
LOG(ERROR) << "Snapshot failed for " << apex_name << ": "
<< result.error();
}
@@ -1767,11 +1259,11 @@ void SnapshotOrRestoreDeIfNeeded(const std::string& base_dir,
for (const auto& apex_name : session.GetApexNames()) {
if (!gSupportsFsCheckpoints) {
// Snapshot before restore so this rollback can be reverted.
- SnapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name,
+ snapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name,
true /* pre_restore */);
}
Result<void> result =
- RestoreDataDirectory(base_dir, session.GetRollbackId(), apex_name);
+ restoreDataDirectory(base_dir, session.GetRollbackId(), apex_name);
if (!result.ok()) {
LOG(ERROR) << "Restore of data failed for " << apex_name << ": "
<< result.error();
@@ -1780,18 +1272,18 @@ void SnapshotOrRestoreDeIfNeeded(const std::string& base_dir,
}
}
-void SnapshotOrRestoreDeSysData() {
+void snapshotOrRestoreDeSysData() {
auto sessions = ApexSession::GetSessionsInState(SessionState::ACTIVATED);
for (const ApexSession& session : sessions) {
- SnapshotOrRestoreDeIfNeeded(kDeSysDataDir, session);
+ snapshotOrRestoreDeIfNeeded(kDeSysDataDir, session);
}
}
-int SnapshotOrRestoreDeUserData() {
+int snapshotOrRestoreDeUserData() {
auto user_dirs = GetDeUserDirs();
- if (!user_dirs.ok()) {
+ if (!user_dirs) {
LOG(ERROR) << "Error reading dirs " << user_dirs.error();
return 1;
}
@@ -1800,69 +1292,93 @@ int SnapshotOrRestoreDeUserData() {
for (const ApexSession& session : sessions) {
for (const auto& user_dir : *user_dirs) {
- SnapshotOrRestoreDeIfNeeded(user_dir, session);
+ snapshotOrRestoreDeIfNeeded(user_dir, session);
}
}
return 0;
}
-Result<void> SnapshotCeData(const int user_id, const int rollback_id,
- const std::string& apex_name) {
+Result<ino_t> snapshotCeData(const int user_id, const int rollback_id,
+ const std::string& apex_name) {
auto base_dir = StringPrintf("%s/%d", kCeDataDir, user_id);
- return SnapshotDataDirectory(base_dir, rollback_id, apex_name);
+ Result<void> result = snapshotDataDirectory(base_dir, rollback_id, apex_name);
+ if (!result) {
+ return result.error();
+ }
+ auto ce_snapshot_path =
+ StringPrintf("%s/%s/%d/%s", base_dir.c_str(), kApexSnapshotSubDir,
+ rollback_id, apex_name.c_str());
+ return get_path_inode(ce_snapshot_path);
}
-Result<void> RestoreCeData(const int user_id, const int rollback_id,
+Result<void> restoreCeData(const int user_id, const int rollback_id,
const std::string& apex_name) {
auto base_dir = StringPrintf("%s/%d", kCeDataDir, user_id);
- return RestoreDataDirectory(base_dir, rollback_id, apex_name);
+ return restoreDataDirectory(base_dir, rollback_id, apex_name);
}
// Migrates sessions directory from /data/apex/sessions to
// /metadata/apex/sessions, if necessary.
-Result<void> MigrateSessionsDirIfNeeded() {
- return ApexSession::MigrateToMetadataSessionsDir();
+Result<void> migrateSessionsDirIfNeeded() {
+ namespace fs = std::filesystem;
+ auto from_path = std::string(kApexDataDir) + "/sessions";
+ auto exists = PathExists(from_path);
+ if (!exists) {
+ return Error() << "Failed to access " << from_path << ": "
+ << exists.error();
+ }
+ if (!*exists) {
+ LOG(DEBUG) << from_path << " does not exist. Nothing to migrate.";
+ return {};
+ }
+ auto to_path = kApexSessionsDir;
+ std::error_code error_code;
+ fs::copy(from_path, to_path, fs::copy_options::recursive, error_code);
+ if (error_code) {
+ return Error() << "Failed to copy old sessions directory"
+ << error_code.message();
+ }
+ fs::remove_all(from_path, error_code);
+ if (error_code) {
+ return Error() << "Failed to delete old sessions directory "
+ << error_code.message();
+ }
+ return {};
}
-Result<void> DestroySnapshots(const std::string& base_dir,
+Result<void> destroySnapshots(const std::string& base_dir,
const int rollback_id) {
auto path = StringPrintf("%s/%s/%d", base_dir.c_str(), kApexSnapshotSubDir,
rollback_id);
return DeleteDir(path);
}
-Result<void> DestroyDeSnapshots(const int rollback_id) {
- DestroySnapshots(kDeSysDataDir, rollback_id);
+Result<void> destroyDeSnapshots(const int rollback_id) {
+ destroySnapshots(kDeSysDataDir, rollback_id);
auto user_dirs = GetDeUserDirs();
- if (!user_dirs.ok()) {
+ if (!user_dirs) {
return Error() << "Error reading user dirs " << user_dirs.error();
}
for (const auto& user_dir : *user_dirs) {
- DestroySnapshots(user_dir, rollback_id);
+ destroySnapshots(user_dir, rollback_id);
}
return {};
}
-Result<void> DestroyCeSnapshots(const int user_id, const int rollback_id) {
- auto path = StringPrintf("%s/%d/%s/%d", kCeDataDir, user_id,
- kApexSnapshotSubDir, rollback_id);
- return DeleteDir(path);
-}
-
/**
* Deletes all credential-encrypted snapshots for the given user, except for
* those listed in retain_rollback_ids.
*/
-Result<void> DestroyCeSnapshotsNotSpecified(
+Result<void> destroyCeSnapshotsNotSpecified(
int user_id, const std::vector<int>& retain_rollback_ids) {
auto snapshot_root =
StringPrintf("%s/%d/%s", kCeDataDir, user_id, kApexSnapshotSubDir);
auto snapshot_dirs = GetSubdirs(snapshot_root);
- if (!snapshot_dirs.ok()) {
+ if (!snapshot_dirs) {
return Error() << "Error reading snapshot dirs " << snapshot_dirs.error();
}
@@ -1874,7 +1390,7 @@ Result<void> DestroyCeSnapshotsNotSpecified(
std::find(retain_rollback_ids.begin(), retain_rollback_ids.end(),
snapshot_id) == retain_rollback_ids.end()) {
Result<void> result = DeleteDir(snapshot_dir);
- if (!result.ok()) {
+ if (!result) {
return Error() << "Destroy CE snapshot failed for " << snapshot_dir
<< " : " << result.error();
}
@@ -1883,16 +1399,16 @@ Result<void> DestroyCeSnapshotsNotSpecified(
return {};
}
-void RestorePreRestoreSnapshotsIfPresent(const std::string& base_dir,
+void restorePreRestoreSnapshotsIfPresent(const std::string& base_dir,
const ApexSession& session) {
auto pre_restore_snapshot_path =
StringPrintf("%s/%s/%d%s", base_dir.c_str(), kApexSnapshotSubDir,
session.GetRollbackId(), kPreRestoreSuffix);
- if (PathExists(pre_restore_snapshot_path).ok()) {
+ if (PathExists(pre_restore_snapshot_path)) {
for (const auto& apex_name : session.GetApexNames()) {
- Result<void> result = RestoreDataDirectory(
+ Result<void> result = restoreDataDirectory(
base_dir, session.GetRollbackId(), apex_name, true /* pre_restore */);
- if (!result.ok()) {
+ if (!result) {
LOG(ERROR) << "Restore of pre-restore snapshot failed for " << apex_name
<< ": " << result.error();
}
@@ -1900,77 +1416,71 @@ void RestorePreRestoreSnapshotsIfPresent(const std::string& base_dir,
}
}
-void RestoreDePreRestoreSnapshotsIfPresent(const ApexSession& session) {
- RestorePreRestoreSnapshotsIfPresent(kDeSysDataDir, session);
+void restoreDePreRestoreSnapshotsIfPresent(const ApexSession& session) {
+ restorePreRestoreSnapshotsIfPresent(kDeSysDataDir, session);
auto user_dirs = GetDeUserDirs();
- if (!user_dirs.ok()) {
+ if (!user_dirs) {
LOG(ERROR) << "Error reading user dirs to restore pre-restore snapshots"
<< user_dirs.error();
}
for (const auto& user_dir : *user_dirs) {
- RestorePreRestoreSnapshotsIfPresent(user_dir, session);
+ restorePreRestoreSnapshotsIfPresent(user_dir, session);
}
}
-void DeleteDePreRestoreSnapshots(const std::string& base_dir,
+void deleteDePreRestoreSnapshots(const std::string& base_dir,
const ApexSession& session) {
auto pre_restore_snapshot_path =
StringPrintf("%s/%s/%d%s", base_dir.c_str(), kApexSnapshotSubDir,
session.GetRollbackId(), kPreRestoreSuffix);
Result<void> result = DeleteDir(pre_restore_snapshot_path);
- if (!result.ok()) {
+ if (!result) {
LOG(ERROR) << "Deletion of pre-restore snapshot failed: " << result.error();
}
}
-void DeleteDePreRestoreSnapshots(const ApexSession& session) {
- DeleteDePreRestoreSnapshots(kDeSysDataDir, session);
+void deleteDePreRestoreSnapshots(const ApexSession& session) {
+ deleteDePreRestoreSnapshots(kDeSysDataDir, session);
auto user_dirs = GetDeUserDirs();
- if (!user_dirs.ok()) {
+ if (!user_dirs) {
LOG(ERROR) << "Error reading user dirs to delete pre-restore snapshots"
<< user_dirs.error();
}
for (const auto& user_dir : *user_dirs) {
- DeleteDePreRestoreSnapshots(user_dir, session);
+ deleteDePreRestoreSnapshots(user_dir, session);
}
}
-void OnBootCompleted() {
- ApexdLifecycle::GetInstance().MarkBootCompleted();
- BootCompletedCleanup();
-}
-
-// Returns true if any session gets staged
-void ScanStagedSessionsDirAndStage() {
- LOG(INFO) << "Scanning " << ApexSession::GetSessionsDir()
+void scanStagedSessionsDirAndStage() {
+ LOG(INFO) << "Scanning " << kApexSessionsDir
<< " looking for sessions to be activated.";
- auto sessions_to_activate =
+ auto sessionsToActivate =
ApexSession::GetSessionsInState(SessionState::STAGED);
if (gSupportsFsCheckpoints) {
// A session that is in the ACTIVATED state should still be re-activated if
// fs checkpointing is supported. In this case, a session may be in the
// ACTIVATED state yet the data/apex/active directory may have been
// reverted. The session should be reverted in this scenario.
- auto activated_sessions =
+ auto activatedSessions =
ApexSession::GetSessionsInState(SessionState::ACTIVATED);
- sessions_to_activate.insert(sessions_to_activate.end(),
- activated_sessions.begin(),
- activated_sessions.end());
+ sessionsToActivate.insert(sessionsToActivate.end(),
+ activatedSessions.begin(),
+ activatedSessions.end());
}
- for (auto& session : sessions_to_activate) {
- auto session_id = session.GetId();
+ for (auto& session : sessionsToActivate) {
+ auto sessionId = session.GetId();
auto session_failed_fn = [&]() {
- LOG(WARNING) << "Marking session " << session_id << " as failed.";
+ LOG(WARNING) << "Marking session " << sessionId << " as failed.";
auto st = session.UpdateStateAndCommit(SessionState::ACTIVATION_FAILED);
if (!st.ok()) {
- LOG(WARNING) << "Failed to mark session " << session_id
+ LOG(WARNING) << "Failed to mark session " << sessionId
<< " as failed : " << st.error();
}
};
@@ -1978,101 +1488,74 @@ void ScanStagedSessionsDirAndStage() {
std::string build_fingerprint = GetProperty(kBuildFingerprintSysprop, "");
if (session.GetBuildFingerprint().compare(build_fingerprint) != 0) {
- auto error_message = "APEX build fingerprint has changed";
- LOG(ERROR) << error_message;
- session.SetErrorMessage(error_message);
- continue;
- }
-
- // If device supports fs-checkpoint, then apex session should only be
- // installed when in checkpoint-mode. Otherwise, we will not be able to
- // revert /data on error.
- if (gSupportsFsCheckpoints && !gInFsCheckpointMode) {
- auto error_message =
- "Cannot install apex session if not in fs-checkpoint mode";
- LOG(ERROR) << error_message;
- session.SetErrorMessage(error_message);
+ LOG(ERROR) << "APEX build fingerprint has changed";
continue;
}
- std::vector<std::string> dirs_to_scan;
+ std::vector<std::string> dirsToScan;
if (session.GetChildSessionIds().empty()) {
- dirs_to_scan.push_back(std::string(gConfig->staged_session_dir) +
- "/session_" + std::to_string(session_id));
+ dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
+ std::to_string(sessionId));
} else {
- for (auto child_session_id : session.GetChildSessionIds()) {
- dirs_to_scan.push_back(std::string(gConfig->staged_session_dir) +
- "/session_" + std::to_string(child_session_id));
+ for (auto childSessionId : session.GetChildSessionIds()) {
+ dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
+ std::to_string(childSessionId));
}
}
std::vector<std::string> apexes;
- bool scan_successful = true;
- for (const auto& dir_to_scan : dirs_to_scan) {
- Result<std::vector<std::string>> scan =
- FindFilesBySuffix(dir_to_scan, {kApexPackageSuffix});
+ bool scanSuccessful = true;
+ for (const auto& dirToScan : dirsToScan) {
+ Result<std::vector<std::string>> scan = FindApexFilesByName(dirToScan);
if (!scan.ok()) {
LOG(WARNING) << scan.error();
- session.SetErrorMessage(scan.error().message());
- scan_successful = false;
+ scanSuccessful = false;
break;
}
if (scan->size() > 1) {
- std::string error_message = StringPrintf(
- "More than one APEX package found in the same session directory %s "
- ", skipping activation",
- dir_to_scan.c_str());
- LOG(WARNING) << error_message;
- session.SetErrorMessage(error_message);
- scan_successful = false;
+ LOG(WARNING) << "More than one APEX package found in the same session "
+ << "directory " << dirToScan << ", skipping activation.";
+ scanSuccessful = false;
break;
}
if (scan->empty()) {
- std::string error_message = StringPrintf(
- "No APEX packages found while scanning %s session id: %d.",
- dir_to_scan.c_str(), session_id);
- LOG(WARNING) << error_message;
- session.SetErrorMessage(error_message);
- scan_successful = false;
+ LOG(WARNING) << "No APEX packages found while scanning " << dirToScan
+ << " session id: " << sessionId << ".";
+ scanSuccessful = false;
break;
}
apexes.push_back(std::move((*scan)[0]));
}
- if (!scan_successful) {
+ if (!scanSuccessful) {
continue;
}
// Run postinstall, if necessary.
- Result<void> postinstall_status = PostinstallPackages(apexes);
+ 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);
+ LOG(ERROR) << "Postinstall failed for session "
+ << std::to_string(sessionId) << ": "
+ << postinstall_status.error();
continue;
}
for (const auto& apex : apexes) {
- // TODO(b/158470836): Avoid opening ApexFile repeatedly.
+ // TODO: Avoid opening ApexFile repeatedly.
Result<ApexFile> apex_file = ApexFile::Open(apex);
- if (!apex_file.ok()) {
+ if (!apex_file) {
LOG(ERROR) << "Cannot open apex file during staging: " << apex;
continue;
}
session.AddApexName(apex_file->GetManifest().name());
}
- const Result<void> result = StagePackages(apexes);
+ const Result<void> result = stagePackages(apexes);
if (!result.ok()) {
- std::string error_message = StringPrintf(
- "Activation failed for packages %s : %s", Join(apexes, ',').c_str(),
- result.error().message().c_str());
- LOG(ERROR) << error_message;
- session.SetErrorMessage(error_message);
+ LOG(ERROR) << "Activation failed for packages " << Join(apexes, ',')
+ << ": " << result.error();
continue;
}
@@ -2087,61 +1570,49 @@ void ScanStagedSessionsDirAndStage() {
}
}
-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();
+Result<void> preinstallPackages(const std::vector<std::string>& paths) {
+ if (paths.empty()) {
+ return Errorf("Empty set of inputs");
}
- LOG(DEBUG) << "PreinstallPackages() for " << Join(paths, ',');
- return PreinstallPackages(*apex_files);
+ LOG(DEBUG) << "preinstallPackages() for " << Join(paths, ',');
+ return HandlePackages<Result<void>>(paths, PreinstallPackages);
}
-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();
+Result<void> postinstallPackages(const std::vector<std::string>& paths) {
+ if (paths.empty()) {
+ return Errorf("Empty set of inputs");
}
- LOG(DEBUG) << "PostinstallPackages() for " << Join(paths, ',');
- return PostinstallPackages(*apex_files);
+ LOG(DEBUG) << "postinstallPackages() for " << Join(paths, ',');
+ return HandlePackages<Result<void>>(paths, PostinstallPackages);
}
namespace {
std::string StageDestPath(const ApexFile& apex_file) {
- return StringPrintf("%s/%s%s", gConfig->active_apex_data_dir,
+ return StringPrintf("%s/%s%s", kActiveApexPackagesDataDir,
GetPackageId(apex_file.GetManifest()).c_str(),
kApexPackageSuffix);
}
} // namespace
-Result<void> StagePackages(const std::vector<std::string>& tmp_paths) {
- if (tmp_paths.empty()) {
+Result<void> stagePackages(const std::vector<std::string>& tmpPaths) {
+ if (tmpPaths.empty()) {
return Errorf("Empty set of inputs");
}
- LOG(DEBUG) << "StagePackages() for " << Join(tmp_paths, ',');
+ LOG(DEBUG) << "stagePackages() for " << Join(tmpPaths, ',');
// Note: this function is temporary. As such the code is not optimized, e.g.,
// it will open ApexFiles multiple times.
// 1) Verify all packages.
- Result<std::vector<ApexFile>> apex_files = OpenApexFiles(tmp_paths);
- if (!apex_files.ok()) {
- return apex_files.error();
- }
- for (const ApexFile& apex_file : *apex_files) {
- if (shim::IsShimApex(apex_file)) {
- // Shim apex will be validated on every boot. No need to do it here.
- continue;
- }
- Result<void> result = VerifyPackageBoot(apex_file);
- if (!result.ok()) {
- return result.error();
- }
+ auto verify_status = verifyPackages(tmpPaths, VerifyPackageBoot);
+ if (!verify_status.ok()) {
+ return verify_status.error();
}
// Make sure that kActiveApexPackagesDataDir exists.
auto create_dir_status =
- CreateDirIfNeeded(std::string(gConfig->active_apex_data_dir), 0755);
+ createDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0755);
if (!create_dir_status.ok()) {
return create_dir_status.error();
}
@@ -2166,12 +1637,16 @@ Result<void> StagePackages(const std::vector<std::string>& tmp_paths) {
auto scope_guard = android::base::make_scope_guard(deleter);
std::unordered_set<std::string> staged_packages;
- for (const ApexFile& apex_file : *apex_files) {
+ for (const std::string& path : tmpPaths) {
+ Result<ApexFile> apex_file = ApexFile::Open(path);
+ if (!apex_file.ok()) {
+ return apex_file.error();
+ }
// First promote new hashtree file to the one that will be used when
// mounting apex.
- std::string new_hashtree_file = GetHashTreeFileName(apex_file,
+ std::string new_hashtree_file = GetHashTreeFileName(*apex_file,
/* is_new = */ true);
- std::string old_hashtree_file = GetHashTreeFileName(apex_file,
+ std::string old_hashtree_file = GetHashTreeFileName(*apex_file,
/* is_new = */ false);
if (access(new_hashtree_file.c_str(), F_OK) == 0) {
if (TEMP_FAILURE_RETRY(rename(new_hashtree_file.c_str(),
@@ -2182,7 +1657,7 @@ Result<void> StagePackages(const std::vector<std::string>& tmp_paths) {
changed_hashtree_files.emplace_back(std::move(old_hashtree_file));
}
// And only then move apex to /data/apex/active.
- std::string dest_path = StageDestPath(apex_file);
+ std::string dest_path = StageDestPath(*apex_file);
if (access(dest_path.c_str(), F_OK) == 0) {
LOG(DEBUG) << dest_path << " already exists. Deleting";
if (TEMP_FAILURE_RETRY(unlink(dest_path.c_str())) != 0) {
@@ -2190,14 +1665,15 @@ Result<void> StagePackages(const std::vector<std::string>& tmp_paths) {
}
}
- if (link(apex_file.GetPath().c_str(), dest_path.c_str()) != 0) {
- return ErrnoError() << "Unable to link " << apex_file.GetPath() << " to "
+ if (link(apex_file->GetPath().c_str(), dest_path.c_str()) != 0) {
+ // TODO: Get correct binder error status.
+ return ErrnoError() << "Unable to link " << apex_file->GetPath() << " to "
<< dest_path;
}
staged_files.insert(dest_path);
- staged_packages.insert(apex_file.GetManifest().name());
+ staged_packages.insert(apex_file->GetManifest().name());
- LOG(DEBUG) << "Success linking " << apex_file.GetPath() << " to "
+ LOG(DEBUG) << "Success linking " << apex_file->GetPath() << " to "
<< dest_path;
}
@@ -2206,19 +1682,18 @@ Result<void> StagePackages(const std::vector<std::string>& tmp_paths) {
return RemovePreviouslyActiveApexFiles(staged_packages, staged_files);
}
-Result<void> UnstagePackages(const std::vector<std::string>& paths) {
+Result<void> unstagePackages(const std::vector<std::string>& paths) {
if (paths.empty()) {
return Errorf("Empty set of inputs");
}
- LOG(DEBUG) << "UnstagePackages() for " << Join(paths, ',');
+ LOG(DEBUG) << "unstagePackages() for " << Join(paths, ',');
+
+ // TODO: to make unstage safer, we can copy to be unstaged packages to a
+ // temporary folder and restore state from it in case unstagePackages fails.
for (const std::string& path : paths) {
- auto apex = ApexFile::Open(path);
- if (!apex.ok()) {
- return apex.error();
- }
- if (ApexFileRepository::GetInstance().IsPreInstalledApex(*apex)) {
- return Error() << "Can't uninstall pre-installed apex " << path;
+ if (access(path.c_str(), F_OK) != 0) {
+ return ErrnoError() << "Can't access " << path;
}
}
@@ -2240,57 +1715,59 @@ Result<void> UnstagePackages(const std::vector<std::string>& paths) {
* Also, we need to put staged sessions in /data/apex/sessions in REVERTED state
* so that they do not get activated on next reboot.
*/
-Result<void> RevertActiveSessions(const std::string& crashing_native_process,
- const std::string& error_message) {
+Result<void> revertActiveSessions(const std::string& crashing_native_process) {
// First check whenever there is anything to revert. If there is none, then
// fail. This prevents apexd from boot looping a device in case a native
// process is crashing and there are no apex updates.
- auto active_sessions = ApexSession::GetActiveSessions();
- if (active_sessions.empty()) {
+ auto activeSessions = ApexSession::GetActiveSessions();
+ if (activeSessions.empty()) {
return Error() << "Revert requested, when there are no active sessions.";
}
- for (auto& session : active_sessions) {
+ for (auto& session : activeSessions) {
if (!crashing_native_process.empty()) {
session.SetCrashingNativeProcess(crashing_native_process);
}
- if (!error_message.empty()) {
- session.SetErrorMessage(error_message);
- }
auto status =
session.UpdateStateAndCommit(SessionState::REVERT_IN_PROGRESS);
- if (!status.ok()) {
+ if (!status) {
+ // TODO: should we continue with a revert?
return Error() << "Revert of session " << session
<< " failed : " << status.error();
}
}
+ if (!gInFsCheckpointMode) {
+ // SafetyNet logging for b/19393765
+ android_errorWriteLog(0x534e4554, "193932765");
+ }
+
if (!gSupportsFsCheckpoints) {
- auto restore_status = RestoreActivePackages();
- if (!restore_status.ok()) {
- for (auto& session : active_sessions) {
+ auto restoreStatus = RestoreActivePackages();
+ if (!restoreStatus.ok()) {
+ for (auto& session : activeSessions) {
auto st = session.UpdateStateAndCommit(SessionState::REVERT_FAILED);
LOG(DEBUG) << "Marking " << session << " as failed to revert";
- if (!st.ok()) {
+ if (!st) {
LOG(WARNING) << "Failed to mark session " << session
<< " as failed to revert : " << st.error();
}
}
- return restore_status;
+ return restoreStatus;
}
} else {
LOG(INFO) << "Not restoring active packages in checkpoint mode.";
}
- for (auto& session : active_sessions) {
+ for (auto& session : activeSessions) {
if (!gSupportsFsCheckpoints && session.IsRollback()) {
// If snapshots have already been restored, undo that by restoring the
// pre-restore snapshot.
- RestoreDePreRestoreSnapshotsIfPresent(session);
+ restoreDePreRestoreSnapshotsIfPresent(session);
}
auto status = session.UpdateStateAndCommit(SessionState::REVERTED);
- if (!status.ok()) {
+ if (!status) {
LOG(WARNING) << "Failed to mark session " << session
<< " as reverted : " << status.error();
}
@@ -2299,10 +1776,9 @@ Result<void> RevertActiveSessions(const std::string& crashing_native_process,
return {};
}
-Result<void> RevertActiveSessionsAndReboot(
- const std::string& crashing_native_process,
- const std::string& error_message) {
- auto status = RevertActiveSessions(crashing_native_process, error_message);
+Result<void> revertActiveSessionsAndReboot(
+ const std::string& crashing_native_process) {
+ auto status = revertActiveSessions(crashing_native_process);
if (!status.ok()) {
return status;
}
@@ -2318,101 +1794,49 @@ Result<void> RevertActiveSessionsAndReboot(
return {};
}
-Result<void> CreateSharedLibsApexDir() {
- // Creates /apex/sharedlibs/lib{,64} for SharedLibs APEXes.
- std::string shared_libs_sub_dir =
- StringPrintf("%s/%s", kApexRoot, kApexSharedLibsSubDir);
- auto dir_exists = PathExists(shared_libs_sub_dir);
- if (!dir_exists.ok() || !*dir_exists) {
- std::error_code error_code;
- std::filesystem::create_directory(shared_libs_sub_dir, error_code);
- if (error_code) {
- return Error() << "Failed to create directory " << shared_libs_sub_dir
- << ": " << error_code.message();
- }
- }
- for (const auto& lib_path : {"lib", "lib64"}) {
- std::string apex_lib_path =
- StringPrintf("%s/%s", shared_libs_sub_dir.c_str(), lib_path);
- auto lib_dir_exists = PathExists(apex_lib_path);
- if (!lib_dir_exists.ok() || !*lib_dir_exists) {
- std::error_code error_code;
- std::filesystem::create_directory(apex_lib_path, error_code);
- if (error_code) {
- return Error() << "Failed to create directory " << apex_lib_path << ": "
- << error_code.message();
- }
- }
- }
+int onBootstrap() {
+ gBootstrap = true;
- return {};
-}
-
-int OnBootstrap() {
- auto time_started = boot_clock::now();
- Result<void> pre_allocate = PreAllocateLoopDevices();
- if (!pre_allocate.ok()) {
+ Result<void> preAllocate = preAllocateLoopDevices();
+ if (!preAllocate.ok()) {
LOG(ERROR) << "Failed to pre-allocate loop devices : "
- << pre_allocate.error();
+ << preAllocate.error();
}
- ApexFileRepository& instance = ApexFileRepository::GetInstance();
- static const std::vector<std::string> kBootstrapApexDirs{
+ std::vector<std::string> bootstrap_apex_dirs{
kApexPackageSystemDir, kApexPackageSystemExtDir, kApexPackageVendorDir};
- Result<void> status = instance.AddPreInstalledApex(kBootstrapApexDirs);
+ Result<void> status = collectPreinstalledData(bootstrap_apex_dirs);
if (!status.ok()) {
LOG(ERROR) << "Failed to collect APEX keys : " << status.error();
return 1;
}
- // Create directories for APEX shared libraries.
- auto sharedlibs_apex_dir = CreateSharedLibsApexDir();
- if (!sharedlibs_apex_dir.ok()) {
- LOG(ERROR) << sharedlibs_apex_dir.error();
- return 1;
- }
-
- // Find all bootstrap apexes
- std::vector<ApexFile> bootstrap_apexes;
- for (const auto& dir : kBootstrapApexDirs) {
- auto scan = ScanApexFiles(dir.c_str());
- if (!scan.ok()) {
+ // Activate built-in APEXes for processes launched before /data is mounted.
+ for (const auto& dir : bootstrap_apex_dirs) {
+ auto scan_status = ScanApexFiles(dir.c_str());
+ if (!scan_status.ok()) {
LOG(ERROR) << "Failed to scan APEX files in " << dir << " : "
- << scan.error();
+ << scan_status.error();
+ return 1;
+ }
+ if (auto ret = ActivateApexPackages(*scan_status); !ret.ok()) {
+ LOG(ERROR) << "Failed to activate APEX files in " << dir << " : "
+ << ret.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.
- 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;
}
-
- OnAllPackagesActivated(/*is_bootstrap=*/true);
- auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
- boot_clock::now() - time_started).count();
- LOG(INFO) << "OnBootstrap done, duration=" << time_elapsed;
+ LOG(INFO) << "Bootstrapping done";
return 0;
}
-Result<void> RemountApexFile(const std::string& path) {
- if (auto ret = DeactivatePackage(path); !ret.ok()) {
+Result<void> remountApexFile(const std::string& path) {
+ if (auto ret = deactivatePackage(path); !ret.ok()) {
return ret;
}
- return ActivatePackage(path);
+ return activatePackage(path);
}
-void InitializeVold(CheckpointInterface* checkpoint_service) {
+void initializeVold(CheckpointInterface* checkpoint_service) {
if (checkpoint_service != nullptr) {
gVoldService = checkpoint_service;
Result<bool> supports_fs_checkpoints =
@@ -2435,327 +1859,21 @@ void InitializeVold(CheckpointInterface* checkpoint_service) {
}
}
-void Initialize(CheckpointInterface* checkpoint_service) {
- InitializeVold(checkpoint_service);
- ApexFileRepository& instance = ApexFileRepository::GetInstance();
- Result<void> status = instance.AddPreInstalledApex(kApexPackageBuiltinDirs);
+void initialize(CheckpointInterface* checkpoint_service) {
+ initializeVold(checkpoint_service);
+ Result<void> status = collectPreinstalledData(kApexPackageBuiltinDirs);
if (!status.ok()) {
- LOG(ERROR) << "Failed to collect pre-installed APEX files : "
- << status.error();
- return;
- }
- gMountedApexes.PopulateFromMounts(gConfig->active_apex_data_dir,
- gConfig->decompression_dir,
- gConfig->apex_hash_tree_dir);
-}
-
-// Note: Pre-installed apex are initialized in Initialize(CheckpointInterface*)
-// TODO(b/172911822): Consolidate this with Initialize() when
-// ApexFileRepository can act as cache and re-scanning is not expensive
-void InitializeDataApex() {
- ApexFileRepository& instance = ApexFileRepository::GetInstance();
- Result<void> status = instance.AddDataApex(kActiveApexPackagesDataDir);
- if (!status.ok()) {
- LOG(ERROR) << "Failed to collect data APEX files : " << status.error();
+ LOG(ERROR) << "Failed to collect APEX keys : " << status.error();
return;
}
-}
-
-/**
- * For every package X, there can be at most two APEX, pre-installed vs
- * installed on data. We usually select only one of these APEX for each package
- * based on the following conditions:
- * - Package X must be pre-installed on one of the built-in directories.
- * - If there are multiple APEX, we select the one with highest version.
- * - If there are multiple with same version, we give priority to APEX on
- * /data partition.
- *
- * Typically, only one APEX is activated for each package, but APEX that provide
- * shared libs are exceptions. We have to activate both APEX for them.
- *
- * @param all_apex all the APEX grouped by their package name
- * @return list of ApexFile that needs to be activated
- */
-std::vector<ApexFileRef> SelectApexForActivation(
- const std::unordered_map<std::string, std::vector<ApexFileRef>>& all_apex,
- const ApexFileRepository& instance) {
- LOG(INFO) << "Selecting APEX for activation";
- std::vector<ApexFileRef> activation_list;
- // For every package X, select which APEX to activate
- for (auto& apex_it : all_apex) {
- const std::string& package_name = apex_it.first;
- const std::vector<ApexFileRef>& apex_files = apex_it.second;
-
- if (apex_files.size() > 2 || apex_files.size() == 0) {
- LOG(FATAL) << "Unexpectedly found more than two versions or none for "
- "APEX package "
- << package_name;
- continue;
- }
- // The package must have a pre-installed version before we consider it for
- // activation
- if (!instance.HasPreInstalledVersion(package_name)) {
- LOG(INFO) << "Package " << package_name << " is not pre-installed";
- continue;
- }
-
- if (apex_files.size() == 1) {
- LOG(DEBUG) << "Selecting the only APEX: " << package_name << " "
- << apex_files[0].get().GetPath();
- activation_list.emplace_back(apex_files[0]);
- continue;
- }
-
- // TODO(b/179497746): Now that we are dealing with list of reference, this
- // selection process can be simplified by sorting the vector.
-
- // Given an APEX A and the version of the other APEX B, should we activate
- // it?
- auto select_apex = [&instance, &activation_list](
- const ApexFileRef& a_ref,
- const int version_b) mutable {
- const ApexFile& a = a_ref.get();
- // If A has higher version than B, then it should be activated
- const bool higher_version = a.GetManifest().version() > version_b;
- // If A has same version as B, then data version should get activated
- const bool same_version_priority_to_data =
- a.GetManifest().version() == version_b &&
- !instance.IsPreInstalledApex(a);
-
- // APEX that provides shared library are special:
- // - if preinstalled version is lower than data version, both versions
- // are activated.
- // - if preinstalled version is equal to data version, data version only
- // is activated.
- // - if preinstalled version is higher than data version, preinstalled
- // version only is activated.
- const bool provides_shared_apex_libs =
- a.GetManifest().providesharedapexlibs();
- bool activate = false;
- if (provides_shared_apex_libs) {
- // preinstalled version gets activated in all cases except when same
- // version as data.
- if (instance.IsPreInstalledApex(a) &&
- (a.GetManifest().version() != version_b)) {
- LOG(DEBUG) << "Activating preinstalled shared libs APEX: "
- << a.GetManifest().name() << " " << a.GetPath();
- activate = true;
- }
- // data version gets activated in all cases except when its version
- // is lower than preinstalled version.
- if (!instance.IsPreInstalledApex(a) &&
- (a.GetManifest().version() >= version_b)) {
- LOG(DEBUG) << "Activating shared libs APEX: "
- << a.GetManifest().name() << " " << a.GetPath();
- activate = true;
- }
- } else if (higher_version || same_version_priority_to_data) {
- LOG(DEBUG) << "Selecting between two APEX: " << a.GetManifest().name()
- << " " << a.GetPath();
- activate = true;
- }
- if (activate) {
- activation_list.emplace_back(a_ref);
- }
- };
- const int version_0 = apex_files[0].get().GetManifest().version();
- const int version_1 = apex_files[1].get().GetManifest().version();
- select_apex(apex_files[0].get(), version_1);
- select_apex(apex_files[1].get(), version_0);
- }
- return activation_list;
+ gMountedApexes.PopulateFromMounts();
}
-namespace {
-
-Result<ApexFile> OpenAndValidateDecompressedApex(const ApexFile& capex,
- const std::string& apex_path) {
- auto apex = ApexFile::Open(apex_path);
- if (!apex.ok()) {
- return Error() << "Failed to open decompressed APEX: " << apex.error();
- }
- auto result = ValidateDecompressedApex(capex, *apex);
- if (!result.ok()) {
- return result.error();
- }
- return std::move(*apex);
-}
-
-// Process a single compressed APEX. Returns the decompressed APEX if
-// successful.
-Result<ApexFile> ProcessCompressedApex(const ApexFile& capex,
- bool is_ota_chroot) {
- LOG(INFO) << "Processing compressed APEX " << capex.GetPath();
- const auto decompressed_apex_path =
- StringPrintf("%s/%s%s", gConfig->decompression_dir,
- GetPackageId(capex.GetManifest()).c_str(),
- kDecompressedApexPackageSuffix);
- // Check if decompressed APEX already exist
- auto decompressed_path_exists = PathExists(decompressed_apex_path);
- if (decompressed_path_exists.ok() && *decompressed_path_exists) {
- // Check if existing decompressed APEX is valid
- auto result =
- OpenAndValidateDecompressedApex(capex, decompressed_apex_path);
- if (result.ok()) {
- LOG(INFO) << "Skipping decompression for " << capex.GetPath();
- return result;
- }
- // Do not delete existing decompressed APEX when is_ota_chroot is true
- if (!is_ota_chroot) {
- // Existing decompressed APEX is not valid. We will have to redecompress
- LOG(WARNING) << "Existing decompressed APEX is invalid: "
- << result.error();
- RemoveFileIfExists(decompressed_apex_path);
- }
- }
-
- // We can also reuse existing OTA APEX, depending on situation
- auto ota_apex_path = StringPrintf("%s/%s%s", gConfig->decompression_dir,
- GetPackageId(capex.GetManifest()).c_str(),
- kOtaApexPackageSuffix);
- auto ota_path_exists = PathExists(ota_apex_path);
- if (ota_path_exists.ok() && *ota_path_exists) {
- if (is_ota_chroot) {
- // During ota_chroot, we try to reuse ota APEX as is
- auto result = OpenAndValidateDecompressedApex(capex, ota_apex_path);
- if (result.ok()) {
- LOG(INFO) << "Skipping decompression for " << ota_apex_path;
- return result;
- }
- // Existing ota_apex is not valid. We will have to decompress
- LOG(WARNING) << "Existing decompressed OTA APEX is invalid: "
- << result.error();
- RemoveFileIfExists(ota_apex_path);
- } else {
- // During boot, we can avoid decompression by renaming OTA apex
- // to expected decompressed_apex path
-
- // Check if ota_apex APEX is valid
- auto result = OpenAndValidateDecompressedApex(capex, ota_apex_path);
- if (result.ok()) {
- // ota_apex matches with capex. Slot has been switched.
-
- // Rename ota_apex to expected decompressed_apex path
- if (rename(ota_apex_path.c_str(), decompressed_apex_path.c_str()) ==
- 0) {
- // Check if renamed decompressed APEX is valid
- result =
- OpenAndValidateDecompressedApex(capex, decompressed_apex_path);
- if (result.ok()) {
- LOG(INFO) << "Renamed " << ota_apex_path << " to "
- << decompressed_apex_path;
- return result;
- }
- // Renamed ota_apex is not valid. We will have to decompress
- LOG(WARNING) << "Renamed decompressed APEX from " << ota_apex_path
- << " to " << decompressed_apex_path
- << " is invalid: " << result.error();
- RemoveFileIfExists(decompressed_apex_path);
- } else {
- PLOG(ERROR) << "Failed to rename file " << ota_apex_path;
- }
- }
- }
- }
-
- // There was no way to avoid decompression
-
- // Clean up reserved space before decompressing capex
- if (auto ret = DeleteDirContent(gConfig->ota_reserved_dir); !ret.ok()) {
- LOG(ERROR) << "Failed to clean up reserved space: " << ret.error();
- }
-
- auto decompression_dest =
- is_ota_chroot ? ota_apex_path : decompressed_apex_path;
- auto scope_guard = android::base::make_scope_guard(
- [&]() { RemoveFileIfExists(decompression_dest); });
-
- auto decompression_result = capex.Decompress(decompression_dest);
- if (!decompression_result.ok()) {
- return Error() << "Failed to decompress : " << capex.GetPath().c_str()
- << " " << decompression_result.error();
- }
-
- // Fix label of decompressed file
- auto restore = RestoreconPath(decompression_dest);
- if (!restore.ok()) {
- return restore.error();
- }
-
- // Validate the newly decompressed APEX
- auto return_apex = OpenAndValidateDecompressedApex(capex, decompression_dest);
- if (!return_apex.ok()) {
- return Error() << "Failed to decompress CAPEX: " << return_apex.error();
- }
-
- /// Release compressed blocks in case decompression_dest is on f2fs-compressed
- // filesystem.
- ReleaseF2fsCompressedBlocks(decompression_dest);
-
- scope_guard.Disable();
- return return_apex;
-}
-} // namespace
-
-/**
- * For each compressed APEX, decompress it to kApexDecompressedDir
- * and return the decompressed APEX.
- *
- * Returns list of decompressed APEX.
- */
-std::vector<ApexFile> ProcessCompressedApex(
- const std::vector<ApexFileRef>& compressed_apex, bool is_ota_chroot) {
- LOG(INFO) << "Processing compressed APEX";
-
- std::vector<ApexFile> decompressed_apex_list;
- for (const ApexFile& capex : compressed_apex) {
- if (!capex.IsCompressed()) {
- continue;
- }
-
- auto decompressed_apex = ProcessCompressedApex(capex, is_ota_chroot);
- if (decompressed_apex.ok()) {
- decompressed_apex_list.emplace_back(std::move(*decompressed_apex));
- continue;
- }
- LOG(ERROR) << "Failed to process compressed APEX: "
- << decompressed_apex.error();
- }
- return std::move(decompressed_apex_list);
-}
-
-Result<void> ValidateDecompressedApex(const ApexFile& capex,
- const ApexFile& apex) {
- // Decompressed APEX must have same public key as CAPEX
- if (capex.GetBundledPublicKey() != apex.GetBundledPublicKey()) {
- return Error()
- << "Public key of compressed APEX is different than original "
- << "APEX for " << apex.GetPath();
- }
- // Decompressed APEX must have same version as CAPEX
- if (capex.GetManifest().version() != apex.GetManifest().version()) {
- return Error()
- << "Compressed APEX has different version than decompressed APEX "
- << apex.GetPath();
- }
- // Decompressed APEX must have same root digest as what is stored in CAPEX
- auto apex_verity = apex.VerifyApexVerity(apex.GetBundledPublicKey());
- if (!apex_verity.ok() ||
- capex.GetManifest().capexmetadata().originalapexdigest() !=
- apex_verity->root_digest) {
- return Error() << "Root digest of " << apex.GetPath()
- << " does not match with"
- << " expected root digest in " << capex.GetPath();
- }
- return {};
-}
-
-void OnStart() {
+void onStart() {
LOG(INFO) << "Marking APEXd as starting";
- auto time_started = boot_clock::now();
- if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusStarting)) {
- PLOG(ERROR) << "Failed to set " << gConfig->apex_status_sysprop << " to "
+ if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusStarting)) {
+ PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
<< kApexStatusStarting;
}
@@ -2771,134 +1889,98 @@ void OnStart() {
LOG(INFO) << "Exceeded number of session retries ("
<< kNumRetriesWhenCheckpointingEnabled
<< "). Starting a revert";
- RevertActiveSessions("", "");
+ revertActiveSessions("");
}
}
- // Create directories for APEX shared libraries.
- auto sharedlibs_apex_dir = CreateSharedLibsApexDir();
- if (!sharedlibs_apex_dir.ok()) {
- LOG(ERROR) << sharedlibs_apex_dir.error();
- }
-
- // If there is any new apex to be installed on /data/app-staging, hardlink
- // them to /data/apex/active first.
- ScanStagedSessionsDirAndStage();
- if (auto status = ApexFileRepository::GetInstance().AddDataApex(
- gConfig->active_apex_data_dir);
- !status.ok()) {
- LOG(ERROR) << "Failed to collect data APEX files : " << status.error();
- }
-
- auto status = ResumeRevertIfNeeded();
+ // Activate APEXes from /data/apex. If one in the directory is newer than the
+ // system one, the new one will eclipse the old one.
+ scanStagedSessionsDirAndStage();
+ auto status = resumeRevertIfNeeded();
if (!status.ok()) {
LOG(ERROR) << "Failed to resume revert : " << status.error();
}
- // Group every ApexFile on device by name
- const auto& instance = ApexFileRepository::GetInstance();
- const auto& all_apex = instance.AllApexFilesByName();
- // There can be multiple APEX packages with package name X. Determine which
- // one to activate.
- auto activation_list = SelectApexForActivation(all_apex, instance);
-
- // Process compressed APEX, if any
- std::vector<ApexFileRef> compressed_apex;
- for (auto it = activation_list.begin(); it != activation_list.end();) {
- if (it->get().IsCompressed()) {
- compressed_apex.emplace_back(*it);
- it = activation_list.erase(it);
- } else {
- it++;
+ std::vector<ApexFile> data_apex;
+ if (auto scan = ScanApexFiles(kActiveApexPackagesDataDir); !scan.ok()) {
+ LOG(ERROR) << "Failed to scan packages from " << kActiveApexPackagesDataDir
+ << " : " << scan.error();
+ if (auto revert = revertActiveSessionsAndReboot(""); !revert.ok()) {
+ LOG(ERROR) << "Failed to revert : " << revert.error();
}
+ } else {
+ auto filter_fn = [](const ApexFile& apex) {
+ if (!ShouldActivateApexOnData(apex)) {
+ LOG(WARNING) << "Skipping " << apex.GetPath();
+ return false;
+ }
+ return true;
+ };
+ std::copy_if(std::make_move_iterator(scan->begin()),
+ std::make_move_iterator(scan->end()),
+ std::back_inserter(data_apex), filter_fn);
}
- std::vector<ApexFile> decompressed_apex;
- if (!compressed_apex.empty()) {
- decompressed_apex =
- ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ false);
- for (const ApexFile& apex_file : decompressed_apex) {
- activation_list.emplace_back(std::cref(apex_file));
+
+ if (auto ret = ActivateApexPackages(data_apex); !ret.ok()) {
+ LOG(ERROR) << "Failed to activate packages from "
+ << kActiveApexPackagesDataDir << " : " << status.error();
+ Result<void> revert_status = revertActiveSessionsAndReboot("");
+ if (!revert_status.ok()) {
+ // TODO: should we kill apexd in this case?
+ LOG(ERROR) << "Failed to revert : " << revert_status.error()
+ << kActiveApexPackagesDataDir << " : " << ret.error();
}
}
- int data_apex_cnt = std::count_if(
- activation_list.begin(), activation_list.end(), [](const auto& a) {
- return !ApexFileRepository::GetInstance().IsPreInstalledApex(a.get());
- });
- if (data_apex_cnt > 0) {
- Result<void> pre_allocate = loop::PreAllocateLoopDevices(data_apex_cnt);
- if (!pre_allocate.ok()) {
- LOG(ERROR) << "Failed to pre-allocate loop devices : "
- << pre_allocate.error();
- }
- }
-
- // TODO(b/179248390): activate parallelly if possible
- auto activate_status =
- ActivateApexPackages(activation_list, /* is_ota_chroot= */ false);
- if (!activate_status.ok()) {
- std::string error_message =
- StringPrintf("Failed to activate packages: %s",
- activate_status.error().message().c_str());
- LOG(ERROR) << error_message;
- Result<void> revert_status =
- RevertActiveSessionsAndReboot("", error_message);
- if (!revert_status.ok()) {
- LOG(ERROR) << "Failed to revert : " << revert_status.error();
+ // Now also scan and activate APEXes from pre-installed directories.
+ for (const auto& dir : kApexPackageBuiltinDirs) {
+ auto scan_status = ScanApexFiles(dir.c_str());
+ if (!scan_status.ok()) {
+ LOG(ERROR) << "Failed to scan APEX packages from " << dir << " : "
+ << scan_status.error();
+ if (auto revert = revertActiveSessionsAndReboot(""); !revert.ok()) {
+ LOG(ERROR) << "Failed to revert : " << revert.error();
+ }
}
- auto retry_status = ActivateMissingApexes(activation_list,
- /* is_ota_chroot= */ false);
- if (!retry_status.ok()) {
- LOG(ERROR) << retry_status.error();
+ if (auto activate = ActivateApexPackages(*scan_status); !activate.ok()) {
+ // This should never happen. Like **really** never.
+ // TODO: should we kill apexd in this case?
+ LOG(ERROR) << "Failed to activate packages from " << dir << " : "
+ << activate.error();
}
}
// Now that APEXes are mounted, snapshot or restore DE_sys data.
- SnapshotOrRestoreDeSysData();
-
- auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
- boot_clock::now() - time_started).count();
- LOG(INFO) << "OnStart done, duration=" << time_elapsed;
+ snapshotOrRestoreDeSysData();
}
-void OnAllPackagesActivated(bool is_bootstrap) {
- auto result = EmitApexInfoList(is_bootstrap);
- if (!result.ok()) {
- LOG(ERROR) << "cannot emit apex info list: " << result.error();
- }
-
- // Because apexd in bootstrap mode runs in blocking mode
- // we don't have to set as activated.
- if (is_bootstrap) {
- return;
- }
-
+void onAllPackagesActivated() {
// Set a system property to let other components know that APEXs are
// activated, but are not yet ready to be used. init is expected to wait
// for this status before performing configuration based on activated
// apexes. Other components that need to use APEXs should wait for the
// ready state instead.
LOG(INFO) << "Marking APEXd as activated";
- if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusActivated)) {
- PLOG(ERROR) << "Failed to set " << gConfig->apex_status_sysprop << " to "
+ if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusActivated)) {
+ PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
<< kApexStatusActivated;
}
}
-void OnAllPackagesReady() {
+void onAllPackagesReady() {
// Set a system property to let other components know that APEXs are
// correctly mounted and ready to be used. Before using any file from APEXs,
// they can query this system property to ensure that they are okay to
// access. Or they may have a on-property trigger to delay a task until
// APEXs become ready.
LOG(INFO) << "Marking APEXd as ready";
- if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusReady)) {
- PLOG(ERROR) << "Failed to set " << gConfig->apex_status_sysprop << " to "
+ if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusReady)) {
+ PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
<< kApexStatusReady;
}
}
-Result<std::vector<ApexFile>> SubmitStagedSession(
+Result<std::vector<ApexFile>> submitStagedSession(
const int session_id, const std::vector<int>& child_session_ids,
const bool has_rollback_enabled, const bool is_rollback,
const int rollback_id) {
@@ -2922,13 +2004,8 @@ Result<std::vector<ApexFile>> SubmitStagedSession(
}
std::vector<ApexFile> ret;
- auto guard = android::base::make_scope_guard([&ret]() {
- for (const auto& apex : ret) {
- apexd_private::UnmountTempMount(apex);
- }
- });
for (int id_to_scan : ids_to_scan) {
- auto verified = VerifySessionDir(id_to_scan);
+ auto verified = verifySessionDir(id_to_scan);
if (!verified.ok()) {
return verified.error();
}
@@ -2962,15 +2039,10 @@ Result<std::vector<ApexFile>> SubmitStagedSession(
return commit_status.error();
}
- for (const auto& apex : ret) {
- // Release compressed blocks in case /data is f2fs-compressed filesystem.
- ReleaseF2fsCompressedBlocks(apex.GetPath());
- }
-
return ret;
}
-Result<void> MarkStagedSessionReady(const int session_id) {
+Result<void> markStagedSessionReady(const int session_id) {
auto session = ApexSession::GetSession(session_id);
if (!session.ok()) {
return session.error();
@@ -2989,7 +2061,7 @@ Result<void> MarkStagedSessionReady(const int session_id) {
<< ". Cannot mark it as ready.";
}
-Result<void> MarkStagedSessionSuccessful(const int session_id) {
+Result<void> markStagedSessionSuccessful(const int session_id) {
auto session = ApexSession::GetSession(session_id);
if (!session.ok()) {
return session.error();
@@ -3005,7 +2077,7 @@ Result<void> MarkStagedSessionSuccessful(const int session_id) {
<< " as successful : " << cleanup_status.error();
}
if (session->IsRollback() && !gSupportsFsCheckpoints) {
- DeleteDePreRestoreSnapshots(*session);
+ deleteDePreRestoreSnapshots(*session);
}
return session->UpdateStateAndCommit(SessionState::SUCCESS);
} else {
@@ -3013,63 +2085,86 @@ Result<void> MarkStagedSessionSuccessful(const int session_id) {
}
}
-// Removes APEXes on /data that have not been activated
-void RemoveInactiveDataApex() {
- std::vector<std::string> all_apex_files;
- Result<std::vector<std::string>> active_apex =
- FindFilesBySuffix(gConfig->active_apex_data_dir, {kApexPackageSuffix});
- if (!active_apex.ok()) {
- LOG(ERROR) << "Failed to scan " << gConfig->active_apex_data_dir << " : "
- << active_apex.error();
- } else {
- all_apex_files.insert(all_apex_files.end(),
- std::make_move_iterator(active_apex->begin()),
- std::make_move_iterator(active_apex->end()));
- }
- Result<std::vector<std::string>> decompressed_apex = FindFilesBySuffix(
- gConfig->decompression_dir, {kDecompressedApexPackageSuffix});
- if (!decompressed_apex.ok()) {
- LOG(ERROR) << "Failed to scan " << gConfig->decompression_dir << " : "
- << decompressed_apex.error();
- } else {
- all_apex_files.insert(all_apex_files.end(),
- std::make_move_iterator(decompressed_apex->begin()),
- std::make_move_iterator(decompressed_apex->end()));
+namespace {
+
+// Find dangling mounts and unmount them.
+// If one is on /data/apex/active, remove it.
+void UnmountDanglingMounts() {
+ std::multimap<std::string, MountedApexData> danglings;
+ gMountedApexes.ForallMountedApexes([&](const std::string& package,
+ const MountedApexData& data,
+ bool latest) {
+ if (!latest) {
+ danglings.insert({package, data});
+ }
+ });
+
+ for (const auto& [package, data] : danglings) {
+ const std::string& path = data.full_path;
+ LOG(VERBOSE) << "Unmounting " << data.mount_point;
+ gMountedApexes.RemoveMountedApex(package, path);
+ if (auto st = Unmount(data); !st.ok()) {
+ LOG(ERROR) << st.error();
+ }
+ if (StartsWith(path, kActiveApexPackagesDataDir)) {
+ LOG(VERBOSE) << "Deleting old APEX " << path;
+ if (unlink(path.c_str()) != 0) {
+ PLOG(ERROR) << "Failed to delete " << path;
+ }
+ }
}
- for (const auto& path : all_apex_files) {
- if (!apexd_private::IsMounted(path)) {
- LOG(INFO) << "Removing inactive data APEX " << path;
+ RemoveObsoleteHashTrees();
+}
+
+// Removes APEXes on /data that don't have corresponding pre-installed version
+// or that are corrupt
+void RemoveOrphanedApexes() {
+ auto data_apexes = FindApexFilesByName(kActiveApexPackagesDataDir);
+ if (!data_apexes.ok()) {
+ LOG(ERROR) << "Failed to scan " << kActiveApexPackagesDataDir << " : "
+ << data_apexes.error();
+ return;
+ }
+ for (const auto& path : *data_apexes) {
+ auto apex = ApexFile::Open(path);
+ if (!apex.ok()) {
+ LOG(DEBUG) << "Failed to open APEX " << path << " : " << apex.error();
+ // before removing, double-check if the path is active or not
+ // just in case ApexFile::Open() fails with valid APEX
+ if (!apexd_private::IsMounted(path)) {
+ LOG(DEBUG) << "Removing corrupt APEX " << path;
+ if (unlink(path.c_str()) != 0) {
+ PLOG(ERROR) << "Failed to unlink " << path;
+ }
+ }
+ continue;
+ }
+ if (!ShouldActivateApexOnData(*apex)) {
+ LOG(DEBUG) << "Removing orphaned APEX " << path;
if (unlink(path.c_str()) != 0) {
- PLOG(ERROR) << "Failed to unlink inactive data APEX " << path;
+ PLOG(ERROR) << "Failed to unlink " << path;
}
}
}
}
-void BootCompletedCleanup() {
- RemoveInactiveDataApex();
- ApexSession::DeleteFinalizedSessions();
+} // namespace
+
+void bootCompletedCleanup() {
+ UnmountDanglingMounts();
+ RemoveOrphanedApexes();
}
-int UnmountAll() {
- gMountedApexes.PopulateFromMounts(gConfig->active_apex_data_dir,
- gConfig->decompression_dir,
- gConfig->apex_hash_tree_dir);
+int unmountAll() {
+ gMountedApexes.PopulateFromMounts();
int ret = 0;
gMountedApexes.ForallMountedApexes([&](const std::string& /*package*/,
const MountedApexData& data,
bool latest) {
LOG(INFO) << "Unmounting " << data.full_path << " mounted on "
<< data.mount_point;
- auto apex = ApexFile::Open(data.full_path);
- if (!apex.ok()) {
- LOG(ERROR) << "Failed to open " << data.full_path << " : "
- << apex.error();
- ret = 1;
- return;
- }
- if (latest && !apex->GetManifest().providesharedapexlibs()) {
+ if (latest) {
auto pos = data.mount_point.find('@');
CHECK(pos != std::string::npos);
std::string bind_mount = data.mount_point.substr(0, pos);
@@ -3078,7 +2173,7 @@ int UnmountAll() {
ret = 1;
}
}
- if (auto status = Unmount(data, /* deferred= */ false); !status.ok()) {
+ if (auto status = Unmount(data); !status.ok()) {
LOG(ERROR) << "Failed to unmount " << data.mount_point << " : "
<< status.error();
ret = 1;
@@ -3087,7 +2182,12 @@ int UnmountAll() {
return ret;
}
-Result<void> RemountPackages() {
+bool isBooting() {
+ auto status = GetProperty(kApexStatusSysprop, "");
+ return status != kApexStatusReady && status != kApexStatusActivated;
+}
+
+Result<void> remountPackages() {
std::vector<std::string> apexes;
gMountedApexes.ForallMountedApexes([&apexes](const std::string& /*package*/,
const MountedApexData& data,
@@ -3101,7 +2201,7 @@ Result<void> RemountPackages() {
for (const std::string& apex : apexes) {
// Since this is only used during development workflow, we are trying to
// remount as many apexes as possible instead of failing fast.
- if (auto ret = RemountApexFile(apex); !ret.ok()) {
+ if (auto ret = remountApexFile(apex); !ret) {
LOG(WARNING) << "Failed to remount " << apex << " : " << ret.error();
failed.emplace_back(apex);
}
@@ -3118,596 +2218,5 @@ Result<void> RemountPackages() {
return {};
}
-// Given a single new APEX incoming via OTA, should we allocate space for it?
-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.
- if (!instance.HasPreInstalledVersion(new_apex_name)) {
- // We are introducing a new APEX that doesn't exist at all
- return true;
- }
-
- // Check if there is a data apex
- if (!instance.HasDataVersion(new_apex_name)) {
- // Data apex doesn't exist. Compare against pre-installed APEX
- auto pre_installed_apex = instance.GetPreInstalledApex(new_apex_name);
- if (!pre_installed_apex.get().IsCompressed()) {
- // Compressing an existing uncompressed system APEX.
- return true;
- }
- // Since there is no data apex, it means device is using the compressed
- // pre-installed version. If new apex has higher version, we are upgrading
- // the pre-install version and if new apex has lower version, we are
- // downgrading it. So the current decompressed apex should be replaced
- // with the new decompressed apex to reflect that.
- const int64_t pre_installed_version =
- instance.GetPreInstalledApex(new_apex_name)
- .get()
- .GetManifest()
- .version();
- return new_apex_version != pre_installed_version;
- }
-
- // From here on, data apex exists. So we should compare directly against data
- // apex.
- auto data_apex = instance.GetDataApex(new_apex_name);
- // Compare the data apex version with new apex
- const int64_t data_version = data_apex.get().GetManifest().version();
- // We only decompress the new_apex if it has higher version than data apex.
- return new_apex_version > data_version;
-}
-
-void CollectApexInfoList(std::ostream& os,
- const std::vector<ApexFile>& active_apexs,
- const std::vector<ApexFile>& inactive_apexs) {
- std::vector<com::android::apex::ApexInfo> apex_infos;
-
- auto convert_to_autogen = [&apex_infos](const ApexFile& apex,
- bool is_active) {
- auto& instance = ApexFileRepository::GetInstance();
-
- auto preinstalled_path =
- instance.GetPreinstalledPath(apex.GetManifest().name());
- std::optional<std::string> preinstalled_module_path;
- if (preinstalled_path.ok()) {
- preinstalled_module_path = *preinstalled_path;
- }
-
- 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_infos.emplace_back(apex_info);
- };
- for (const auto& apex : active_apexs) {
- convert_to_autogen(apex, /* is_active= */ true);
- }
- for (const auto& apex : inactive_apexs) {
- convert_to_autogen(apex, /* is_active= */ false);
- }
- com::android::apex::ApexInfoList apex_info_list(apex_infos);
- com::android::apex::write(os, apex_info_list);
-}
-
-// Reserve |size| bytes in |dest_dir| by creating a zero-filled file.
-// Also, we always clean up ota_apex that has been processed as
-// part of pre-reboot decompression whenever we reserve space.
-Result<void> ReserveSpaceForCompressedApex(int64_t size,
- const std::string& dest_dir) {
- if (size < 0) {
- return Error() << "Cannot reserve negative byte of space";
- }
-
- // Since we are reserving space, then we must be preparing for a new OTA.
- // Clean up any processed ota_apex from previous OTA.
- auto ota_apex_files =
- FindFilesBySuffix(gConfig->decompression_dir, {kOtaApexPackageSuffix});
- if (!ota_apex_files.ok()) {
- return Error() << "Failed to clean up ota_apex: " << ota_apex_files.error();
- }
- for (const std::string& ota_apex : *ota_apex_files) {
- RemoveFileIfExists(ota_apex);
- }
-
- auto file_path = StringPrintf("%s/full.tmp", dest_dir.c_str());
- if (size == 0) {
- LOG(INFO) << "Cleaning up reserved space for compressed APEX";
- // Ota is being cancelled. Clean up reserved space
- RemoveFileIfExists(file_path);
- return {};
- }
-
- LOG(INFO) << "Reserving " << size << " bytes for compressed APEX";
- unique_fd dest_fd(
- open(file_path.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT, 0644));
- if (dest_fd.get() == -1) {
- return ErrnoError() << "Failed to open file for reservation "
- << file_path.c_str();
- }
-
- // Resize to required size
- std::error_code ec;
- std::filesystem::resize_file(file_path, size, ec);
- if (ec) {
- RemoveFileIfExists(file_path);
- return ErrnoError() << "Failed to resize file " << file_path.c_str()
- << " : " << ec.message();
- }
-
- return {};
-}
-
-int OnOtaChrootBootstrap() {
- auto& instance = ApexFileRepository::GetInstance();
- if (auto status = instance.AddPreInstalledApex(gConfig->apex_built_in_dirs);
- !status.ok()) {
- LOG(ERROR) << "Failed to scan pre-installed apexes from "
- << Join(gConfig->apex_built_in_dirs, ',');
- return 1;
- }
- if (auto status = instance.AddDataApex(gConfig->active_apex_data_dir);
- !status.ok()) {
- LOG(ERROR) << "Failed to scan upgraded apexes from "
- << gConfig->active_apex_data_dir;
- // Failing to scan upgraded apexes is not fatal, since we can still try to
- // run otapreopt using only pre-installed apexes. Worst case, apps will be
- // re-optimized on next boot.
- }
-
- // Create directories for APEX shared libraries.
- if (auto status = CreateSharedLibsApexDir(); !status.ok()) {
- LOG(ERROR) << "Failed to create /apex/sharedlibs : " << status.ok();
- return 1;
- }
-
- auto activation_list =
- SelectApexForActivation(instance.AllApexFilesByName(), instance);
-
- // TODO(b/179497746): This is the third time we are duplicating this code
- // block. This will be easier to dedup once we start opening ApexFiles via
- // ApexFileRepository. That way, ProcessCompressedApex can return list of
- // ApexFileRef, instead of ApexFile.
-
- // Process compressed APEX, if any
- std::vector<ApexFileRef> compressed_apex;
- for (auto it = activation_list.begin(); it != activation_list.end();) {
- if (it->get().IsCompressed()) {
- compressed_apex.emplace_back(*it);
- it = activation_list.erase(it);
- } else {
- it++;
- }
- }
- std::vector<ApexFile> decompressed_apex;
- if (!compressed_apex.empty()) {
- decompressed_apex =
- ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ true);
-
- for (const ApexFile& apex_file : decompressed_apex) {
- activation_list.emplace_back(std::cref(apex_file));
- }
- }
-
- 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,
- /* is_ota_chroot= */ true);
- if (!retry_status.ok()) {
- LOG(ERROR) << retry_status.error();
- }
- }
-
- // There are a bunch of places that are producing apex-info.xml file.
- // We should consolidate the logic in one function and make all other places
- // use it.
- auto active_apexes = GetActivePackages();
- std::vector<ApexFile> inactive_apexes = GetFactoryPackages();
- auto new_end = std::remove_if(
- inactive_apexes.begin(), inactive_apexes.end(),
- [&active_apexes](const ApexFile& apex) {
- return std::any_of(active_apexes.begin(), active_apexes.end(),
- [&apex](const ApexFile& active_apex) {
- return apex.GetPath() == active_apex.GetPath();
- });
- });
- inactive_apexes.erase(new_end, inactive_apexes.end());
- std::stringstream xml;
- CollectApexInfoList(xml, active_apexes, inactive_apexes);
- std::string file_name = StringPrintf("%s/%s", kApexRoot, kApexInfoList);
- unique_fd fd(TEMP_FAILURE_RETRY(
- open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
- if (fd.get() == -1) {
- PLOG(ERROR) << "Can't open " << file_name;
- return 1;
- }
-
- if (!android::base::WriteStringToFd(xml.str(), fd)) {
- PLOG(ERROR) << "Can't write to " << file_name;
- return 1;
- }
-
- fd.reset();
-
- if (auto status = RestoreconPath(file_name); !status.ok()) {
- LOG(ERROR) << "Failed to restorecon " << file_name << " : "
- << status.error();
- return 1;
- }
-
- return 0;
-}
-
-int OnOtaChrootBootstrapFlattenedApex() {
- LOG(INFO) << "OnOtaChrootBootstrapFlattenedApex";
-
- std::vector<com::android::apex::ApexInfo> apex_infos;
-
- for (const std::string& dir : gConfig->apex_built_in_dirs) {
- LOG(INFO) << "Scanning " << dir;
- auto dir_content = ReadDir(dir, [](const auto& entry) {
- std::error_code ec;
- return entry.is_directory(ec);
- });
-
- if (!dir_content.ok()) {
- LOG(ERROR) << "Failed to scan " << dir << " : " << dir_content.error();
- continue;
- }
-
- // Sort to make sure that /apex/apex-info-list.xml generation doesn't depend
- // on the unstable directory scan.
- std::vector<std::string> entries = std::move(*dir_content);
- std::sort(entries.begin(), entries.end());
-
- for (const std::string& apex_dir : entries) {
- std::string manifest_file = apex_dir + "/" + kManifestFilenamePb;
- if (access(manifest_file.c_str(), F_OK) != 0) {
- PLOG(ERROR) << "Failed to access " << manifest_file;
- continue;
- }
-
- auto manifest = ReadManifest(manifest_file);
- if (!manifest.ok()) {
- LOG(ERROR) << "Failed to read apex manifest from " << manifest_file
- << " : " << manifest.error();
- continue;
- }
-
- std::string mount_point = std::string(kApexRoot) + "/" + manifest->name();
- if (mkdir(mount_point.c_str(), 0755) != 0) {
- PLOG(ERROR) << "Failed to mkdir " << mount_point;
- continue;
- }
-
- LOG(INFO) << "Bind mounting " << apex_dir << " onto " << mount_point;
- if (mount(apex_dir.c_str(), mount_point.c_str(), nullptr, MS_BIND,
- nullptr) != 0) {
- PLOG(ERROR) << "Failed to bind mount " << apex_dir << " to "
- << mount_point;
- continue;
- }
-
- apex_infos.emplace_back(manifest->name(), /* modulePath= */ apex_dir,
- /* preinstalledModulePath= */ apex_dir,
- /* versionCode= */ manifest->version(),
- /* versionName= */ manifest->versionname(),
- /* isFactory= */ true, /* isActive= */ true,
- /* lastUpdateMillis= */ 0);
- }
- }
-
- std::string file_name = StringPrintf("%s/%s", kApexRoot, kApexInfoList);
- unique_fd fd(TEMP_FAILURE_RETRY(
- open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
- if (fd.get() == -1) {
- PLOG(ERROR) << "Can't open " << file_name;
- return 1;
- }
-
- std::ostringstream xml;
- com::android::apex::ApexInfoList apex_info_list(apex_infos);
- com::android::apex::write(xml, apex_info_list);
- if (!android::base::WriteStringToFd(xml.str(), fd)) {
- PLOG(ERROR) << "Can't write to " << file_name;
- return 1;
- }
- fd.reset();
-
- if (auto status = RestoreconPath(file_name); !status.ok()) {
- LOG(ERROR) << "Failed to restorecon " << file_name << " : "
- << status.error();
- return 1;
- }
-
- return 0;
-}
-
-android::apex::MountedApexDatabase& GetApexDatabaseForTesting() {
- return gMountedApexes;
-}
-
-// A version of apex verification that happens during non-staged APEX
-// installation.
-Result<void> VerifyPackageNonStagedInstall(const ApexFile& apex_file) {
- const auto& verify_package_boot_status = VerifyPackageBoot(apex_file);
- if (!verify_package_boot_status.ok()) {
- return verify_package_boot_status;
- }
-
- auto check_fn = [&apex_file](const std::string& mount_point) -> Result<void> {
- auto dirs = GetSubdirs(mount_point);
- if (!dirs.ok()) {
- return dirs.error();
- }
- if (std::find(dirs->begin(), dirs->end(), mount_point + "/app") !=
- dirs->end()) {
- return Error() << apex_file.GetPath() << " contains app inside";
- }
- if (std::find(dirs->begin(), dirs->end(), mount_point + "/priv-app") !=
- dirs->end()) {
- return Error() << apex_file.GetPath() << " contains priv-app inside";
- }
- return Result<void>{};
- };
- return RunVerifyFnInsideTempMount(apex_file, check_fn, true);
-}
-
-Result<void> CheckSupportsNonStagedInstall(const ApexFile& cur_apex,
- const ApexFile& new_apex) {
- const auto& cur_manifest = cur_apex.GetManifest();
- const auto& new_manifest = new_apex.GetManifest();
-
- if (!new_manifest.supportsrebootlessupdate()) {
- return Error() << new_apex.GetPath()
- << " does not support non-staged update";
- }
-
- // Check if update will impact linkerconfig.
-
- // Updates to shared libs APEXes must be done via staged install flow.
- if (new_manifest.providesharedapexlibs()) {
- return Error() << new_apex.GetPath() << " is a shared libs APEX";
- }
-
- // This APEX provides native libs to other parts of the platform. It can only
- // be updated via staged install flow.
- if (new_manifest.providenativelibs_size() > 0) {
- return Error() << new_apex.GetPath() << " provides native libs";
- }
-
- // This APEX requires libs provided by dynamic common library APEX, hence it
- // can only be installed using staged install flow.
- if (new_manifest.requiresharedapexlibs_size() > 0) {
- return Error() << new_apex.GetPath() << " requires shared apex libs";
- }
-
- // We don't allow non-staged updates of APEXES that have java libs inside.
- if (new_manifest.jnilibs_size() > 0) {
- return Error() << new_apex.GetPath() << " requires JNI libs";
- }
-
- // For requireNativeLibs bit, we only allow updates that don't change list of
- // required libs.
-
- std::vector<std::string> cur_required_libs(
- cur_manifest.requirenativelibs().begin(),
- cur_manifest.requirenativelibs().end());
- sort(cur_required_libs.begin(), cur_required_libs.end());
-
- std::vector<std::string> new_required_libs(
- new_manifest.requirenativelibs().begin(),
- new_manifest.requirenativelibs().end());
- sort(new_required_libs.begin(), new_required_libs.end());
-
- if (cur_required_libs != new_required_libs) {
- return Error() << "Set of native libs required by " << new_apex.GetPath()
- << " differs from the one required by the currently active "
- << cur_apex.GetPath();
- }
-
- auto expected_public_key =
- ApexFileRepository::GetInstance().GetPublicKey(new_manifest.name());
- if (!expected_public_key.ok()) {
- return expected_public_key.error();
- }
- auto verity_data = new_apex.VerifyApexVerity(*expected_public_key);
- if (!verity_data.ok()) {
- return verity_data.error();
- }
- // Supporting non-staged install of APEXes without a hashtree is additional
- // hassle, it's easier not to support it.
- if (verity_data->desc->tree_size == 0) {
- return Error() << new_apex.GetPath()
- << " does not have an embedded hash tree";
- }
- return {};
-}
-
-Result<size_t> ComputePackageIdMinor(const ApexFile& apex) {
- static constexpr size_t kMaxVerityDevicesPerApexName = 3u;
- DeviceMapper& dm = DeviceMapper::Instance();
- std::vector<DeviceMapper::DmBlockDevice> dm_devices;
- if (!dm.GetAvailableDevices(&dm_devices)) {
- return Error() << "Failed to list dm devices";
- }
- size_t devices = 0;
- size_t next_minor = 1;
- for (const auto& dm_device : dm_devices) {
- std::string_view dm_name(dm_device.name());
- // Format is <module_name>@<version_code>[_<minor>]
- if (!ConsumePrefix(&dm_name, apex.GetManifest().name())) {
- continue;
- }
- devices++;
- auto pos = dm_name.find_last_of('_');
- if (pos == std::string_view::npos) {
- continue;
- }
- size_t minor;
- if (!ParseUint(std::string(dm_name.substr(pos + 1)), &minor)) {
- return Error() << "Unexpected dm device name " << dm_device.name();
- }
- if (next_minor < minor + 1) {
- next_minor = minor + 1;
- }
- }
- if (devices > kMaxVerityDevicesPerApexName) {
- return Error() << "There are too many (" << devices
- << ") dm block devices associated with package "
- << apex.GetManifest().name();
- }
- while (true) {
- std::string target_file =
- StringPrintf("%s/%s_%zu.apex", gConfig->active_apex_data_dir,
- GetPackageId(apex.GetManifest()).c_str(), next_minor);
- if (access(target_file.c_str(), F_OK) == 0) {
- next_minor++;
- } else {
- break;
- }
- }
-
- return next_minor;
-}
-
-Result<void> UpdateApexInfoList() {
- std::vector<ApexFile> active(GetActivePackages());
- std::vector<ApexFile> inactive = CalculateInactivePackages(active);
-
- std::stringstream xml;
- CollectApexInfoList(xml, active, inactive);
-
- std::string name = StringPrintf("%s/.default-%s", kApexRoot, kApexInfoList);
- unique_fd fd(TEMP_FAILURE_RETRY(
- open(name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
- if (fd.get() == -1) {
- return ErrnoError() << "Can't open " << name;
- }
- if (!WriteStringToFd(xml.str(), fd)) {
- return ErrnoError() << "Failed to write to " << name;
- }
-
- return {};
-}
-
-Result<ApexFile> InstallPackage(const std::string& package_path) {
- LOG(INFO) << "Installing " << package_path;
- auto temp_apex = ApexFile::Open(package_path);
- if (!temp_apex.ok()) {
- return temp_apex.error();
- }
-
- const std::string& module_name = temp_apex->GetManifest().name();
- // Don't allow non-staged update if there are no active versions of this APEX.
- auto cur_mounted_data = gMountedApexes.GetLatestMountedApex(module_name);
- if (!cur_mounted_data.has_value()) {
- return Error() << "No active version found for package " << module_name;
- }
-
- auto cur_apex = ApexFile::Open(cur_mounted_data->full_path);
- if (!cur_apex.ok()) {
- return cur_apex.error();
- }
-
- // Do a quick check if this APEX can be installed without a reboot.
- // Note that passing this check doesn't guarantee that APEX will be
- // successfully installed.
- if (auto r = CheckSupportsNonStagedInstall(*cur_apex, *temp_apex); !r.ok()) {
- return r.error();
- }
-
- // 1. Verify that APEX is correct. This is a heavy check that involves
- // mounting an APEX on a temporary mount point and reading the entire
- // dm-verity block device.
- if (auto verify = VerifyPackageNonStagedInstall(*temp_apex); !verify.ok()) {
- return verify.error();
- }
-
- // 2. Compute params for mounting new apex.
- auto new_id_minor = ComputePackageIdMinor(*temp_apex);
- if (!new_id_minor.ok()) {
- return new_id_minor.error();
- }
-
- std::string new_id = GetPackageId(temp_apex->GetManifest()) + "_" +
- std::to_string(*new_id_minor);
-
- // 2. Unmount currently active APEX.
- if (auto res = UnmountPackage(*cur_apex, /* allow_latest= */ true,
- /* deferred= */ true);
- !res.ok()) {
- return res.error();
- }
-
- // 3. Hard link to final destination.
- std::string target_file =
- StringPrintf("%s/%s.apex", gConfig->active_apex_data_dir, new_id.c_str());
-
- auto guard = android::base::make_scope_guard([&]() {
- if (unlink(target_file.c_str()) != 0 && errno != ENOENT) {
- PLOG(ERROR) << "Failed to unlink " << target_file;
- }
- // We can't really rely on the fact that dm-verity device backing up
- // 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);
- if (auto res = ActivatePackageImpl(*cur_apex, old_new_id); !res.ok()) {
- // At this point not much we can do... :(
- LOG(ERROR) << res.error();
- }
- });
-
- // At this point it should be safe to hard link |temp_apex| to
- // |params->target_file|. In case reboot happens during one of the stages
- // below, then on next boot apexd will pick up the new verified APEX.
- if (link(package_path.c_str(), target_file.c_str()) != 0) {
- return ErrnoError() << "Failed to link " << package_path << " to "
- << target_file;
- }
-
- auto new_apex = ApexFile::Open(target_file);
- if (!new_apex.ok()) {
- return new_apex.error();
- }
-
- // 4. And activate new one.
- if (auto res = ActivatePackageImpl(*new_apex, new_id); !res.ok()) {
- return res.error();
- }
-
- // Accept the install.
- guard.Disable();
-
- // 4. Now we can unlink old APEX if it's not pre-installed.
- if (!ApexFileRepository::GetInstance().IsPreInstalledApex(*cur_apex)) {
- if (unlink(cur_mounted_data->full_path.c_str()) != 0) {
- PLOG(ERROR) << "Failed to unlink " << cur_mounted_data->full_path;
- }
- }
-
- if (auto res = UpdateApexInfoList(); !res.ok()) {
- LOG(ERROR) << res.error();
- }
-
- // Release compressed blocks in case target_file is on f2fs-compressed
- // filesystem.
- ReleaseF2fsCompressedBlocks(target_file);
-
- return new_apex;
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd.h b/apexd/apexd.h
index 2465bde9..36f72beb 100644
--- a/apexd/apexd.h
+++ b/apexd/apexd.h
@@ -17,7 +17,6 @@
#ifndef ANDROID_APEXD_APEXD_H_
#define ANDROID_APEXD_APEXD_H_
-#include <ostream>
#include <string>
#include <vector>
@@ -25,177 +24,101 @@
#include <android-base/result.h>
#include "apex_constants.h"
-#include "apex_database.h"
#include "apex_file.h"
-#include "apex_file_repository.h"
-#include "apexd_session.h"
namespace android {
namespace apex {
-// A structure containing all the values that might need to be injected for
-// testing (e.g. apexd status property, etc.)
-//
-// Ideally we want to introduce Apexd class and use dependency injection for
-// such values, but that will require a sizeable refactoring. For the time being
-// this config should do the trick.
-struct ApexdConfig {
- const char* apex_status_sysprop;
- std::vector<std::string> apex_built_in_dirs;
- const char* active_apex_data_dir;
- const char* decompression_dir;
- const char* ota_reserved_dir;
- const char* apex_hash_tree_dir;
- const char* staged_session_dir;
-};
-
-static const ApexdConfig kDefaultConfig = {
- kApexStatusSysprop, kApexPackageBuiltinDirs, kActiveApexPackagesDataDir,
- kApexDecompressedDir, kOtaReservedDir, kApexHashTreeDir,
- kStagedSessionsDir,
-};
-
class CheckpointInterface;
-void SetConfig(const ApexdConfig& config);
-
-// Exposed only for testing.
-android::base::Result<void> Unmount(
- const MountedApexDatabase::MountedApexData& data, bool deferred);
+android::base::Result<void> resumeRevertIfNeeded();
-android::base::Result<void> ResumeRevertIfNeeded();
-
-android::base::Result<void> PreinstallPackages(
+// Keep it for now to make otapreopt_chroot keep happy.
+// TODO(b/137086602): remove this function.
+android::base::Result<void> scanPackagesDirAndActivate(
+ const char* apex_package_dir);
+void scanStagedSessionsDirAndStage();
+android::base::Result<void> preinstallPackages(
const std::vector<std::string>& paths) WARN_UNUSED;
-android::base::Result<void> PostinstallPackages(
+android::base::Result<void> postinstallPackages(
const std::vector<std::string>& paths) WARN_UNUSED;
-android::base::Result<void> StagePackages(
+android::base::Result<void> stagePackages(
const std::vector<std::string>& tmpPaths) WARN_UNUSED;
-android::base::Result<void> UnstagePackages(
+android::base::Result<void> unstagePackages(
const std::vector<std::string>& paths) WARN_UNUSED;
-android::base::Result<std::vector<ApexFile>> SubmitStagedSession(
+android::base::Result<std::vector<ApexFile>> submitStagedSession(
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<void> MarkStagedSessionReady(const int session_id)
+android::base::Result<void> markStagedSessionReady(const int session_id)
WARN_UNUSED;
-android::base::Result<void> MarkStagedSessionSuccessful(const int session_id)
+android::base::Result<void> markStagedSessionSuccessful(const int session_id)
WARN_UNUSED;
-// Only only of the parameters should be passed during revert
-android::base::Result<void> RevertActiveSessions(
- const std::string& crashing_native_process,
- const std::string& error_message);
-// Only only of the parameters should be passed during revert
-android::base::Result<void> RevertActiveSessionsAndReboot(
- const std::string& crashing_native_process,
- const std::string& error_message);
-
-android::base::Result<void> ActivatePackage(const std::string& full_path)
+android::base::Result<void> revertActiveSessions(
+ const std::string& crashing_native_process);
+android::base::Result<void> revertActiveSessionsAndReboot(
+ const std::string& crashing_native_process);
+
+android::base::Result<void> activatePackage(const std::string& full_path)
WARN_UNUSED;
-android::base::Result<void> DeactivatePackage(const std::string& full_path)
+android::base::Result<void> deactivatePackage(const std::string& full_path)
WARN_UNUSED;
-std::vector<ApexFile> GetActivePackages();
-android::base::Result<ApexFile> GetActivePackage(
+std::vector<ApexFile> getActivePackages();
+android::base::Result<ApexFile> getActivePackage(
const std::string& package_name);
-std::vector<ApexFile> GetFactoryPackages();
+std::vector<ApexFile> getFactoryPackages();
-android::base::Result<void> AbortStagedSession(const int session_id);
+android::base::Result<void> abortStagedSession(const int session_id);
+android::base::Result<void> abortActiveSession();
-android::base::Result<void> SnapshotCeData(const int user_id,
- const int rollback_id,
- const std::string& apex_name);
-android::base::Result<void> RestoreCeData(const int user_id,
+android::base::Result<ino_t> snapshotCeData(const int user_id,
+ const int rollback_id,
+ const std::string& apex_name);
+android::base::Result<void> restoreCeData(const int user_id,
const int rollback_id,
const std::string& apex_name);
-
-android::base::Result<void> DestroyDeSnapshots(const int rollback_id);
-android::base::Result<void> DestroyCeSnapshots(const int user_id,
- const int rollback_id);
-android::base::Result<void> DestroyCeSnapshotsNotSpecified(
+android::base::Result<void> destroyDeSnapshots(const int rollback_id);
+android::base::Result<void> destroyCeSnapshotsNotSpecified(
int user_id, const std::vector<int>& retain_rollback_ids);
-int OnBootstrap();
+int onBootstrap();
+// Small helper function to tell if device is currently booting.
+bool isBooting();
// Sets the values of gVoldService and gInFsCheckpointMode.
-void InitializeVold(CheckpointInterface* checkpoint_service);
+void initializeVold(CheckpointInterface* checkpoint_service);
// Initializes in-memory state (e.g. pre-installed data, activated apexes).
// Must be called first before calling any other boot sequence related function.
-void Initialize(CheckpointInterface* checkpoint_service);
-// Initializes data apex as in-memory state. Should be called only if we are
-// not booting, since initialization timing is different when booting
-void InitializeDataApex();
+void initialize(CheckpointInterface* checkpoint_service);
// Migrates sessions from /data/apex/session to /metadata/session.i
// Must only be called during boot (i.e apexd.status is not "ready" or
// "activated").
-android::base::Result<void> MigrateSessionsDirIfNeeded();
+android::base::Result<void> migrateSessionsDirIfNeeded();
// Apex activation logic. Scans staged apex sessions and activates apexes.
// Must only be called during boot (i.e apexd.status is not "ready" or
// "activated").
-void OnStart();
-// For every package X, there can be at most two APEX, pre-installed vs
-// installed on data. We decide which ones should be activated and return them
-// as a list
-std::vector<ApexFileRef> SelectApexForActivation(
- const std::unordered_map<std::string, std::vector<ApexFileRef>>& all_apex,
- const ApexFileRepository& instance);
-std::vector<ApexFile> ProcessCompressedApex(
- const std::vector<ApexFileRef>& compressed_apex, bool is_ota_chroot);
-// Validate |apex| is same as |capex|
-android::base::Result<void> ValidateDecompressedApex(const ApexFile& capex,
- const ApexFile& apex);
+void onStart();
// Notifies system that apexes are activated by setting apexd.status property to
// "activated".
// Must only be called during boot (i.e. apexd.status is not "ready" or
// "activated").
-void OnAllPackagesActivated(bool is_bootstrap);
+void onAllPackagesActivated();
// Notifies system that apexes are ready by setting apexd.status property to
// "ready".
// Must only be called during boot (i.e. apexd.status is not "ready" or
// "activated").
-void OnAllPackagesReady();
-void OnBootCompleted();
-// Exposed for testing
-void RemoveInactiveDataApex();
-void BootCompletedCleanup();
-int SnapshotOrRestoreDeUserData();
-
-int UnmountAll();
+void onAllPackagesReady();
+void bootCompletedCleanup();
+int snapshotOrRestoreDeUserData();
-android::base::Result<MountedApexDatabase::MountedApexData>
-GetTempMountedApexData(const std::string& package);
+int unmountAll();
// Optimistically tries to remount as many APEX packages as possible.
// For more documentation see corresponding binder call in IApexService.aidl.
-android::base::Result<void> RemountPackages();
-
-// Exposed for unit tests
-android::base::Result<bool> ShouldAllocateSpaceForDecompression(
- const std::string& new_apex_name, int64_t new_apex_version,
- const ApexFileRepository& instance);
-
-void CollectApexInfoList(std::ostream& os,
- const std::vector<ApexFile>& active_apexs,
- const std::vector<ApexFile>& inactive_apexs);
-
-// Reserve |size| bytes in |dest_dir| by creating a zero-filled file
-android::base::Result<void> ReserveSpaceForCompressedApex(
- int64_t size, const std::string& dest_dir);
-
-// Activates apexes in otapreot_chroot environment.
-// TODO(b/172911822): support compressed apexes.
-int OnOtaChrootBootstrap();
-
-// Activates flattened apexes in otapreopt_chroot environment.
-int OnOtaChrootBootstrapFlattenedApex();
-
-android::apex::MountedApexDatabase& GetApexDatabaseForTesting();
-
-// Performs a non-staged install of an APEX specified by |package_path|.
-// TODO(ioffe): add more documentation.
-android::base::Result<ApexFile> InstallPackage(const std::string& package_path);
+android::base::Result<void> remountPackages();
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_checkpoint.h b/apexd/apexd_checkpoint.h
index 2b4c3a12..7177c047 100644
--- a/apexd/apexd_checkpoint.h
+++ b/apexd/apexd_checkpoint.h
@@ -32,7 +32,7 @@ class CheckpointInterface {
virtual android::base::Result<bool> NeedsCheckpoint() = 0;
virtual android::base::Result<bool> NeedsRollback() = 0;
- virtual android::base::Result<void> StartCheckpoint(int32_t num_retries) = 0;
+ virtual android::base::Result<void> StartCheckpoint(int32_t numRetries) = 0;
virtual android::base::Result<void> AbortChanges(const std::string& msg,
bool retry) = 0;
diff --git a/apexd/apexd_checkpoint_vold.cpp b/apexd/apexd_checkpoint_vold.cpp
index 8a8d0ff1..ca29209d 100644
--- a/apexd/apexd_checkpoint_vold.cpp
+++ b/apexd/apexd_checkpoint_vold.cpp
@@ -31,11 +31,11 @@ namespace android {
namespace apex {
Result<VoldCheckpointInterface> VoldCheckpointInterface::Create() {
- auto vold_service =
+ auto voldService =
defaultServiceManager()->getService(android::String16("vold"));
- if (vold_service != nullptr) {
+ if (voldService != nullptr) {
return VoldCheckpointInterface(
- android::interface_cast<android::os::IVold>(vold_service));
+ android::interface_cast<android::os::IVold>(voldService));
}
return Errorf("Failed to retrieve vold service.");
}
@@ -91,10 +91,9 @@ Result<bool> VoldCheckpointInterface::NeedsRollback() {
return false;
}
-Result<void> VoldCheckpointInterface::StartCheckpoint(int32_t num_retries) {
+Result<void> VoldCheckpointInterface::StartCheckpoint(int32_t numRetries) {
if (supports_fs_checkpoints_) {
- android::binder::Status status =
- vold_service_->startCheckpoint(num_retries);
+ android::binder::Status status = vold_service_->startCheckpoint(numRetries);
if (!status.isOk()) {
return Error() << status.toString8().c_str();
}
diff --git a/apexd/apexd_checkpoint_vold.h b/apexd/apexd_checkpoint_vold.h
index f547532e..dbd190da 100644
--- a/apexd/apexd_checkpoint_vold.h
+++ b/apexd/apexd_checkpoint_vold.h
@@ -44,7 +44,7 @@ class VoldCheckpointInterface : public CheckpointInterface {
android::base::Result<void> StartCheckpoint(int32_t retry) override;
android::base::Result<void> AbortChanges(const std::string& msg,
- bool num_retries) override;
+ bool numRetries) override;
static android::base::Result<VoldCheckpointInterface> Create();
diff --git a/apexd/apexd_lifecycle.h b/apexd/apexd_lifecycle.h
deleted file mode 100644
index ecdef96e..00000000
--- a/apexd/apexd_lifecycle.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_APEXD_APEXD_LIFECYCLE_H_
-#define ANDROID_APEXD_APEXD_LIFECYCLE_H_
-
-#include <android-base/result.h>
-
-namespace android {
-namespace apex {
-
-class ApexdLifecycle {
- private:
- ApexdLifecycle(){};
- std::atomic<bool> boot_completed_;
-
- // Non-copyable && non-moveable.
- ApexdLifecycle(const ApexdLifecycle&) = delete;
- ApexdLifecycle& operator=(const ApexdLifecycle&) = delete;
- ApexdLifecycle& operator=(ApexdLifecycle&&) = delete;
-
- public:
- static ApexdLifecycle& GetInstance() {
- static ApexdLifecycle instance;
- return instance;
- }
- bool IsBooting();
- void MarkBootCompleted();
- void WaitForBootStatus(android::base::Result<void> (&rollback_fn)(
- const std::string&, const std::string&));
-};
-} // namespace apex
-} // namespace android
-
-#endif // ANDROID_APEXD_APEXD_LIFECYCLE_H
diff --git a/apexd/apexd_loop.cpp b/apexd/apexd_loop.cpp
index 08805eaf..568eb055 100644
--- a/apexd/apexd_loop.cpp
+++ b/apexd/apexd_loop.cpp
@@ -18,49 +18,29 @@
#include "apexd_loop.h"
-#include <mutex>
-
#include <dirent.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/statfs.h>
#include <sys/types.h>
#include <unistd.h>
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include "apexd_utils.h"
#include "string_log.h"
-using android::base::Basename;
-using android::base::ErrnoError;
using android::base::Error;
-using android::base::GetBoolProperty;
-using android::base::ParseUint;
using android::base::Result;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
-#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 {
namespace loop {
@@ -86,9 +66,13 @@ void LoopbackDeviceUniqueFd::MaybeCloseBad() {
}
}
-Result<void> ConfigureReadAhead(const std::string& device_path) {
- CHECK(StartsWith(device_path, "/dev/"));
- std::string device_name = Basename(device_path);
+Result<void> configureReadAhead(const std::string& device_path) {
+ auto pos = device_path.find("/dev/block/");
+ if (pos != 0) {
+ return Error() << "Device path does not start with /dev/block.";
+ }
+ pos = device_path.find_last_of('/');
+ std::string device_name = device_path.substr(pos + 1, std::string::npos);
std::string sysfs_device =
StringPrintf("/sys/block/%s/queue/read_ahead_kb", device_name.c_str());
@@ -106,10 +90,10 @@ Result<void> ConfigureReadAhead(const std::string& device_path) {
return {};
}
-Result<void> PreAllocateLoopDevices(size_t num) {
- Result<void> loop_ready = WaitForFile("/dev/loop-control", 20s);
- if (!loop_ready.ok()) {
- return loop_ready;
+Result<void> preAllocateLoopDevices(size_t num) {
+ Result<void> loopReady = WaitForFile("/dev/loop-control", 20s);
+ if (!loopReady.ok()) {
+ return loopReady;
}
unique_fd ctl_fd(
TEMP_FAILURE_RETRY(open("/dev/loop-control", O_RDWR | O_CLOEXEC)));
@@ -117,30 +101,13 @@ Result<void> PreAllocateLoopDevices(size_t num) {
return ErrnoError() << "Failed to open loop-control";
}
- bool found = false;
- size_t start_id = 0;
- constexpr const char* kLoopPrefix = "loop";
- WalkDir("/dev/block", [&](const std::filesystem::directory_entry& entry) {
- std::string devname = entry.path().filename().string();
- if (StartsWith(devname, kLoopPrefix)) {
- size_t id;
- auto parse_ok = ParseUint(
- devname.substr(std::char_traits<char>::length(kLoopPrefix)), &id);
- if (parse_ok && id > start_id) {
- start_id = id;
- found = true;
- }
- }
- });
- if (found) ++start_id;
-
// Assumption: loop device ID [0..num) is valid.
// This is because pre-allocation happens during bootstrap.
// Anyway Kernel pre-allocated loop devices
// as many as CONFIG_BLK_DEV_LOOP_MIN_COUNT,
// Within the amount of kernel-pre-allocation,
// LOOP_CTL_ADD will fail with EEXIST
- for (size_t id = start_id; id < num + start_id; ++id) {
+ for (size_t id = 0ul; id < num; ++id) {
int ret = ioctl(ctl_fd.get(), LOOP_CTL_ADD, id);
if (ret < 0 && errno != EEXIST) {
return ErrnoError() << "Failed LOOP_CTL_ADD";
@@ -153,30 +120,25 @@ Result<void> PreAllocateLoopDevices(size_t num) {
// just optimistally hope that they are all created when we actually
// access them for activating APEXes. If the dev nodes are not ready
// even then, we wait 50ms and warning message will be printed (see below
- // CreateLoopDevice()).
+ // createLoopDevice()).
LOG(INFO) << "Pre-allocated " << num << " loopback devices";
return {};
}
-Result<void> ConfigureLoopDevice(const int device_fd, const std::string& target,
- const int32_t image_offset,
- const size_t image_size) {
- static bool use_loop_configure;
- static std::once_flag once_flag;
- std::call_once(once_flag, [&]() {
- // LOOP_CONFIGURE is a new ioctl in Linux 5.8 (and backported in Android
- // common) that allows atomically configuring a loop device. It is a lot
- // faster than the traditional LOOP_SET_FD/LOOP_SET_STATUS64 combo, but
- // it may not be available on updating devices, so try once before
- // deciding.
- struct loop_config config;
- memset(&config, 0, sizeof(config));
- config.fd = -1;
- if (ioctl(device_fd, LOOP_CONFIGURE, &config) == -1 && errno == EBADF) {
- // If the IOCTL exists, it will fail with EBADF for the -1 fd
- use_loop_configure = true;
- }
- });
+Result<LoopbackDeviceUniqueFd> createLoopDevice(const std::string& target,
+ const int32_t imageOffset,
+ const size_t imageSize) {
+ unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
+ if (ctl_fd.get() == -1) {
+ return ErrnoError() << "Failed to open loop-control";
+ }
+
+ int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
+ if (num == -1) {
+ return ErrnoError() << "Failed LOOP_CTL_GET_FREE";
+ }
+
+ std::string device = StringPrintf("/dev/block/loop%d", num);
/*
* Using O_DIRECT will tell the kernel that we want to use Direct I/O
@@ -189,151 +151,74 @@ Result<void> ConfigureLoopDevice(const int device_fd, const std::string& target,
*/
unique_fd target_fd(open(target.c_str(), O_RDONLY | O_CLOEXEC | O_DIRECT));
if (target_fd.get() == -1) {
- struct statfs stbuf;
- int saved_errno = errno;
- // let's give another try with buffered I/O for EROFS and squashfs
- if (statfs(target.c_str(), &stbuf) != 0 ||
- (stbuf.f_type != EROFS_SUPER_MAGIC_V1 &&
- stbuf.f_type != SQUASHFS_MAGIC &&
- stbuf.f_type != OVERLAYFS_SUPER_MAGIC)) {
- return Error(saved_errno) << "Failed to open " << target;
- }
- LOG(WARNING) << "Fallback to buffered I/O for " << target;
- target_fd.reset(open(target.c_str(), O_RDONLY | O_CLOEXEC));
- if (target_fd.get() == -1) {
- return ErrnoError() << "Failed to open " << target;
- }
- }
-
- struct loop_info64 li;
- memset(&li, 0, sizeof(li));
- strlcpy((char*)li.lo_crypt_name, kApexLoopIdPrefix, LO_NAME_SIZE);
- li.lo_offset = image_offset;
- li.lo_sizelimit = image_size;
- // Automatically free loop device on last close.
- li.lo_flags |= LO_FLAGS_AUTOCLEAR;
-
- 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 (ioctl(device_fd, LOOP_CONFIGURE, &config) == -1) {
- return ErrnoError() << "Failed to LOOP_CONFIGURE";
- }
-
- return {};
- } else {
- if (ioctl(device_fd, LOOP_SET_FD, target_fd.get()) == -1) {
- return ErrnoError() << "Failed to LOOP_SET_FD";
- }
-
- if (ioctl(device_fd, LOOP_SET_STATUS64, &li) == -1) {
- return ErrnoError() << "Failed to LOOP_SET_STATUS64";
- }
-
- if (ioctl(device_fd, BLKFLSBUF, 0) == -1) {
- // This works around a kernel bug where the following happens.
- // 1) The device runs with a value of loop.max_part > 0
- // 2) As part of LOOP_SET_FD above, we do a partition scan, which loads
- // the first 2 pages of the underlying file into the buffer cache
- // 3) When we then change the offset with LOOP_SET_STATUS64, those pages
- // are not invalidated from the cache.
- // 4) When we try to mount an ext4 filesystem on the loop device, the ext4
- // code will try to find a superblock by reading 4k at offset 0; but,
- // because we still have the old pages at offset 0 lying in the cache,
- // those pages will be returned directly. However, those pages contain
- // the data at offset 0 in the underlying file, not at the offset that
- // we configured
- // 5) the ext4 driver fails to find a superblock in the (wrong) data, and
- // fails to mount the filesystem.
- //
- // To work around this, explicitly flush the block device, which will
- // flush the buffer cache and make sure we actually read the data at the
- // correct offset.
- return ErrnoError() << "Failed to flush buffers on the loop device";
- }
-
- // Direct-IO requires the loop device to have the same block size as the
- // underlying filesystem.
- if (ioctl(device_fd, LOOP_SET_BLOCK_SIZE, 4096) == -1) {
- PLOG(WARNING) << "Failed to LOOP_SET_BLOCK_SIZE";
- }
+ return ErrnoError() << "Failed to open " << target;
}
- return {};
-}
-
-Result<LoopbackDeviceUniqueFd> WaitForDevice(int num) {
- std::string opened_device;
- const std::vector<std::string> candidate_devices = {
- StringPrintf("/dev/block/loop%d", num),
- StringPrintf("/dev/loop%d", num),
- };
-
- // apexd-bootstrap runs in parallel with ueventd to optimize boot time. In
- // rare cases apexd would try attempt to mount an apex before ueventd created
- // 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) {
+ LoopbackDeviceUniqueFd device_fd;
+ {
+ // See comment on kLoopDeviceRetryAttempts.
+ unique_fd sysfs_fd;
+ for (size_t i = 0; i != kLoopDeviceRetryAttempts; ++i) {
sysfs_fd.reset(open(device.c_str(), O_RDWR | O_CLOEXEC));
if (sysfs_fd.get() != -1) {
- return LoopbackDeviceUniqueFd(std::move(sysfs_fd), device);
+ break;
}
+ PLOG(WARNING) << "Loopback device " << device
+ << " not ready. Waiting 50ms...";
+ usleep(50000);
}
- PLOG(WARNING) << "Loopback device " << num << " not ready. Waiting 50ms...";
- usleep(50000);
- if (!cold_boot_done) {
- // ueventd hasn't finished cold boot yet, keep trying.
- i = 0;
+ if (sysfs_fd.get() == -1) {
+ return ErrnoError() << "Failed to open " << device;
}
+ device_fd = LoopbackDeviceUniqueFd(std::move(sysfs_fd), device);
+ CHECK_NE(device_fd.get(), -1);
}
- return Error() << "Faled to open loopback device " << num;
-}
-
-Result<LoopbackDeviceUniqueFd> CreateLoopDevice(const std::string& target,
- 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 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";
- }
-
- Result<LoopbackDeviceUniqueFd> loop_device = WaitForDevice(num);
- if (!loop_device.ok()) {
- return loop_device.error();
+ if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {
+ return ErrnoError() << "Failed to LOOP_SET_FD";
}
- CHECK_NE(loop_device->device_fd.get(), -1);
- Result<void> configureStatus = ConfigureLoopDevice(
- loop_device->device_fd.get(), target, image_offset, image_size);
- if (!configureStatus.ok()) {
- return configureStatus.error();
- }
-
- Result<void> read_ahead_status = ConfigureReadAhead(loop_device->name);
- if (!read_ahead_status.ok()) {
- return read_ahead_status.error();
- }
-
- return loop_device;
+ struct loop_info64 li;
+ memset(&li, 0, sizeof(li));
+ strlcpy((char*)li.lo_crypt_name, kApexLoopIdPrefix, LO_NAME_SIZE);
+ li.lo_offset = imageOffset;
+ li.lo_sizelimit = imageSize;
+ if (ioctl(device_fd.get(), LOOP_SET_STATUS64, &li) == -1) {
+ return ErrnoError() << "Failed to LOOP_SET_STATUS64";
+ }
+
+ if (ioctl(device_fd.get(), BLKFLSBUF, 0) == -1) {
+ // This works around a kernel bug where the following happens.
+ // 1) The device runs with a value of loop.max_part > 0
+ // 2) As part of LOOP_SET_FD above, we do a partition scan, which loads
+ // the first 2 pages of the underlying file into the buffer cache
+ // 3) When we then change the offset with LOOP_SET_STATUS64, those pages
+ // are not invalidated from the cache.
+ // 4) When we try to mount an ext4 filesystem on the loop device, the ext4
+ // code will try to find a superblock by reading 4k at offset 0; but,
+ // because we still have the old pages at offset 0 lying in the cache,
+ // those pages will be returned directly. However, those pages contain
+ // the data at offset 0 in the underlying file, not at the offset that
+ // we configured
+ // 5) the ext4 driver fails to find a superblock in the (wrong) data, and
+ // fails to mount the filesystem.
+ //
+ // To work around this, explicitly flush the block device, which will flush
+ // the buffer cache and make sure we actually read the data at the correct
+ // offset.
+ return ErrnoError() << "Failed to flush buffers on the loop device";
+ }
+
+ // Direct-IO requires the loop device to have the same block size as the
+ // underlying filesystem.
+ if (ioctl(device_fd.get(), LOOP_SET_BLOCK_SIZE, 4096) == -1) {
+ PLOG(WARNING) << "Failed to LOOP_SET_BLOCK_SIZE";
+ }
+
+ Result<void> readAheadStatus = configureReadAhead(device);
+ if (!readAheadStatus.ok()) {
+ return readAheadStatus.error();
+ }
+ return device_fd;
}
void DestroyLoopDevice(const std::string& path, const DestroyLoopFn& extra) {
diff --git a/apexd/apexd_loop.h b/apexd/apexd_loop.h
index c727944a..8341675d 100644
--- a/apexd/apexd_loop.h
+++ b/apexd/apexd_loop.h
@@ -38,7 +38,7 @@ struct LoopbackDeviceUniqueFd {
: device_fd(std::move(fd)), name(name) {}
LoopbackDeviceUniqueFd(LoopbackDeviceUniqueFd&& fd) noexcept
- : device_fd(std::move(fd.device_fd)), name(std::move(fd.name)) {}
+ : device_fd(std::move(fd.device_fd)), name(fd.name) {}
LoopbackDeviceUniqueFd& operator=(LoopbackDeviceUniqueFd&& other) noexcept {
MaybeCloseBad();
device_fd = std::move(other.device_fd);
@@ -52,16 +52,16 @@ struct LoopbackDeviceUniqueFd {
void CloseGood() { device_fd.reset(-1); }
- int Get() { return device_fd.get(); }
+ int get() { return device_fd.get(); }
};
-android::base::Result<void> ConfigureReadAhead(const std::string& device_path);
+android::base::Result<void> configureReadAhead(const std::string& device_path);
-android::base::Result<void> PreAllocateLoopDevices(size_t num);
+android::base::Result<void> preAllocateLoopDevices(size_t num);
-android::base::Result<LoopbackDeviceUniqueFd> CreateLoopDevice(
- const std::string& target, const int32_t image_offset,
- const size_t image_size);
+android::base::Result<LoopbackDeviceUniqueFd> createLoopDevice(
+ const std::string& target, const int32_t imageOffset,
+ const size_t imageSize);
using DestroyLoopFn =
std::function<void(const std::string&, const std::string&)>;
diff --git a/apexd/apexd_main.cpp b/apexd/apexd_main.cpp
index 26d5732e..c60f4faf 100644
--- a/apexd/apexd_main.cpp
+++ b/apexd/apexd_main.cpp
@@ -17,15 +17,14 @@
#define LOG_TAG "apexd"
#include <strings.h>
-#include <sys/stat.h>
#include <ApexProperties.sysprop.h>
#include <android-base/logging.h>
#include "apexd.h"
#include "apexd_checkpoint_vold.h"
-#include "apexd_lifecycle.h"
#include "apexd_prepostinstall.h"
+#include "apexd_prop.h"
#include "apexservice.h"
#include <android-base/properties.h>
@@ -45,17 +44,12 @@ int HandleSubcommand(char** argv) {
if (strcmp("--bootstrap", argv[1]) == 0) {
LOG(INFO) << "Bootstrap subcommand detected";
- return android::apex::OnBootstrap();
+ return android::apex::onBootstrap();
}
if (strcmp("--unmount-all", argv[1]) == 0) {
LOG(INFO) << "Unmount all subcommand detected";
- return android::apex::UnmountAll();
- }
-
- if (strcmp("--otachroot-bootstrap", argv[1]) == 0) {
- LOG(INFO) << "OTA chroot bootstrap subcommand detected";
- return android::apex::OnOtaChrootBootstrap();
+ return android::apex::unmountAll();
}
if (strcmp("--snapshotde", argv[1]) == 0) {
@@ -68,16 +62,16 @@ int HandleSubcommand(char** argv) {
LOG(ERROR) << "Could not retrieve vold service: "
<< vold_service_st.error();
} else {
- android::apex::InitializeVold(&*vold_service_st);
+ android::apex::initializeVold(&*vold_service_st);
}
- int result = android::apex::SnapshotOrRestoreDeUserData();
+ int result = android::apex::snapshotOrRestoreDeUserData();
if (result == 0) {
// Notify other components (e.g. init) that all APEXs are ready to be used
// Note that it's important that the binder service is registered at this
// point, since other system services might depend on it.
- android::apex::OnAllPackagesReady();
+ android::apex::onAllPackagesReady();
}
return result;
}
@@ -104,40 +98,20 @@ void InstallSigtermSignalHandler() {
int main(int /*argc*/, char** argv) {
android::base::InitLogging(argv, &android::base::KernelLogger);
- // TODO(b/158468454): add a -v flag or an external setting to change severity.
- android::base::SetMinimumLogSeverity(android::base::INFO);
-
- // set umask to 022 so that files/dirs created are accessible to other
- // processes e.g.) apex-info-file.xml is supposed to be read by other
- // processes
- umask(022);
+ // TODO: add a -v flag or an external setting to change LogSeverity.
+ android::base::SetMinimumLogSeverity(android::base::VERBOSE);
InstallSigtermSignalHandler();
- android::apex::SetConfig(android::apex::kDefaultConfig);
-
- android::apex::ApexdLifecycle& lifecycle =
- android::apex::ApexdLifecycle::GetInstance();
- bool booting = lifecycle.IsBooting();
-
const bool has_subcommand = argv[1] != nullptr;
if (!android::sysprop::ApexProperties::updatable().value_or(false)) {
+ LOG(INFO) << "This device does not support updatable APEX. Exiting";
if (!has_subcommand) {
- if (!booting) {
- // We've finished booting, but for some reason somebody tried to start
- // apexd. Simply exit.
- return 0;
- }
-
- LOG(INFO) << "This device does not support updatable APEX. Exiting";
- // Mark apexd as activated so that init can proceed.
- android::apex::OnAllPackagesActivated(/*is_bootstrap=*/false);
+ // mark apexd as activated so that init can proceed
+ android::apex::onAllPackagesActivated();
} else if (strcmp("--snapshotde", argv[1]) == 0) {
- LOG(INFO) << "This device does not support updatable APEX. Exiting";
// mark apexd as ready
- android::apex::OnAllPackagesReady();
- } else if (strcmp("--otachroot-bootstrap", argv[1]) == 0) {
- return android::apex::OnOtaChrootBootstrapFlattenedApex();
+ android::apex::onAllPackagesReady();
}
return 0;
}
@@ -155,21 +129,12 @@ int main(int /*argc*/, char** argv) {
} else {
vold_service = &*vold_service_st;
}
- android::apex::Initialize(vold_service);
+ android::apex::initialize(vold_service);
+ bool booting = android::apex::isBooting();
if (booting) {
- if (auto res = android::apex::MigrateSessionsDirIfNeeded(); !res.ok()) {
- LOG(ERROR) << "Failed to migrate sessions to /metadata partition : "
- << res.error();
- }
- android::apex::OnStart();
- } else {
- // TODO(b/172911822): Trying to use data apex related ApexFileRepository
- // apis without initializing it should throw error. Also, unit tests should
- // not pass without initialization.
- // TODO(b/172911822): Consolidate this with Initialize() when
- // ApexFileRepository can act as cache and re-scanning is not expensive
- android::apex::InitializeDataApex();
+ android::apex::migrateSessionsDirIfNeeded();
+ android::apex::onStart();
}
android::apex::binder::CreateAndRegisterService();
android::apex::binder::StartThreadPool();
@@ -181,8 +146,10 @@ int main(int /*argc*/, char** argv) {
// themselves should wait for the ready status instead, which is set when
// the "--snapshotde" subcommand is received and snapshot/restore is
// complete.
- android::apex::OnAllPackagesActivated(/*is_bootstrap=*/false);
- lifecycle.WaitForBootStatus(android::apex::RevertActiveSessionsAndReboot);
+ android::apex::onAllPackagesActivated();
+ android::apex::waitForBootStatus(
+ android::apex::revertActiveSessionsAndReboot,
+ android::apex::bootCompletedCleanup);
}
android::apex::binder::AllowServiceShutdown();
diff --git a/apexd/apexd_prepostinstall.cpp b/apexd/apexd_prepostinstall.cpp
index 51b60b4b..21b8650a 100644
--- a/apexd/apexd_prepostinstall.cpp
+++ b/apexd/apexd_prepostinstall.cpp
@@ -35,7 +35,6 @@
#include "apex_database.h"
#include "apex_file.h"
-#include "apex_manifest.h"
#include "apexd.h"
#include "apexd_private.h"
#include "apexd_utils.h"
@@ -43,7 +42,6 @@
using android::base::Error;
using android::base::Result;
-using ::apex::proto::ApexManifest;
namespace android {
namespace apex {
@@ -60,12 +58,14 @@ void CloseSTDDescriptors() {
close(STDERR_FILENO);
}
+// Instead of temp mounting inside this fuction, we can make a caller do it.
+// This will align with the plan of extending temp mounting to provide a
+// way to run additional pre-reboot verification of an APEX.
+// TODO(ioffe): pass mount points instead of apex files.
template <typename Fn>
-Result<void> StageFnInstall(const std::vector<ApexFile>& apexes,
- const std::vector<std::string>& mount_points, Fn fn,
+Result<void> StageFnInstall(const std::vector<ApexFile>& apexes, Fn fn,
const char* arg, const char* name) {
- // TODO(b/158470023): consider supporting a session with more than one
- // pre-install hook.
+ // TODO: Support 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()) {
@@ -78,32 +78,73 @@ Result<void> StageFnInstall(const std::vector<ApexFile>& apexes,
CHECK(hook_idx != -1);
LOG(VERBOSE) << name << " for " << apexes[hook_idx].GetPath();
- // Create invocation args.
+ std::vector<MountedApexData> mounted_apexes;
+ std::vector<std::string> activation_dirs;
+ auto preinstall_guard = android::base::make_scope_guard([&]() {
+ for (const auto& mount : mounted_apexes) {
+ Result<void> st = apexd_private::Unmount(mount);
+ if (!st.ok()) {
+ LOG(ERROR) << "Failed to unmount " << mount.full_path << " from "
+ << mount.mount_point << " after " << name << ": "
+ << st.error();
+ }
+ }
+ 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;
+ }
+ }
+ });
+
+ for (const ApexFile& apex : apexes) {
+ // 1) Mount the package.
+ std::string mount_point =
+ apexd_private::GetPackageTempMountPoint(apex.GetManifest());
+
+ auto mount_data = apexd_private::TempMountPackage(apex, mount_point);
+ if (!mount_data.ok()) {
+ return mount_data.error();
+ }
+ mounted_apexes.push_back(std::move(*mount_data));
+
+ // Given the fact, that we only allow updates of existing APEXes, all the
+ // activation points will always be already created. Only scenario, when it
+ // won't be the case might be apexservice_test. But even then, it might be
+ // safer to move active_point creation logic to run after unshare.
+ // TODO(ioffe): move creation of activation points inside RunFnInstall?
+ // 2) Ensure there is an activation point, and we will clean it up.
+ std::string active_point =
+ apexd_private::GetActiveMountPoint(apex.GetManifest());
+ if (0 == mkdir(active_point.c_str(), kMkdirMode)) {
+ activation_dirs.emplace_back(std::move(active_point));
+ } else {
+ int saved_errno = errno;
+ if (saved_errno != EEXIST) {
+ return Error() << "Unable to create mount point" << active_point << ": "
+ << strerror(saved_errno);
+ }
+ }
+ }
+
+ // 3) Create invocation args.
std::vector<std::string> args{
"/system/bin/apexd", arg,
- mount_points[hook_idx] // Make the APEX with hook first.
+ mounted_apexes[hook_idx].mount_point, // Make the APEX with hook first.
};
- for (size_t i = 0; i < mount_points.size(); i++) {
+ for (size_t i = 0; i < mounted_apexes.size(); i++) {
if ((int)i != hook_idx) {
- args.push_back(mount_points[i]);
+ args.push_back(mounted_apexes[i].mount_point);
}
}
- return ForkAndRun(args);
+ std::string error_msg;
+ int res = ForkAndRun(args, &error_msg);
+ return res == 0 ? Result<void>{} : Error() << error_msg;
}
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;
@@ -119,8 +160,7 @@ int RunFnInstall(char** in_argv, Fn fn, const char* name) {
std::string hook_path;
{
- auto bind_fn = [&fn, name,
- activation_dirs](const std::string& mount_point) mutable {
+ auto bind_fn = [&fn, name](const std::string& mount_point) {
std::string hook;
std::string active_point;
{
@@ -143,14 +183,6 @@ int RunFnInstall(char** in_argv, Fn fn, const char* name) {
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.
@@ -201,19 +233,17 @@ int RunFnInstall(char** in_argv, Fn fn, const char* name) {
} // 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");
+Result<void> StagePreInstall(const std::vector<ApexFile>& apexes) {
+ return StageFnInstall(apexes, &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,
+Result<void> StagePostInstall(const std::vector<ApexFile>& apexes) {
+ return StageFnInstall(apexes, &ApexManifest::postinstallhook,
"--post-install", "post-install");
}
diff --git a/apexd/apexd_prepostinstall.h b/apexd/apexd_prepostinstall.h
index 65125bae..66cd2f57 100644
--- a/apexd/apexd_prepostinstall.h
+++ b/apexd/apexd_prepostinstall.h
@@ -27,20 +27,16 @@ 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.
+// Temp mounts given apexes and then forks into:
+// apexd --pre-install <mount-point-of-apex-with-hook> [<other-mount-points>]
android::base::Result<void> StagePreInstall(
- const std::vector<ApexFile>& apexes,
- const std::vector<std::string>& mount_points);
+ const std::vector<ApexFile>& apexes);
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.
+// Temp mounts given apexes and then forks into:
+// apexd --post-install <mount-point-of-apex-with-hook> [<other-mount-points>]
android::base::Result<void> StagePostInstall(
- const std::vector<ApexFile>& apexes,
- const std::vector<std::string>& mount_points);
+ const std::vector<ApexFile>& apexes);
int RunPostInstall(char** argv);
} // namespace apex
diff --git a/apexd/apexd_private.h b/apexd/apexd_private.h
index b3108cff..1706e08b 100644
--- a/apexd/apexd_private.h
+++ b/apexd/apexd_private.h
@@ -21,7 +21,6 @@
#include <android-base/result.h>
#include "apex_database.h"
-#include "apex_file.h"
#include "apex_manifest.h"
namespace android {
@@ -33,16 +32,16 @@ static constexpr int kMkdirMode = 0755;
namespace apexd_private {
-std::string GetPackageMountPoint(const ::apex::proto::ApexManifest& manifest);
-std::string GetPackageTempMountPoint(
- const ::apex::proto::ApexManifest& manifest);
-std::string GetActiveMountPoint(const ::apex::proto::ApexManifest& manifest);
+std::string GetPackageMountPoint(const ApexManifest& manifest);
+std::string GetPackageTempMountPoint(const ApexManifest& manifest);
+std::string GetActiveMountPoint(const ApexManifest& manifest);
android::base::Result<void> BindMount(const std::string& target,
const std::string& source);
-android::base::Result<MountedApexDatabase::MountedApexData>
-GetTempMountedApexData(const std::string& package);
-android::base::Result<void> UnmountTempMount(const ApexFile& apex);
+android::base::Result<MountedApexDatabase::MountedApexData> TempMountPackage(
+ const ApexFile& apex, const std::string& mount_point);
+android::base::Result<void> Unmount(
+ const MountedApexDatabase::MountedApexData& data);
} // namespace apexd_private
} // namespace apex
diff --git a/apexd/apexd_lifecycle.cpp b/apexd/apexd_prop.cpp
index 41c1abef..31030e10 100644
--- a/apexd/apexd_lifecycle.cpp
+++ b/apexd/apexd_prop.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,28 +16,23 @@
#define LOG_TAG "apexd"
-#include "apexd_lifecycle.h"
+#include "apexd_prop.h"
#include <android-base/logging.h>
#include <android-base/properties.h>
#include "apexd_utils.h"
+using android::base::GetBoolProperty;
using android::base::GetProperty;
using android::base::Result;
using android::base::WaitForProperty;
namespace android {
namespace apex {
-
-bool ApexdLifecycle::IsBooting() {
- auto status = GetProperty(kApexStatusSysprop, "");
- return status != kApexStatusReady && status != kApexStatusActivated;
-}
-
-void ApexdLifecycle::WaitForBootStatus(
- Result<void> (&revert_fn)(const std::string&, const std::string&)) {
- while (!boot_completed_) {
+void waitForBootStatus(Result<void> (&revert_fn)(const std::string&),
+ void (&complete_fn)()) {
+ while (!GetBoolProperty("sys.boot_completed", false)) {
// Check for change in either crashing property or sys.boot_completed
// Wait for updatable_crashing property change for most of the time
// (arbitrary 30s), briefly check if boot has completed successfully,
@@ -49,7 +44,7 @@ void ApexdLifecycle::WaitForBootStatus(
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, "");
+ auto result = revert_fn(name);
if (!result.ok()) {
LOG(ERROR) << "Revert failed : " << result.error();
break;
@@ -64,9 +59,15 @@ void ApexdLifecycle::WaitForBootStatus(
}
}
}
+ // Wait for boot to complete, and then run complete_fn.
+ // TODO(ioffe): this is a hack, instead we should have a binder call from
+ // system_server into apexd when boot completes.
+ if (WaitForProperty("sys.boot_completed", "1", std::chrono::minutes(5))) {
+ complete_fn();
+ return;
+ } else {
+ LOG(ERROR) << "Boot never completed";
+ }
}
-
-void ApexdLifecycle::MarkBootCompleted() { boot_completed_ = true; }
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_prop.h b/apexd/apexd_prop.h
new file mode 100644
index 00000000..4b8a7661
--- /dev/null
+++ b/apexd/apexd_prop.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_APEXD_APEXD_PROP_H_
+#define ANDROID_APEXD_APEXD_PROP_H_
+
+#include <android-base/result.h>
+
+namespace android {
+namespace apex {
+
+void waitForBootStatus(
+ android::base::Result<void> (&rollback_fn)(const std::string&),
+ void (&complete_fn)());
+
+} // namespace apex
+} // namespace android
+
+#endif // ANDROID_APEXD_APEXD_PROP_H
diff --git a/apexd/apexd_rollback_utils.h b/apexd/apexd_rollback_utils.h
index c7fa05ec..9990be26 100644
--- a/apexd/apexd_rollback_utils.h
+++ b/apexd/apexd_rollback_utils.h
@@ -25,6 +25,10 @@
#include <android-base/result.h>
#include <android-base/scopeguard.h>
#include <logwrap/logwrap.h>
+#include <selinux/android.h>
+
+using android::base::Error;
+using android::base::Result;
namespace android {
namespace apex {
@@ -36,7 +40,7 @@ static constexpr const char* kCpPath = "/system/bin/cp";
* path. Note that this will fail if run before APEXes are mounted, due to a
* dependency on runtime.
*/
-inline int32_t CopyDirectoryRecursive(const char* from, const char* to) {
+int32_t copy_directory_recursive(const char* from, const char* to) {
const char* const argv[] = {
kCpPath,
"-F", /* delete any existing destination file first
@@ -58,15 +62,15 @@ inline int32_t CopyDirectoryRecursive(const char* from, const char* to) {
* from from_path into to_path. Note that this must be run after APEXes are
* mounted.
*/
-inline android::base::Result<void> ReplaceFiles(const std::string& from_path,
- const std::string& to_path) {
+inline Result<void> ReplaceFiles(const std::string& from_path,
+ const std::string& to_path) {
namespace fs = std::filesystem;
std::error_code error_code;
fs::remove_all(to_path, error_code);
if (error_code) {
- return android::base::Error() << "Failed to delete existing files at "
- << to_path << " : " << error_code.message();
+ return Error() << "Failed to delete existing files at " << to_path << " : "
+ << error_code.message();
}
auto deleter = [&] {
@@ -79,15 +83,23 @@ inline android::base::Result<void> ReplaceFiles(const std::string& from_path,
};
auto scope_guard = android::base::make_scope_guard(deleter);
- int rc = CopyDirectoryRecursive(from_path.c_str(), to_path.c_str());
+ int rc = copy_directory_recursive(from_path.c_str(), to_path.c_str());
if (rc != 0) {
- return android::base::Error() << "Failed to copy from [" << from_path
- << "] to [" << to_path << "]";
+ return Error() << "Failed to copy from [" << from_path << "] to ["
+ << to_path << "]";
}
scope_guard.Disable();
return {};
}
+inline Result<void> RestoreconPath(const std::string& path) {
+ unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
+ if (selinux_android_restorecon(path.c_str(), seflags) < 0) {
+ return Error() << "Failed to restorecon " << path;
+ }
+ return {};
+}
+
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_session.cpp b/apexd/apexd_session.cpp
index defef6fa..3d916c48 100644
--- a/apexd/apexd_session.cpp
+++ b/apexd/apexd_session.cpp
@@ -22,7 +22,6 @@
#include "session_state.pb.h"
#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
#include <dirent.h>
#include <sys/stat.h>
@@ -33,7 +32,6 @@
using android::base::Error;
using android::base::Result;
-using android::base::StringPrintf;
using apex::proto::SessionState;
namespace android {
@@ -41,57 +39,68 @@ namespace apex {
namespace {
-// Starting from R, apexd prefers /metadata partition (kNewApexSessionsDir) as
-// location for sessions-related information. For devices that don't have
-// /metadata partition, apexd will fallback to the /data one
-// (kOldApexSessionsDir).
-static constexpr const char* kOldApexSessionsDir = "/data/apex/sessions";
-static constexpr const char* kNewApexSessionsDir = "/metadata/apex/sessions";
-
static constexpr const char* kStateFileName = "state";
-} // namespace
+std::string getSessionDir(int session_id) {
+ return kApexSessionsDir + "/" + std::to_string(session_id);
+}
-ApexSession::ApexSession(SessionState state) : state_(std::move(state)) {}
+std::string getSessionStateFilePath(int session_id) {
+ return getSessionDir(session_id) + "/" + kStateFileName;
+}
-std::string ApexSession::GetSessionsDir() {
- static std::string result;
- static std::once_flag once_flag;
- std::call_once(once_flag, [&]() {
- auto status =
- FindFirstExistingDirectory(kNewApexSessionsDir, kOldApexSessionsDir);
- if (!status.ok()) {
- LOG(FATAL) << status.error();
- }
- result = std::move(*status);
- });
- return result;
+Result<std::string> createSessionDirIfNeeded(int session_id) {
+ // create /data/sessions
+ auto res = createDirIfNeeded(kApexSessionsDir, 0700);
+ if (!res.ok()) {
+ return res.error();
+ }
+ // create /data/sessions/session_id
+ std::string sessionDir = getSessionDir(session_id);
+ res = createDirIfNeeded(sessionDir, 0700);
+ if (!res.ok()) {
+ return res.error();
+ }
+
+ return sessionDir;
}
-Result<void> ApexSession::MigrateToMetadataSessionsDir() {
- return MoveDir(kOldApexSessionsDir, kNewApexSessionsDir);
+Result<void> deleteSessionDir(int session_id) {
+ std::string session_dir = getSessionDir(session_id);
+ LOG(DEBUG) << "Deleting " << session_dir;
+ auto path = std::filesystem::path(session_dir);
+ std::error_code error_code;
+ std::filesystem::remove_all(path, error_code);
+ if (error_code) {
+ return Error() << "Failed to delete " << session_dir << " : "
+ << error_code.message();
+ }
+ return {};
}
+} // namespace
+
+ApexSession::ApexSession(SessionState state) : state_(std::move(state)) {}
+
Result<ApexSession> ApexSession::CreateSession(int session_id) {
SessionState state;
// Create session directory
- std::string session_dir = GetSessionsDir() + "/" + std::to_string(session_id);
- if (auto status = CreateDirIfNeeded(session_dir, 0700); !status.ok()) {
- return status.error();
+ auto sessionPath = createSessionDirIfNeeded(session_id);
+ if (!sessionPath.ok()) {
+ return sessionPath.error();
}
state.set_id(session_id);
return ApexSession(state);
}
-
Result<ApexSession> ApexSession::GetSessionFromFile(const std::string& path) {
SessionState state;
- std::fstream state_file(path, std::ios::in | std::ios::binary);
- if (!state_file) {
+ std::fstream stateFile(path, std::ios::in | std::ios::binary);
+ if (!stateFile) {
return Error() << "Failed to open " << path;
}
- if (!state.ParseFromIstream(&state_file)) {
+ if (!state.ParseFromIstream(&stateFile)) {
return Error() << "Failed to parse " << path;
}
@@ -99,8 +108,7 @@ Result<ApexSession> ApexSession::GetSessionFromFile(const std::string& path) {
}
Result<ApexSession> ApexSession::GetSession(int session_id) {
- auto path = StringPrintf("%s/%d/%s", GetSessionsDir().c_str(), session_id,
- kStateFileName);
+ auto path = getSessionStateFilePath(session_id);
return GetSessionFromFile(path);
}
@@ -108,19 +116,19 @@ Result<ApexSession> ApexSession::GetSession(int session_id) {
std::vector<ApexSession> ApexSession::GetSessions() {
std::vector<ApexSession> sessions;
- Result<std::vector<std::string>> session_paths = ReadDir(
- GetSessionsDir(), [](const std::filesystem::directory_entry& entry) {
+ Result<std::vector<std::string>> sessionPaths = ReadDir(
+ kApexSessionsDir, [](const std::filesystem::directory_entry& entry) {
std::error_code ec;
return entry.is_directory(ec);
});
- if (!session_paths.ok()) {
+ if (!sessionPaths.ok()) {
return sessions;
}
- for (const std::string& session_dir_path : *session_paths) {
+ for (const std::string& sessionDirPath : *sessionPaths) {
// Try to read session state
- auto session = GetSessionFromFile(session_dir_path + "/" + kStateFileName);
+ auto session = GetSessionFromFile(sessionDirPath + "/" + kStateFileName);
if (!session.ok()) {
LOG(WARNING) << session.error();
continue;
@@ -144,20 +152,20 @@ std::vector<ApexSession> ApexSession::GetSessionsInState(
std::vector<ApexSession> ApexSession::GetActiveSessions() {
auto sessions = GetSessions();
- std::vector<ApexSession> active_sessions;
+ std::vector<ApexSession> activeSessions;
for (const ApexSession& session : sessions) {
if (!session.IsFinalized() && session.GetState() != SessionState::UNKNOWN) {
- active_sessions.push_back(session);
+ activeSessions.push_back(session);
}
}
- return active_sessions;
+ return activeSessions;
}
SessionState::State ApexSession::GetState() const { return state_.state(); }
int ApexSession::GetId() const { return state_.id(); }
-const std::string& ApexSession::GetBuildFingerprint() const {
+std::string ApexSession::GetBuildFingerprint() const {
return state_.expected_build_fingerprint();
}
@@ -181,14 +189,10 @@ bool ApexSession::IsRollback() const { return state_.is_rollback(); }
int ApexSession::GetRollbackId() const { return state_.rollback_id(); }
-const std::string& ApexSession::GetCrashingNativeProcess() const {
+std::string ApexSession::GetCrashingNativeProcess() const {
return state_.crashing_native_process();
}
-const std::string& ApexSession::GetErrorMessage() const {
- return state_.error_message();
-}
-
const google::protobuf::RepeatedField<int> ApexSession::GetChildSessionIds()
const {
return state_.child_session_ids();
@@ -226,10 +230,6 @@ void ApexSession::SetCrashingNativeProcess(
state_.set_crashing_native_process(crashing_process);
}
-void ApexSession::SetErrorMessage(const std::string& error_message) {
- state_.set_error_message(error_message);
-}
-
void ApexSession::AddApexName(const std::string& apex_name) {
state_.add_apex_names(apex_name);
}
@@ -238,29 +238,19 @@ Result<void> ApexSession::UpdateStateAndCommit(
const SessionState::State& session_state) {
state_.set_state(session_state);
- auto state_file_path = StringPrintf("%s/%d/%s", GetSessionsDir().c_str(),
- state_.id(), kStateFileName);
+ auto stateFilePath = getSessionStateFilePath(state_.id());
- std::fstream state_file(state_file_path,
- std::ios::out | std::ios::trunc | std::ios::binary);
- if (!state_.SerializeToOstream(&state_file)) {
- return Error() << "Failed to write state file " << state_file_path;
+ std::fstream stateFile(stateFilePath,
+ std::ios::out | std::ios::trunc | std::ios::binary);
+ if (!state_.SerializeToOstream(&stateFile)) {
+ return Error() << "Failed to write state file " << stateFilePath;
}
return {};
}
Result<void> ApexSession::DeleteSession() const {
- std::string session_dir = GetSessionsDir() + "/" + std::to_string(GetId());
- LOG(INFO) << "Deleting " << session_dir;
- auto path = std::filesystem::path(session_dir);
- std::error_code error_code;
- std::filesystem::remove_all(path, error_code);
- if (error_code) {
- return Error() << "Failed to delete " << session_dir << " : "
- << error_code.message();
- }
- return {};
+ return deleteSessionDir(GetId());
}
std::ostream& operator<<(std::ostream& out, const ApexSession& session) {
@@ -269,18 +259,5 @@ std::ostream& operator<<(std::ostream& out, const ApexSession& session) {
<< "]";
}
-void ApexSession::DeleteFinalizedSessions() {
- auto sessions = GetSessions();
- for (const ApexSession& session : sessions) {
- if (!session.IsFinalized()) {
- continue;
- }
- auto result = session.DeleteSession();
- if (!result.ok()) {
- LOG(WARNING) << "Failed to delete finalized session: " << session.GetId();
- }
- }
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_session.h b/apexd/apexd_session.h
index 5c1f1e3e..e0cea91c 100644
--- a/apexd/apexd_session.h
+++ b/apexd/apexd_session.h
@@ -28,18 +28,10 @@
namespace android {
namespace apex {
+static const std::string kApexSessionsDir = "/metadata/apex/sessions";
+
class ApexSession {
public:
- // Returns top-level directory to store sessions metadata in.
- // If device has /metadata partition, this will return
- // /metadata/apex/sessions, on all other devices it will return
- // /data/apex/sessions.
- static std::string GetSessionsDir();
- // Migrates content of /data/apex/sessions to /metadata/apex/sessions.
- // If device doesn't have /metadata partition this call will be a no-op.
- // If /data/apex/sessions this call will also be a no-op.
- static android::base::Result<void> MigrateToMetadataSessionsDir();
-
static android::base::Result<ApexSession> CreateSession(int session_id);
static android::base::Result<ApexSession> GetSession(int session_id);
static std::vector<ApexSession> GetSessions();
@@ -52,9 +44,8 @@ class ApexSession {
const google::protobuf::RepeatedField<int> GetChildSessionIds() const;
::apex::proto::SessionState::State GetState() const;
int GetId() const;
- const std::string& GetBuildFingerprint() const;
- const std::string& GetCrashingNativeProcess() const;
- const std::string& GetErrorMessage() const;
+ std::string GetBuildFingerprint() const;
+ std::string GetCrashingNativeProcess() const;
bool IsFinalized() const;
bool HasRollbackEnabled() const;
bool IsRollback() const;
@@ -67,17 +58,15 @@ class ApexSession {
void SetIsRollback(const bool is_rollback);
void SetRollbackId(const int rollback_id);
void SetCrashingNativeProcess(const std::string& crashing_process);
- void SetErrorMessage(const std::string& error_message);
void AddApexName(const std::string& apex_name);
android::base::Result<void> UpdateStateAndCommit(
const ::apex::proto::SessionState::State& state);
android::base::Result<void> DeleteSession() const;
- static void DeleteFinalizedSessions();
private:
- explicit ApexSession(::apex::proto::SessionState state);
+ ApexSession(::apex::proto::SessionState state);
::apex::proto::SessionState state_;
static android::base::Result<ApexSession> GetSessionFromFile(
diff --git a/apexd/apexd_session_test.cpp b/apexd/apexd_session_test.cpp
deleted file mode 100644
index 50d0f858..00000000
--- a/apexd/apexd_session_test.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <filesystem>
-#include <fstream>
-#include <string>
-
-#include <errno.h>
-
-#include <android-base/file.h>
-#include <android-base/result.h>
-#include <android-base/scopeguard.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <gtest/gtest.h>
-
-#include "apexd_session.h"
-#include "apexd_test_utils.h"
-#include "apexd_utils.h"
-#include "session_state.pb.h"
-
-namespace android {
-namespace apex {
-namespace {
-
-using android::apex::testing::IsOk;
-using android::base::Join;
-using android::base::make_scope_guard;
-
-// TODO(b/170329726): add unit tests for apexd_sessions.h
-
-TEST(ApexdSessionTest, GetSessionsDirSessionsStoredInMetadata) {
- if (access("/metadata", F_OK) != 0) {
- GTEST_SKIP() << "Device doesn't have /metadata partition";
- }
-
- std::string result = ApexSession::GetSessionsDir();
- ASSERT_EQ(result, "/metadata/apex/sessions");
-}
-
-TEST(ApexdSessionTest, GetSessionsDirNoMetadataPartitionFallbackToData) {
- if (access("/metadata", F_OK) == 0) {
- GTEST_SKIP() << "Device has /metadata partition";
- }
-
- std::string result = ApexSession::GetSessionsDir();
- ASSERT_EQ(result, "/data/apex/sessions");
-}
-
-TEST(ApexdSessionTest, MigrateToMetadataSessionsDir) {
- namespace fs = std::filesystem;
-
- if (access("/metadata", F_OK) != 0) {
- GTEST_SKIP() << "Device doesn't have /metadata partition";
- }
-
- // This is ugly, but does the job. To have a truly hermetic unit tests we
- // need to refactor ApexSession class.
- for (const auto& entry : fs::directory_iterator("/metadata/apex/sessions")) {
- fs::remove_all(entry.path());
- }
-
- // This is a very ugly test set up, but to have something better we need to
- // refactor ApexSession class.
- class TestApexSession {
- public:
- TestApexSession(int id, const SessionState::State& state) {
- path_ = "/data/apex/sessions/" + std::to_string(id);
- if (auto status = CreateDirIfNeeded(path_, 0700); !status.ok()) {
- ADD_FAILURE() << "Failed to create " << path_ << " : "
- << status.error();
- }
- SessionState session;
- session.set_id(id);
- session.set_state(state);
- std::fstream state_file(
- path_ + "/state", std::ios::out | std::ios::trunc | std::ios::binary);
- if (!session.SerializeToOstream(&state_file)) {
- ADD_FAILURE() << "Failed to write to " << path_;
- }
- }
-
- ~TestApexSession() { fs::remove_all(path_); }
-
- private:
- std::string path_;
- };
-
- auto deleter = make_scope_guard([&]() {
- fs::remove_all("/metadata/apex/sessions/239");
- fs::remove_all("/metadata/apex/sessions/1543");
- });
-
- TestApexSession session1(239, SessionState::SUCCESS);
- TestApexSession session2(1543, SessionState::ACTIVATION_FAILED);
-
- ASSERT_TRUE(IsOk(ApexSession::MigrateToMetadataSessionsDir()));
-
- auto sessions = ApexSession::GetSessions();
- ASSERT_EQ(2u, sessions.size()) << Join(sessions, ',');
-
- auto migrated_session_1 = ApexSession::GetSession(239);
- ASSERT_TRUE(IsOk(migrated_session_1));
- ASSERT_EQ(SessionState::SUCCESS, migrated_session_1->GetState());
-
- auto migrated_session_2 = ApexSession::GetSession(1543);
- ASSERT_TRUE(IsOk(migrated_session_2));
- ASSERT_EQ(SessionState::ACTIVATION_FAILED, migrated_session_2->GetState());
-}
-
-} // namespace
-} // namespace apex
-} // namespace android
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
deleted file mode 100644
index a3ebd03a..00000000
--- a/apexd/apexd_test.cpp
+++ /dev/null
@@ -1,3603 +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 <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/properties.h>
-#include <android-base/scopeguard.h>
-#include <android-base/stringprintf.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "apex_database.h"
-#include "apex_file_repository.h"
-#include "apexd.h"
-#include "apexd_checkpoint.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"
-
-namespace android {
-namespace apex {
-
-namespace fs = std::filesystem;
-
-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::make_scope_guard;
-using android::base::RemoveFileIfExists;
-using android::base::Result;
-using android::base::StringPrintf;
-using android::base::unique_fd;
-using android::base::WriteStringToFile;
-using com::android::apex::testing::ApexInfoXmlEq;
-using ::testing::ByRef;
-using ::testing::HasSubstr;
-using ::testing::IsEmpty;
-using ::testing::StartsWith;
-using ::testing::UnorderedElementsAre;
-using ::testing::UnorderedElementsAreArray;
-
-static std::string GetTestDataDir() { return GetExecutableDirectory(); }
-static std::string GetTestFile(const std::string& name) {
- return GetTestDataDir() + "/" + name;
-}
-
-static int64_t GetMTime(const std::string& path) {
- struct stat st_buf;
- if (stat(path.c_str(), &st_buf) != 0) {
- PLOG(ERROR) << "Failed to stat " << path;
- return 0;
- }
- return st_buf.st_mtime;
-}
-
-// A very basic mock of CheckpointInterface.
-class MockCheckpointInterface : public CheckpointInterface {
- public:
- Result<bool> SupportsFsCheckpoints() override {
- return supports_fs_checkpoint_;
- }
-
- Result<bool> NeedsCheckpoint() override { return needs_checkpoint_; }
-
- Result<bool> NeedsRollback() override { return needs_rollback_; }
-
- Result<void> StartCheckpoint(int32_t num_retries) override { return {}; }
-
- Result<void> AbortChanges(const std::string& msg, bool retry) override {
- return {};
- }
-
- void SetSupportsCheckpoint(bool value) { supports_fs_checkpoint_ = value; }
-
- void SetNeedsCheckpoint(bool value) { needs_checkpoint_ = value; }
-
- void SetNeedsRollback(bool value) { needs_rollback_ = value; }
-
- private:
- bool supports_fs_checkpoint_, needs_checkpoint_, needs_rollback_;
-};
-
-static constexpr const char* kTestApexdStatusSysprop = "apexd.status.test";
-
-// A test fixture that provides frequently required temp directories for tests
-class ApexdUnitTest : public ::testing::Test {
- public:
- ApexdUnitTest() {
- built_in_dir_ = StringPrintf("%s/pre-installed-apex", td_.path);
- data_dir_ = StringPrintf("%s/data-apex", td_.path);
- decompression_dir_ = StringPrintf("%s/decompressed-apex", td_.path);
- 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);
- 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_; }
- const std::string& GetDataDir() { return data_dir_; }
- const std::string& GetDecompressionDir() { return decompression_dir_; }
- const std::string& GetOtaReservedDir() { return ota_reserved_dir_; }
- const std::string& GetHashTreeDir() { return hash_tree_dir_; }
- const std::string GetStagedDir(int session_id) {
- return StringPrintf("%s/session_%d", staged_session_dir_.c_str(),
- session_id);
- }
-
- std::string GetRootDigest(const ApexFile& apex) {
- if (apex.IsCompressed()) {
- return "";
- }
- auto digest = apex.VerifyApexVerity(apex.GetBundledPublicKey());
- if (!digest.ok()) {
- return "";
- }
- return digest->root_digest;
- }
-
- std::string AddPreInstalledApex(const std::string& apex_name) {
- fs::copy(GetTestFile(apex_name), built_in_dir_);
- return StringPrintf("%s/%s", built_in_dir_.c_str(), apex_name.c_str());
- }
-
- std::string AddDataApex(const std::string& apex_name) {
- fs::copy(GetTestFile(apex_name), data_dir_);
- return StringPrintf("%s/%s", data_dir_.c_str(), apex_name.c_str());
- }
-
- std::string AddDataApex(const std::string& apex_name,
- const std::string& target_name) {
- fs::copy(GetTestFile(apex_name), data_dir_ + "/" + target_name);
- return StringPrintf("%s/%s", data_dir_.c_str(), target_name.c_str());
- }
-
- // 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,
- const std::string& built_in_dir) {
- fs::copy(GetTestFile(name), built_in_dir);
- auto compressed_apex = ApexFile::Open(
- StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str()));
- 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);
- return StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str());
- }
-
- std::string PrepareCompressedApex(const std::string& name) {
- return PrepareCompressedApex(name, built_in_dir_);
- }
-
- Result<ApexSession> CreateStagedSession(const std::string& apex_name,
- int session_id) {
- CreateDirIfNeeded(GetStagedDir(session_id), 0755);
- fs::copy(GetTestFile(apex_name), GetStagedDir(session_id));
- auto result = ApexSession::CreateSession(session_id);
- result->SetBuildFingerprint(GetProperty("ro.build.fingerprint", ""));
- return result;
- }
-
- protected:
- void SetUp() override {
- SetConfig(config_);
- ApexFileRepository::GetInstance().Reset(decompression_dir_);
- ASSERT_EQ(mkdir(built_in_dir_.c_str(), 0755), 0);
- ASSERT_EQ(mkdir(data_dir_.c_str(), 0755), 0);
- ASSERT_EQ(mkdir(decompression_dir_.c_str(), 0755), 0);
- 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);
-
- DeleteDirContent(ApexSession::GetSessionsDir());
- }
-
- void TearDown() override { DeleteDirContent(ApexSession::GetSessionsDir()); }
-
- private:
- TemporaryDir td_;
- std::string built_in_dir_;
- std::string data_dir_;
- std::string decompression_dir_;
- std::string ota_reserved_dir_;
- std::string hash_tree_dir_;
- std::string staged_session_dir_;
- ApexdConfig config_;
-};
-
-// Apex that does not have pre-installed version, does not get selected
-TEST_F(ApexdUnitTest, ApexMustHavePreInstalledVersionForSelection) {
- AddPreInstalledApex("apex.apexd_test.apex");
- AddPreInstalledApex("com.android.apex.cts.shim.apex");
- auto shared_lib_1 = ApexFile::Open(AddPreInstalledApex(
- "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_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"));
- // Normally both pre-installed and data apex would be activated for a shared
- // 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_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
- const auto all_apex = instance.AllApexFilesByName();
- // Pass a blank instance so that the data apex files are not considered
- // pre-installed
- const ApexFileRepository instance_blank;
- auto result = SelectApexForActivation(all_apex, instance_blank);
- ASSERT_EQ(result.size(), 0u);
- // When passed proper instance they should get selected
- result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 3u);
- ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file)),
- ApexFileEq(ByRef(*shim_v1)),
- ApexFileEq(ByRef(*shared_lib_2))));
-}
-
-// Higher version gets priority when selecting for activation
-TEST_F(ApexdUnitTest, HigherVersionOfApexIsSelected) {
- auto apexd_test_file_v2 =
- ApexFile::Open(AddPreInstalledApex("apex.apexd_test_v2.apex"));
- AddPreInstalledApex("com.android.apex.cts.shim.apex");
- auto& instance = ApexFileRepository::GetInstance();
- 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_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
- auto all_apex = instance.AllApexFilesByName();
- auto result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 2u);
-
- ASSERT_THAT(result,
- UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file_v2)),
- ApexFileEq(ByRef(*shim_v2))));
-}
-
-// When versions are equal, non-pre-installed version gets priority
-TEST_F(ApexdUnitTest, DataApexGetsPriorityForSameVersions) {
- AddPreInstalledApex("apex.apexd_test.apex");
- AddPreInstalledApex("com.android.apex.cts.shim.apex");
- // Initialize pre-installed APEX information
- auto& instance = ApexFileRepository::GetInstance();
- 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_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
- auto all_apex = instance.AllApexFilesByName();
- auto result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 2u);
-
- ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file)),
- ApexFileEq(ByRef(*shim_v1))));
-}
-
-// Both versions of shared libs can be selected when preinstalled version is
-// lower than data version
-TEST_F(ApexdUnitTest, SharedLibsCanHaveBothVersionSelected) {
- auto shared_lib_v1 = ApexFile::Open(AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
- // Initialize pre-installed APEX information
- auto& instance = ApexFileRepository::GetInstance();
- 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_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
- auto all_apex = instance.AllApexFilesByName();
- auto result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 2u);
-
- ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*shared_lib_v1)),
- ApexFileEq(ByRef(*shared_lib_v2))));
-}
-
-// Data version of shared libs should not be selected if lower than
-// preinstalled version
-TEST_F(ApexdUnitTest, SharedLibsDataVersionDeletedIfLower) {
- auto shared_lib_v2 = ApexFile::Open(AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v2.libvY.apex"));
- // Initialize pre-installed APEX information
- auto& instance = ApexFileRepository::GetInstance();
- 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_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
- auto all_apex = instance.AllApexFilesByName();
- auto result = SelectApexForActivation(all_apex, instance);
- ASSERT_EQ(result.size(), 1u);
-
- ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*shared_lib_v2))));
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApex) {
- 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);
-
- std::string decompressed_file_path = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- // Assert output path is not empty
- auto exists = PathExists(decompressed_file_path);
- 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_TRUE(IsOk(comparison_result));
- ASSERT_TRUE(*comparison_result);
-
- // Assert that return value contains decompressed APEX
- auto decompressed_apex = ApexFile::Open(decompressed_file_path);
- ASSERT_THAT(return_value,
- UnorderedElementsAre(ApexFileEq(ByRef(*decompressed_apex))));
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApexRunsVerification) {
- auto compressed_apex_mismatch_key = ApexFile::Open(AddPreInstalledApex(
- "com.android.apex.compressed_key_mismatch_with_original.capex"));
- auto compressed_apex_version_mismatch = ApexFile::Open(
- AddPreInstalledApex("com.android.apex.compressed.v1_with_v2_apex.capex"));
-
- std::vector<ApexFileRef> compressed_apex_list;
- compressed_apex_list.emplace_back(std::cref(*compressed_apex_mismatch_key));
- compressed_apex_list.emplace_back(
- std::cref(*compressed_apex_version_mismatch));
- auto return_value =
- ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
- ASSERT_EQ(return_value.size(), 0u);
-}
-
-TEST_F(ApexdUnitTest, ValidateDecompressedApex) {
- auto capex = ApexFile::Open(
- AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
- auto decompressed_v1 = ApexFile::Open(
- AddDataApex("com.android.apex.compressed.v1_original.apex"));
-
- auto result =
- ValidateDecompressedApex(std::cref(*capex), std::cref(*decompressed_v1));
- 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.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_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.error().message(),
- HasSubstr("Public key of compressed APEX is different than original"));
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApexCanBeCalledMultipleTimes) {
- 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);
-
- // Capture the creation time of the decompressed APEX
- std::error_code ec;
- auto decompressed_apex_path = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- auto last_write_time_1 = fs::last_write_time(decompressed_apex_path, ec);
- ASSERT_FALSE(ec) << "Failed to capture last write time of "
- << decompressed_apex_path;
-
- // Now try to decompress the same capex again. It should not fail.
- return_value =
- ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
- ASSERT_EQ(return_value.size(), 1u);
-
- // Ensure the decompressed APEX file did not change
- auto last_write_time_2 = fs::last_write_time(decompressed_apex_path, ec);
- ASSERT_FALSE(ec) << "Failed to capture last write time of "
- << decompressed_apex_path;
- ASSERT_EQ(last_write_time_1, last_write_time_2);
-}
-
-// Test behavior of ProcessCompressedApex when is_ota_chroot is true
-TEST_F(ApexdUnitTest, ProcessCompressedApexOnOtaChroot) {
- 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= */ true);
- ASSERT_EQ(return_value.size(), 1u);
-
- // Decompressed APEX should be located in decompression_dir
- std::string decompressed_file_path =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- // Assert output path is not empty
- auto exists = PathExists(decompressed_file_path);
- 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_TRUE(IsOk(comparison_result));
- ASSERT_TRUE(*comparison_result);
-
- // Assert that return value contains the decompressed APEX
- auto apex_file = ApexFile::Open(decompressed_file_path);
- ASSERT_THAT(return_value,
- UnorderedElementsAre(ApexFileEq(ByRef(*apex_file))));
-}
-
-// When decompressing APEX, reuse existing OTA APEX
-TEST_F(ApexdUnitTest, ProcessCompressedApexReuseOtaApex) {
- // Push a compressed APEX that will fail to decompress
- auto compressed_apex = ApexFile::Open(AddPreInstalledApex(
- "com.android.apex.compressed.v1_not_decompressible.capex"));
-
- std::vector<ApexFileRef> compressed_apex_list;
- compressed_apex_list.emplace_back(std::cref(*compressed_apex));
-
- // If we try to decompress capex directly, it should fail since the capex
- // pushed is faulty and cannot be decompressed
- auto return_value =
- ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
- ASSERT_EQ(return_value.size(), 0u);
-
- // But, if there is an ota_apex present for reuse, it should reuse that
- // and avoid decompressing the faulty capex
-
- // Push an OTA apex that should be reused to skip decompression
- auto ota_apex_path =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
- ota_apex_path);
- return_value =
- ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
- ASSERT_EQ(return_value.size(), 1u);
-
- // Ota Apex should be cleaned up
- ASSERT_FALSE(*PathExists(ota_apex_path));
- ASSERT_EQ(return_value[0].GetPath(),
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix));
-}
-
-TEST_F(ApexdUnitTest, ShouldAllocateSpaceForDecompressionNewApex) {
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
- // A brand new compressed APEX is being introduced: selected
- auto result =
- ShouldAllocateSpaceForDecompression("com.android.brand.new", 1, instance);
- ASSERT_TRUE(IsOk(result));
- ASSERT_TRUE(*result);
-}
-
-TEST_F(ApexdUnitTest,
- ShouldAllocateSpaceForDecompressionWasNotCompressedBefore) {
- // Prepare fake pre-installed apex
- AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
- // An existing pre-installed APEX is now compressed in the OTA: selected
- {
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.test_package", 1, instance);
- 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_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
- {
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.test_package", 3, instance);
- ASSERT_TRUE(IsOk(result));
- ASSERT_TRUE(*result);
- }
-
- // But not if data apex has equal or higher version
- {
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.test_package", 2, instance);
- ASSERT_TRUE(IsOk(result));
- ASSERT_FALSE(*result);
- }
-}
-
-TEST_F(ApexdUnitTest, ShouldAllocateSpaceForDecompressionVersionCompare) {
- // Prepare fake pre-installed apex
- PrepareCompressedApex("com.android.apex.compressed.v1.capex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
- ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
- {
- // New Compressed apex has higher version than decompressed data apex:
- // selected
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.compressed", 2, instance);
- ASSERT_TRUE(IsOk(result));
- ASSERT_TRUE(*result)
- << "Higher version test with decompressed data returned false";
- }
-
- // Compare against decompressed data apex
- {
- // New Compressed apex has same version as decompressed data apex: not
- // selected
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.compressed", 1, instance);
- 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
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.compressed", 0, instance);
- 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_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_TRUE(IsOk(instance_new.AddDataApex(data_dir_new.path)));
-
- {
- // New Compressed apex has higher version as data apex: selected
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.compressed", 3, instance_new);
- 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
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.compressed", 2, instance_new);
- 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
- auto result = ShouldAllocateSpaceForDecompression(
- "com.android.apex.compressed", 1, instance_new);
- ASSERT_TRUE(IsOk(result));
- ASSERT_FALSE(*result) << "lower version test with new data returned true";
- }
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexCreatesSingleFile) {
- TemporaryDir dest_dir;
- // Reserving space should create a single file in dest_dir with exact size
-
- ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
- auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_TRUE(IsOk(files));
- ASSERT_EQ(files->size(), 1u);
- EXPECT_EQ(fs::file_size((*files)[0]), 100u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexSafeToCallMultipleTimes) {
- TemporaryDir dest_dir;
- // Calling ReserveSpaceForCompressedApex multiple times should still create
- // a single file
- 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_TRUE(IsOk(files));
- ASSERT_EQ(files->size(), 1u);
- EXPECT_EQ(fs::file_size((*files)[0]), 100u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexShrinkAndGrow) {
- TemporaryDir dest_dir;
-
- // Create a 100 byte file
- ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
-
- // Should be able to shrink and grow the reserved space
- ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(1000, dest_dir.path)));
- auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_TRUE(IsOk(files));
- ASSERT_EQ(files->size(), 1u);
- EXPECT_EQ(fs::file_size((*files)[0]), 1000u);
-
- ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(10, dest_dir.path)));
- files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_TRUE(IsOk(files));
- ASSERT_EQ(files->size(), 1u);
- EXPECT_EQ(fs::file_size((*files)[0]), 10u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexDeallocateIfPassedZero) {
- TemporaryDir dest_dir;
-
- // Create a file first
- ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
- auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_TRUE(IsOk(files));
- ASSERT_EQ(files->size(), 1u);
-
- // Should delete the reserved file if size passed is 0
- ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(0, dest_dir.path)));
- files = ReadDir(dest_dir.path, [](auto _) { return true; });
- ASSERT_TRUE(IsOk(files));
- ASSERT_EQ(files->size(), 0u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCapexCleansOtaApex) {
- TemporaryDir dest_dir;
-
- auto ota_apex_path = StringPrintf(
- "%s/ota_apex%s", GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- auto create_ota_apex = [&]() {
- // Create an ota_apex first
- fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
- ota_apex_path);
- 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_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_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_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_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);
- }
-
- protected:
- void SetUp() final {
- ApexdUnitTest::SetUp();
- GetApexDatabaseForTesting().Reset();
- ASSERT_TRUE(IsOk(SetUpApexTestEnvironment()));
- }
-
- void TearDown() final {
- ApexdUnitTest::TearDown();
- for (const auto& apex : to_unmount_) {
- if (auto status = DeactivatePackage(apex); !status.ok()) {
- LOG(ERROR) << "Failed to unmount " << apex << " : " << status.error();
- }
- }
- }
-
- private:
- MountNamespaceRestorer restorer_;
- std::vector<std::string> to_unmount_;
-};
-
-// TODO(b/187864524): cover other negative scenarios.
-TEST_F(ApexdMountTest, InstallPackageRejectsApexWithoutRebootlessSupport) {
- std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret = InstallPackage(GetTestFile("apex.apexd_test.apex"));
- 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.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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret =
- InstallPackage(GetTestFile("test.rebootless_apex_v2_no_hashtree.apex"));
- ASSERT_FALSE(IsOk(ret));
- ASSERT_THAT(ret.error().message(),
- HasSubstr(" does not have an embedded hash tree"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsNoActiveApex) {
- std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_FALSE(IsOk(ret));
- ASSERT_THAT(
- 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_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.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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_corrupted.apex"));
- 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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret = InstallPackage(
- GetTestFile("test.rebootless_apex_provides_sharedlibs.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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret = InstallPackage(
- GetTestFile("test.rebootless_apex_provides_native_libs.apex"));
- 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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret = InstallPackage(
- GetTestFile("test.rebootless_apex_requires_shared_apex_libs.apex"));
- 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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_jni_libs.apex"));
- 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_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.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_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.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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret =
- InstallPackage(GetTestFile("test.rebootless_apex_app_in_apex.apex"));
- 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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto ret =
- InstallPackage(GetTestFile("test.rebootless_apex_priv_app_in_apex.apex"));
- 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_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_TRUE(IsOk(ret));
- UnmountOnTearDown(ret->GetPath());
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@2"));
-
- // 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_TRUE(IsOk(manifest));
- ASSERT_EQ(2u, manifest->version());
-
- // Check that GetActivePackage correctly reports upgraded version.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
- // Check that pre-installed APEX is still around
- ASSERT_EQ(0, access(file_path.c_str(), F_OK))
- << "Can't access " << file_path << " : " << strerror(errno);
-
- auto& db = GetApexDatabaseForTesting();
- // Check that upgraded APEX is mounted on top of dm-verity device.
- db.ForallMountedApexes(
- "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, ret->GetPath());
- ASSERT_EQ(data.device_name, "test.apex.rebootless@2_1");
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackagePreInstallVersionActiveSamegrade) {
- std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
- ASSERT_TRUE(IsOk(ret));
- UnmountOnTearDown(ret->GetPath());
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@1"));
-
- // Check that GetActivePackage correctly reports upgraded version.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
- // Check that pre-installed APEX is still around
- ASSERT_EQ(0, access(file_path.c_str(), F_OK))
- << "Can't access " << file_path << " : " << strerror(errno);
-
- auto& db = GetApexDatabaseForTesting();
- // Check that upgraded APEX is mounted on top of dm-verity device.
- db.ForallMountedApexes(
- "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, ret->GetPath());
- ASSERT_EQ(data.device_name, "test.apex.rebootless@1_1");
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackageDataVersionActive) {
- AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("test.rebootless_apex_v1.apex");
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_TRUE(IsOk(ret));
- UnmountOnTearDown(ret->GetPath());
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@2"));
-
- // 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_TRUE(IsOk(manifest));
- ASSERT_EQ(2u, manifest->version());
-
- // Check that GetActivePackage correctly reports upgraded version.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
- // Check that previously active APEX was deleted.
- ASSERT_EQ(-1, access(file_path.c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-
- auto& db = GetApexDatabaseForTesting();
- // Check that upgraded APEX is mounted on top of dm-verity device.
- db.ForallMountedApexes(
- "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, ret->GetPath());
- ASSERT_EQ(data.device_name, "test.apex.rebootless@2_1");
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackageResolvesPathCollision) {
- AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("test.rebootless_apex_v1.apex",
- "test.apex.rebootless@1_1.apex");
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
- ASSERT_TRUE(IsOk(ret));
- UnmountOnTearDown(ret->GetPath());
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@1"));
-
- // 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_TRUE(IsOk(manifest));
- ASSERT_EQ(1u, manifest->version());
-
- // Check that GetActivePackage correctly reports upgraded version.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
- // Check that we correctly resolved active apex path collision.
- ASSERT_EQ(active_apex->GetPath(),
- GetDataDir() + "/test.apex.rebootless@1_2.apex");
-
- // Check that previously active APEX was deleted.
- ASSERT_EQ(-1, access(file_path.c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-
- auto& db = GetApexDatabaseForTesting();
- // Check that upgraded APEX is mounted on top of dm-verity device.
- db.ForallMountedApexes(
- "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, ret->GetPath());
- ASSERT_EQ(data.device_name, "test.apex.rebootless@1_2");
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackageDataVersionActiveSamegrade) {
- AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("test.rebootless_apex_v2.apex");
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_TRUE(IsOk(ret));
- UnmountOnTearDown(ret->GetPath());
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@2"));
-
- // 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_TRUE(IsOk(manifest));
- ASSERT_EQ(2u, manifest->version());
-
- // Check that GetActivePackage correctly reports upgraded version.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
- // Check that previously active APEX was deleted.
- ASSERT_EQ(-1, access(file_path.c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-
- auto& db = GetApexDatabaseForTesting();
- // Check that upgraded APEX is mounted on top of dm-verity device.
- db.ForallMountedApexes(
- "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, ret->GetPath());
- ASSERT_EQ(data.device_name, "test.apex.rebootless@2_1");
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackageUnmountFailsPreInstalledApexActive) {
- std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- unique_fd fd(open("/apex/test.apex.rebootless/apex_manifest.pb",
- O_RDONLY | O_CLOEXEC));
- ASSERT_NE(-1, fd.get());
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_FALSE(IsOk(ret));
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@1"));
-
- // Check that GetActivePackage correctly reports upgraded version.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
-
- // Check that old APEX is still around
- ASSERT_EQ(0, access(file_path.c_str(), F_OK))
- << "Can't access " << file_path << " : " << strerror(errno);
-
- auto& db = GetApexDatabaseForTesting();
- // Check that upgraded APEX is mounted on top of dm-verity device.
- db.ForallMountedApexes("test.apex.rebootless",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, file_path);
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackageUnmountFailedUpdatedApexActive) {
- AddPreInstalledApex("test.rebootless_apex_v1.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- std::string file_path = AddDataApex("test.rebootless_apex_v1.apex");
-
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- {
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
- }
-
- unique_fd fd(open("/apex/test.apex.rebootless/apex_manifest.pb",
- O_RDONLY | O_CLOEXEC));
- ASSERT_NE(-1, fd.get());
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_FALSE(IsOk(ret));
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/test.apex.rebootless",
- "/apex/test.apex.rebootless@1"));
-
- // Check that GetActivePackage correctly reports old apex.
- auto active_apex = GetActivePackage("test.apex.rebootless");
- ASSERT_TRUE(IsOk(active_apex));
- ASSERT_EQ(active_apex->GetPath(), file_path);
-
- // Check that old APEX is still around
- ASSERT_EQ(0, access(file_path.c_str(), F_OK))
- << "Can't access " << file_path << " : " << strerror(errno);
-
- auto& db = GetApexDatabaseForTesting();
- db.ForallMountedApexes(
- "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, file_path);
- ASSERT_EQ(data.device_name, "test.apex.rebootless@1");
- });
-}
-
-TEST_F(ApexdMountTest, InstallPackageUpdatesApexInfoList) {
- auto apex_1 = AddPreInstalledApex("test.rebootless_apex_v1.apex");
- auto apex_2 = AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- UnmountOnTearDown(apex_1);
- UnmountOnTearDown(apex_2);
- 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);
- // Check /apex/apex-info-list.xml was created.
- ASSERT_EQ(0, access("/apex/apex-info-list.xml", F_OK));
-
- auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
- ASSERT_TRUE(IsOk(ret));
- UnmountOnTearDown(ret->GetPath());
-
- 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= */ "test.apex.rebootless",
- /* modulePath= */ apex_1,
- /* preinstalledModulePath= */ apex_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- 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()));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2),
- ApexInfoXmlEq(apex_info_xml_3)));
-}
-
-TEST_F(ApexdMountTest, ActivatePackage) {
- std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
- UnmountOnTearDown(file_path);
-
- auto active_apex = GetActivePackage("com.android.apex.test_package");
- 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_package",
- "/apex/com.android.apex.test_package@1"));
-
- 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, ActivateDeactivateSharedLibsApex) {
- ASSERT_EQ(mkdir("/apex/sharedlibs", 0755), 0);
- ASSERT_EQ(mkdir("/apex/sharedlibs/lib", 0755), 0);
- ASSERT_EQ(mkdir("/apex/sharedlibs/lib64", 0755), 0);
- auto deleter = make_scope_guard([]() {
- std::error_code ec;
- fs::remove_all("/apex/sharedlibs", ec);
- if (ec) {
- LOG(ERROR) << "Failed to delete /apex/sharedlibs : " << ec;
- }
- });
-
- std::string file_path = AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
- UnmountOnTearDown(file_path);
- ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-
- auto active_apex = GetActivePackage("com.android.apex.test.sharedlibs");
- 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_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);
-}
-
-TEST_F(ApexdMountTest, RemoveInactiveDataApex) {
- AddPreInstalledApex("com.android.apex.compressed.v2.capex");
- // Add a decompressed apex that will not be mounted, so should be removed
- auto decompressed_apex = StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
- decompressed_apex);
- // Add a decompressed apex that will be mounted, so should be not be removed
- auto active_decompressed_apex = StringPrintf(
- "%s/com.android.apex.compressed@2%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
- active_decompressed_apex);
- // Apex that do not have kDecompressedApexPackageSuffix, should not be removed
- // from decompression_dir
- auto decompressed_different_suffix =
- StringPrintf("%s/com.android.apex.compressed@2%s",
- GetDecompressionDir().c_str(), kApexPackageSuffix);
- fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
- decompressed_different_suffix);
-
- AddPreInstalledApex("apex.apexd_test.apex");
- auto data_apex = AddDataApex("apex.apexd_test.apex");
- auto active_data_apex = AddDataApex("apex.apexd_test_v2.apex");
-
- // Activate some of the apex
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
- UnmountOnTearDown(active_decompressed_apex);
- UnmountOnTearDown(active_data_apex);
- ASSERT_TRUE(IsOk(ActivatePackage(active_decompressed_apex)));
- ASSERT_TRUE(IsOk(ActivatePackage(active_data_apex)));
- // Clean up inactive apex packages
- RemoveInactiveDataApex();
-
- // Verify inactive apex packages have been deleted
- ASSERT_TRUE(*PathExists(active_decompressed_apex));
- ASSERT_TRUE(*PathExists(active_data_apex));
- ASSERT_TRUE(*PathExists(decompressed_different_suffix));
- ASSERT_FALSE(*PathExists(decompressed_apex));
- ASSERT_FALSE(*PathExists(data_apex));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapOnlyPreInstalledApexes) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapFailsToScanPreInstalledApexes) {
- AddPreInstalledApex("apex.apexd_test.apex");
- AddPreInstalledApex("apex.apexd_test_corrupt_superblock_apex.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 1);
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasHigherVersion) {
- 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");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@2",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- 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));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2),
- ApexInfoXmlEq(apex_info_xml_3)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasSameVersion) {
- 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.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
-
- 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"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- 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));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2),
- ApexInfoXmlEq(apex_info_xml_3)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSystemHasHigherVersion) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test_v2.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- AddDataApex("apex.apexd_test.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@2",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 2, /* versionName= */ "2",
- /* 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasSameVersionButDifferentKey) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- AddDataApex("apex.apexd_test_different_key.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest,
- OnOtaChrootBootstrapDataHasHigherVersionButDifferentKey) {
- 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_different_key_v2.apex");
-
- {
- auto apex = ApexFile::Open(apex_path_3);
- ASSERT_TRUE(IsOk(apex));
- ASSERT_EQ(static_cast<uint64_t>(apex->GetManifest().version()), 2ULL);
- }
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataApexWithoutPreInstalledApex) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- AddDataApex("apex.apexd_test_different_app.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_1);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@1"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapPreInstalledSharedLibsApex) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 = AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
- std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@2",
- "/apex/com.android.apex.test.sharedlibs@1"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2),
- ApexInfoXmlEq(apex_info_xml_3)));
-
- ASSERT_EQ(access("/apex/sharedlibs", F_OK), 0);
-
- // Check /apex/sharedlibs is populated properly.
- std::vector<std::string> sharedlibs;
- for (const auto& p : fs::recursive_directory_iterator("/apex/sharedlibs")) {
- if (fs::is_symlink(p)) {
- auto src = fs::read_symlink(p.path());
- ASSERT_EQ(p.path().filename(), src.filename());
- sharedlibs.push_back(p.path().parent_path().string() + "->" +
- src.parent_path().string());
- }
- }
-
- std::vector<std::string> expected = {
- "/apex/sharedlibs/lib/libsharedlibtest.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib/libsharedlibtest.so",
- "/apex/sharedlibs/lib/libc++.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib/libc++.so",
- };
-
- // On 64bit devices we also have lib64.
- if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
- expected.push_back(
- "/apex/sharedlibs/lib64/libsharedlibtest.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib64/libsharedlibtest.so");
- expected.push_back(
- "/apex/sharedlibs/lib64/libc++.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib64/libc++.so");
- }
- ASSERT_THAT(sharedlibs, UnorderedElementsAreArray(expected));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSharedLibsApexBothVersions) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 = AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
- std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
- std::string apex_path_4 =
- AddDataApex("com.android.apex.test.sharedlibs_generated.v2.libvY.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
- UnmountOnTearDown(apex_path_4);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@2",
- "/apex/com.android.apex.test.sharedlibs@1",
- "/apex/com.android.apex.test.sharedlibs@2"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- 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));
- 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2),
- ApexInfoXmlEq(apex_info_xml_3),
- ApexInfoXmlEq(apex_info_xml_4)));
-
- ASSERT_EQ(access("/apex/sharedlibs", F_OK), 0);
-
- // Check /apex/sharedlibs is populated properly.
- // Because we don't want to hardcode full paths (they are pretty long and have
- // a hash in them which might change if new prebuilts are dropped in), the
- // assertion logic is a little bit clunky.
- std::vector<std::string> sharedlibs;
- for (const auto& p : fs::recursive_directory_iterator("/apex/sharedlibs")) {
- if (fs::is_symlink(p)) {
- auto src = fs::read_symlink(p.path());
- ASSERT_EQ(p.path().filename(), src.filename());
- sharedlibs.push_back(p.path().parent_path().string() + "->" +
- src.parent_path().string());
- }
- }
-
- std::vector<std::string> expected = {
- "/apex/sharedlibs/lib/libsharedlibtest.so->"
- "/apex/com.android.apex.test.sharedlibs@2/lib/libsharedlibtest.so",
- "/apex/sharedlibs/lib/libsharedlibtest.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib/libsharedlibtest.so",
- "/apex/sharedlibs/lib/libc++.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib/libc++.so",
- };
- // On 64bit devices we also have lib64.
- if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
- expected.push_back(
- "/apex/sharedlibs/lib64/libsharedlibtest.so->"
- "/apex/com.android.apex.test.sharedlibs@2/lib64/libsharedlibtest.so");
- expected.push_back(
- "/apex/sharedlibs/lib64/libsharedlibtest.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib64/libsharedlibtest.so");
- expected.push_back(
- "/apex/sharedlibs/lib64/libc++.so->"
- "/apex/com.android.apex.test.sharedlibs@1/lib64/libc++.so");
- }
-
- ASSERT_THAT(sharedlibs, UnorderedElementsAreArray(expected));
-}
-
-// Test when we move from uncompressed APEX to CAPEX via ota
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapOnlyCompressedApexes) {
- std::string apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Decompressed APEX should be mounted from decompression_dir
- std::string decompressed_apex =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(decompressed_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1.chroot");
- });
-}
-
-// Test we decompress only once even if OnOtaChrootBootstrap is called multiple
-// times
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDecompressOnlyOnceMultipleCalls) {
- std::string apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Decompressed OTA APEX should be mounted
- std::string decompressed_ota_apex =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_ota_apex);
-
- // Capture the creation time of the OTA APEX
- std::error_code ec;
- auto last_write_time_1 = fs::last_write_time(decompressed_ota_apex, ec);
- ASSERT_FALSE(ec) << "Failed to capture last write time of "
- << decompressed_ota_apex;
-
- // Call OnOtaChrootBootstrap again. Since we do not hardlink decompressed APEX
- // to /data/apex/active directory when in chroot, when selecting apex for
- // activation, we will end up selecting compressed APEX again.
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Compare write time to ensure we did not decompress again
- auto last_write_time_2 = fs::last_write_time(decompressed_ota_apex, ec);
- ASSERT_FALSE(ec) << "Failed to capture last write time of "
- << decompressed_ota_apex << ec.message();
- ASSERT_EQ(last_write_time_1, last_write_time_2);
-}
-
-// Test when we upgrade existing CAPEX to higher version via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapUpgradeCapex) {
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed.v1.capex",
- previous_built_in_dir.path);
- // Place a higher version capex in current built_in_dir
- std::string apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Upgraded decompressed APEX should be mounted from decompression dir
- std::string decompressed_active_apex =
- StringPrintf("%s/com.android.apex.compressed@2%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@2"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_active_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@2.chroot");
- });
-}
-
-// Test when we update existing CAPEX to same version via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSamegradeCapex) {
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed.v1.capex",
- previous_built_in_dir.path);
- // Place a same version capex in current built_in_dir, under a different name
- auto apex_path =
- StringPrintf("%s/different-name.capex", GetBuiltInDir().c_str());
- fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), apex_path);
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Previously decompressed APEX should be mounted from decompression_dir
- std::string decompressed_active_apex = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_active_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1.chroot");
- });
-}
-
-// Test when we update existing CAPEX to same version, but different digest
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSamegradeCapexDifferentDigest) {
- TemporaryDir previous_built_in_dir;
- auto different_digest_apex_path = PrepareCompressedApex(
- "com.android.apex.compressed.v1_different_digest.capex",
- previous_built_in_dir.path);
- // Place a same version capex in current built_in_dir, which has different
- // digest
- auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // New decompressed ota APEX should be mounted with kOtaApexPackageSuffix
- std::string decompressed_ota_apex =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_ota_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_ota_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_ota_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_ota_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1.chroot");
- });
-
- // Ensure decompressed apex has same digest as pre-installed
- auto pre_installed_apex = ApexFile::Open(apex_path);
- auto decompressed_apex = ApexFile::Open(decompressed_ota_apex);
- auto different_digest_apex = ApexFile::Open(different_digest_apex_path);
- ASSERT_EQ(
- pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
- GetRootDigest(*decompressed_apex));
- ASSERT_NE(
- pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
- GetRootDigest(*different_digest_apex));
-
- // Ensure we didn't remove previous decompressed APEX
- std::string previous_decompressed_apex = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- auto path_exists = PathExists(previous_decompressed_apex);
- ASSERT_TRUE(*path_exists);
-}
-
-// Test when we update existing CAPEX to same version, but different key via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSamegradeCapexDifferentKey) {
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed_different_key.capex",
- previous_built_in_dir.path);
- // 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_EQ(OnOtaChrootBootstrap(), 0);
-
- // New decompressed APEX should be mounted from ota_reserved directory
- std::string decompressed_active_apex =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_active_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1.chroot");
- });
-}
-
-// Test when we remove CAPEX via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapCapexToApex) {
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed.v1.capex",
- previous_built_in_dir.path);
- // Place a uncompressed version apex in current built_in_dir
- std::string apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // New uncompressed APEX should be mounted
- UnmountOnTearDown(apex_path);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_uncompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ apex_path,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_uncompressed)));
-}
-
-TEST_F(ApexdMountTest,
- OnOtaChrootBootstrapDecompressedApexVersionDifferentThanCapex) {
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed.v2.capex",
- previous_built_in_dir.path);
- // Place a lower version capex in current built_in_dir, so that previously
- // decompressed APEX has higher version but still doesn't get picked during
- // selection.
- std::string apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Pre-installed CAPEX should be decompressed again and mounted from
- // decompression_dir
- std::string decompressed_active_apex =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_active_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-}
-
-// Test when we update CAPEX and there is a higher version present in data
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHigherThanCapex) {
- auto system_apex_path =
- PrepareCompressedApex("com.android.apex.compressed.v1.capex");
- auto data_apex_path =
- AddDataApex("com.android.apex.compressed.v2_original.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Data APEX should be mounted
- UnmountOnTearDown(data_apex_path);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@2"));
-
- 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_data = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ data_apex_path,
- /* preinstalledModulePath= */ system_apex_path,
- /* versionCode= */ 2, /* versionName= */ "2",
- /* 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));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_data),
- ApexInfoXmlEq(apex_info_xml_system)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, data_apex_path);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@2.chroot");
- });
-}
-
-// Test when we update CAPEX and there is a lower version present in data
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataLowerThanCapex) {
- auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v2.capex");
- AddDataApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Decompressed APEX should be mounted from reserved dir
- std::string decompressed_active_apex =
- StringPrintf("%s/com.android.apex.compressed@2%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@2"));
-
- 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 = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_active_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@2.chroot");
- });
-}
-
-// Test when we update CAPEX and there is a same version present in data
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataSameAsCapex) {
- auto system_apex_path =
- PrepareCompressedApex("com.android.apex.compressed.v1.capex");
- auto data_apex_path =
- AddDataApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- // Data APEX should be mounted
- UnmountOnTearDown(data_apex_path);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_data = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ data_apex_path,
- /* preinstalledModulePath= */ system_apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_data),
- ApexInfoXmlEq(apex_info_xml_system)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, data_apex_path);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1.chroot");
- });
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasDifferentKeyThanCapex) {
- AddDataApex("com.android.apex.compressed_different_key.capex");
- // 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_EQ(OnOtaChrootBootstrap(), 0);
-
- // New decompressed APEX should be mounted from ota_reserved directory
- std::string decompressed_active_apex =
- StringPrintf("%s/com.android.apex.compressed@1%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1"));
-
- 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_decompressed = com::android::apex::ApexInfo(
- /* moduleName= */ "com.android.apex.compressed",
- /* modulePath= */ decompressed_active_apex,
- /* preinstalledModulePath= */ apex_path,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* isFactory= */ true, /* isActive= */ true,
- GetMTime(decompressed_active_apex));
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1.chroot");
- });
-}
-
-static std::string GetSelinuxContext(const std::string& file) {
- char* ctx;
- if (getfilecon(file.c_str(), &ctx) < 0) {
- PLOG(ERROR) << "Failed to getfilecon " << file;
- return "";
- }
- std::string result(ctx);
- freecon(ctx);
- return result;
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSelinuxLabelsAreCorrect) {
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 = AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
- std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
- EXPECT_EQ(GetSelinuxContext("/apex/apex-info-list.xml"),
- "u:object_r:apex_info_file:s0");
-
- EXPECT_EQ(GetSelinuxContext("/apex/sharedlibs"),
- "u:object_r:apex_mnt_dir:s0");
-
- EXPECT_EQ(GetSelinuxContext("/apex/com.android.apex.test_package"),
- "u:object_r:system_file:s0");
- EXPECT_EQ(GetSelinuxContext("/apex/com.android.apex.test_package@2"),
- "u:object_r:system_file:s0");
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDmDevicesHaveCorrectName) {
- 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");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
-
- MountedApexDatabase& db = GetApexDatabaseForTesting();
- // com.android.apex.test_package_2 should be mounted directly on top of loop
- // device.
- db.ForallMountedApexes("com.android.apex.test_package_2",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_THAT(data.device_name, IsEmpty());
- ASSERT_THAT(data.loop_name, StartsWith("/dev"));
- });
- // com.android.apex.test_package should be mounted on top of dm-verity device.
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.device_name,
- "com.android.apex.test_package@2.chroot");
- ASSERT_THAT(data.loop_name, StartsWith("/dev"));
- });
-}
-
-TEST_F(ApexdMountTest,
- OnOtaChrootBootstrapFailsToActivatePreInstalledApexKeepsGoing) {
- std::string apex_path_1 =
- AddPreInstalledApex("apex.apexd_test_manifest_mismatch.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
- UnmountOnTearDown(apex_path_2);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 137, /* versionName= */ "1",
- /* 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest,
- OnOtaChrootBootstrapFailsToActivateDataApexFallsBackToPreInstalled) {
- 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_manifest_mismatch.apex");
-
- ASSERT_EQ(OnOtaChrootBootstrap(), 0);
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- 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= */ apex_path_1,
- /* preinstalledModulePath= */ apex_path_1,
- /* versionCode= */ 1, /* versionName= */ "1",
- /* 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));
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-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";
-
- ASSERT_EQ(mkdir(apex_dir_1.c_str(), 0755), 0);
- ASSERT_EQ(mkdir(apex_dir_2.c_str(), 0755), 0);
-
- auto write_manifest_fn = [&](const std::string& apex_dir,
- const std::string& module_name, int version) {
- using ::apex::proto::ApexManifest;
-
- ApexManifest manifest;
- manifest.set_name(module_name);
- manifest.set_version(version);
- manifest.set_versionname(std::to_string(version));
-
- std::string out;
- manifest.SerializeToString(&out);
- ASSERT_TRUE(WriteStringToFile(out, apex_dir + "/apex_manifest.pb"));
- };
-
- 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(OnOtaChrootBootstrapFlattenedApex(), 0);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package_2"));
-
- ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
- ASSERT_EQ(GetSelinuxContext("/apex/apex-info-list.xml"),
- "u:object_r:apex_info_file:s0");
-
- 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= */ apex_dir_1,
- /* preinstalledModulePath= */ apex_dir_1,
- /* versionCode= */ 2, /* versionName= */ "2",
- /* isFactory= */ true, /* isActive= */ true,
- /* 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);
-
- ASSERT_THAT(info_list->getApexInfo(),
- UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
- ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnStartOnlyPreInstalledApexes) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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, OnStartDataHasHigherVersion) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- 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");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
-
- 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@2",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasWrongSHA) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string apex_path = AddPreInstalledApex("com.android.apex.cts.shim.apex");
- AddDataApex("com.android.apex.cts.shim.v2_wrong_sha.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- UnmountOnTearDown(apex_path);
- OnStart();
-
- // Check system shim apex is activated instead of the data one.
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.cts.shim",
- "/apex/com.android.apex.cts.shim@1"));
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasSameVersion) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- 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.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_2);
- UnmountOnTearDown(apex_path_3);
-
- 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"));
-
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from data apex, not pre-installed one.
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path_3);
- });
-}
-
-TEST_F(ApexdMountTest, OnStartSystemHasHigherVersion) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test_v2.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- AddDataApex("apex.apexd_test.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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@2",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from pre-installed one.
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path_1);
- });
-}
-
-TEST_F(ApexdMountTest, OnStartFailsToActivateApexOnDataFallsBackToBuiltIn) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path_2 =
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- AddDataApex("apex.apexd_test_manifest_mismatch.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from pre-installed apex.
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path_1);
- });
-}
-
-TEST_F(ApexdMountTest, OnStartApexOnDataHasWrongKeyFallsBackToBuiltIn) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- 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_different_key_v2.apex");
-
- {
- auto apex = ApexFile::Open(apex_path_3);
- ASSERT_TRUE(IsOk(apex));
- ASSERT_EQ(static_cast<uint64_t>(apex->GetManifest().version()), 2ULL);
- }
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from pre-installed apex.
- db.ForallMountedApexes("com.android.apex.test_package",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path_1);
- });
-}
-
-TEST_F(ApexdMountTest, OnStartOnlyPreInstalledCapexes) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string apex_path_1 =
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // 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"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1");
- });
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasHigherVersionThanCapex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- std::string apex_path_2 =
- AddDataApex("com.android.apex.compressed.v2_original.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- UnmountOnTearDown(apex_path_2);
-
- ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@2"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from data apex.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path_2);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@2");
- });
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasSameVersionAsCapex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- std::string apex_path_2 =
- AddDataApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Data APEX should be mounted
- UnmountOnTearDown(apex_path_2);
-
- 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"));
-
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from data apex, not pre-installed one.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path_2);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1");
- });
-}
-
-TEST_F(ApexdMountTest, OnStartSystemHasHigherVersionCapexThanData) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- std::string apex_path_1 =
- AddPreInstalledApex("com.android.apex.compressed.v2.capex");
- AddDataApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Decompressed APEX should be mounted
- std::string decompressed_active_apex = StringPrintf(
- "%s/com.android.apex.compressed@2%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@2"));
-
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from compressed apex
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@2");
- });
-}
-
-TEST_F(ApexdMountTest, OnStartFailsToActivateApexOnDataFallsBackToCapex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- AddDataApex("com.android.apex.compressed.v2_manifest_mismatch.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // 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"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex. It should also be mounted
- // on dm-verity device.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1");
- });
-}
-
-// Test scenario when we fallback to capex but it already has a decompressed
-// version on data
-TEST_F(ApexdMountTest, OnStartFallbackToAlreadyDecompressedCapex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- PrepareCompressedApex("com.android.apex.compressed.v1.capex");
- AddDataApex("com.android.apex.compressed.v2_manifest_mismatch.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // 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"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1");
- });
-}
-
-// Test scenario when we fallback to capex but it has same version as corrupt
-// data apex
-TEST_F(ApexdMountTest, OnStartFallbackToCapexSameVersion) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- AddPreInstalledApex("com.android.apex.compressed.v2.capex");
- // Add data apex using the common naming convention for /data/apex/active
- // directory
- fs::copy(GetTestFile("com.android.apex.compressed.v2_manifest_mismatch.apex"),
- GetDataDir() + "/com.android.apex.compressed@2.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Decompressed APEX should be mounted
- std::string decompressed_active_apex = StringPrintf(
- "%s/com.android.apex.compressed@2%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@2"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@2");
- });
-}
-
-TEST_F(ApexdMountTest, OnStartCapexToApex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed.v1.capex",
- previous_built_in_dir.path);
- auto apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Uncompressed APEX should be mounted
- UnmountOnTearDown(apex_path);
-
- 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"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from decompressed apex.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path);
- ASSERT_THAT(data.device_name, IsEmpty());
- });
-}
-
-// Test to ensure we do not mount decompressed APEX from /data/apex/active
-TEST_F(ApexdMountTest, OnStartOrphanedDecompressedApexInActiveDirectory) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Place a decompressed APEX in /data/apex/active. This apex should not
- // be mounted since it's not in correct location. Instead, the
- // pre-installed APEX should be mounted.
- auto decompressed_apex_in_active_dir =
- StringPrintf("%s/com.android.apex.compressed@1%s", GetDataDir().c_str(),
- kDecompressedApexPackageSuffix);
- fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
- decompressed_apex_in_active_dir);
- auto apex_path =
- AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Pre-installed APEX should be mounted
- UnmountOnTearDown(apex_path);
- auto& db = GetApexDatabaseForTesting();
- // Check that pre-installed APEX has been activated
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, apex_path);
- ASSERT_THAT(data.device_name, IsEmpty());
- });
-}
-
-// Test scenario when decompressed version has different version than
-// pre-installed CAPEX
-TEST_F(ApexdMountTest, OnStartDecompressedApexVersionDifferentThanCapex) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- TemporaryDir previous_built_in_dir;
- PrepareCompressedApex("com.android.apex.compressed.v2.capex",
- previous_built_in_dir.path);
- auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Existing higher version decompressed APEX should be ignored and new
- // pre-installed CAPEX should be decompressed and 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"));
- auto& db = GetApexDatabaseForTesting();
- // Check that it was mounted from newly decompressed apex.
- db.ForallMountedApexes("com.android.apex.compressed",
- [&](const MountedApexData& data, bool latest) {
- ASSERT_TRUE(latest);
- ASSERT_EQ(data.full_path, decompressed_active_apex);
- ASSERT_EQ(data.device_name,
- "com.android.apex.compressed@1");
- });
-}
-
-// Test that ota_apex is persisted until slot switch
-TEST_F(ApexdMountTest, OnStartOtaApexKeptUntilSlotSwitch) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Imagine current system has v1 capex and we have v2 incoming via ota
- auto old_capex = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- auto ota_apex_path =
- StringPrintf("%s/com.android.apex.compressed@2%s",
- GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
- fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
- ota_apex_path.c_str());
-
- 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
- // activate it. We need to make sure that activated APEXes are cleaned up
- // after test finishes.
- auto old_decompressed_apex = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- auto new_decompressed_apex = StringPrintf(
- "%s/com.android.apex.compressed@2%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- UnmountOnTearDown(old_decompressed_apex);
- UnmountOnTearDown(new_decompressed_apex);
-
- // First try starting without slot switch. Since we are booting with
- // old pre-installed capex, ota_apex should not be deleted
- OnStart();
- auto path_exists = PathExists(ota_apex_path);
- ASSERT_TRUE(*path_exists);
-
- // When we switch slot, the pre-installed APEX will match ota_apex
- // and the ota_apex will end up getting renamed.
- RemoveFileIfExists(old_capex);
- AddPreInstalledApex("com.android.apex.compressed.v2.capex");
- ApexFileRepository::GetInstance().Reset(GetDecompressionDir());
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
- OnStart();
- path_exists = PathExists(ota_apex_path);
- ASSERT_FALSE(*path_exists);
-}
-
-// Test scenario when decompressed version has same version but different
-// digest
-TEST_F(ApexdMountTest,
- OnStartDecompressedApexVersionSameAsCapexDifferentDigest) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- // Push a CAPEX to system without decompressing it
- auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
- auto pre_installed_apex = ApexFile::Open(apex_path);
- // Now push an APEX with different root digest as decompressed APEX
- auto decompressed_apex_path = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- fs::copy(GetTestFile(
- "com.android.apex.compressed.v1_different_digest_original.apex"),
- decompressed_apex_path);
- auto different_digest_apex = ApexFile::Open(decompressed_apex_path);
- auto different_digest = GetRootDigest(*different_digest_apex);
- ASSERT_NE(
- pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
- different_digest);
-
- ASSERT_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Existing same version decompressed APEX with different root digest should
- // be ignored and the pre-installed CAPEX should be decompressed again.
- UnmountOnTearDown(decompressed_apex_path);
-
- // Ensure decompressed apex has same digest as pre-installed
- auto decompressed_apex = ApexFile::Open(decompressed_apex_path);
- ASSERT_EQ(
- pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
- GetRootDigest(*decompressed_apex));
- ASSERT_NE(GetRootDigest(*decompressed_apex), different_digest);
-}
-
-// Test when decompressed APEX has different key than CAPEX
-TEST_F(ApexdMountTest, OnStartDecompressedApexVersionSameAsCapexDifferentKey) {
- MockCheckpointInterface checkpoint_interface;
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- TemporaryDir previous_built_in_dir;
- auto different_key_apex_path =
- PrepareCompressedApex("com.android.apex.compressed_different_key.capex",
- previous_built_in_dir.path);
- // 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_RESULT_OK(
- ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
- OnStart();
-
- // Existing same version decompressed APEX should be ignored and new
- // pre-installed CAPEX should be decompressed and mounted
- std::string decompressed_active_apex = StringPrintf(
- "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
- kDecompressedApexPackageSuffix);
- UnmountOnTearDown(decompressed_active_apex);
-
- // Ensure decompressed apex has same digest as pre-installed
- auto pre_installed_apex = ApexFile::Open(apex_path);
- auto decompressed_apex = ApexFile::Open(decompressed_active_apex);
- auto different_key_apex = ApexFile::Open(different_key_apex_path);
- ASSERT_EQ(
- pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
- GetRootDigest(*decompressed_apex));
- ASSERT_NE(
- pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
- GetRootDigest(*different_key_apex));
-}
-
-TEST_F(ApexdMountTest, PopulateFromMountsChecksPathPrefix) {
- AddPreInstalledApex("apex.apexd_test.apex");
- std::string apex_path = AddDataApex("apex.apexd_test_v2.apex");
-
- // Mount an apex from decomrpession_dir
- PrepareCompressedApex("com.android.apex.compressed.v1.capex");
- std::string decompressed_apex =
- StringPrintf("%s/com.android.apex.compressed@1.decompressed.apex",
- GetDecompressionDir().c_str());
-
- // Mount an apex from some other directory
- TemporaryDir td;
- AddPreInstalledApex("apex.apexd_test_different_app.apex");
- fs::copy(GetTestFile("apex.apexd_test_different_app.apex"), td.path);
- std::string other_apex =
- StringPrintf("%s/apex.apexd_test_different_app.apex", td.path);
-
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
- 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
- // the database. We will need to tear it down manually.
- std::optional<MountedApexData> other_apex_mount_data;
- db.ForallMountedApexes(
- "com.android.apex.test_package_2",
- [&other_apex_mount_data](const MountedApexData& data, bool latest) {
- if (latest) {
- other_apex_mount_data.emplace(data);
- }
- });
- UnmountOnTearDown(apex_path);
- UnmountOnTearDown(decompressed_apex);
- ASSERT_TRUE(other_apex_mount_data.has_value());
- auto deleter = make_scope_guard([&other_apex_mount_data]() {
- if (!other_apex_mount_data.has_value()) {
- return;
- }
- if (umount2("/apex/com.android.apex.test_package_2", 0) != 0) {
- PLOG(ERROR) << "Failed to unmount /apex/com.android.apex.test_package_2";
- }
- auto res = Unmount(*other_apex_mount_data, /* deferred= */ false);
- if (!res.ok()) {
- LOG(ERROR) << res.error();
- }
- });
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@2",
- "/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-
- // Clear the database before calling PopulateFromMounts
- db.Reset();
-
- // Populate from mount
- db.PopulateFromMounts(GetDataDir(), GetDecompressionDir(), GetHashTreeDir());
-
- // Count number of package and collect package names
- int package_count = 0;
- std::vector<std::string> mounted_paths;
- db.ForallMountedApexes([&](const std::string& package,
- const MountedApexData& data, bool latest) {
- package_count++;
- mounted_paths.push_back(data.full_path);
- });
- ASSERT_EQ(package_count, 2);
- ASSERT_THAT(mounted_paths,
- UnorderedElementsAre(apex_path, decompressed_apex));
-}
-
-TEST_F(ApexdMountTest, UnmountAll) {
- 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");
-
- // Mount an apex from decomrpession_dir
- PrepareCompressedApex("com.android.apex.compressed.v1.capex");
- std::string decompressed_apex =
- StringPrintf("%s/com.android.apex.compressed@1.decompressed.apex",
- GetDecompressionDir().c_str());
-
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
- 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);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test_package",
- "/apex/com.android.apex.test_package@2",
- "/apex/com.android.apex.compressed",
- "/apex/com.android.apex.compressed@1",
- "/apex/com.android.apex.test_package_2",
- "/apex/com.android.apex.test_package_2@1"));
-
- auto& db = GetApexDatabaseForTesting();
- // UnmountAll expects apex database to empty, hence this reset.
- db.Reset();
-
- ASSERT_EQ(0, UnmountAll());
-
- auto new_apex_mounts = GetApexMounts();
- ASSERT_EQ(new_apex_mounts.size(), 0u);
-}
-
-TEST_F(ApexdMountTest, UnmountAllSharedLibsApex) {
- ASSERT_EQ(mkdir("/apex/sharedlibs", 0755), 0);
- ASSERT_EQ(mkdir("/apex/sharedlibs/lib", 0755), 0);
- ASSERT_EQ(mkdir("/apex/sharedlibs/lib64", 0755), 0);
- auto deleter = make_scope_guard([]() {
- std::error_code ec;
- fs::remove_all("/apex/sharedlibs", ec);
- if (ec) {
- LOG(ERROR) << "Failed to delete /apex/sharedlibs : " << ec;
- }
- });
-
- std::string apex_path_1 = AddPreInstalledApex(
- "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
- std::string apex_path_2 =
- AddDataApex("com.android.apex.test.sharedlibs_generated.v2.libvY.apex");
-
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
- ASSERT_TRUE(IsOk(ActivatePackage(apex_path_1)));
- ASSERT_TRUE(IsOk(ActivatePackage(apex_path_2)));
- UnmountOnTearDown(apex_path_1);
- UnmountOnTearDown(apex_path_2);
-
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts,
- UnorderedElementsAre("/apex/com.android.apex.test.sharedlibs@1",
- "/apex/com.android.apex.test.sharedlibs@2"));
-
- auto& db = GetApexDatabaseForTesting();
- // UnmountAll expects apex database to empty, hence this reset.
- db.Reset();
-
- ASSERT_EQ(0, UnmountAll());
-
- auto new_apex_mounts = GetApexMounts();
- ASSERT_EQ(new_apex_mounts.size(), 0u);
-}
-
-class ApexActivationFailureTests : public ApexdMountTest {};
-
-TEST_F(ApexActivationFailureTests, BuildFingerprintDifferent) {
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->SetBuildFingerprint("wrong fingerprint");
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("APEX build fingerprint has changed"));
-}
-
-TEST_F(ApexActivationFailureTests, ApexFileMissingInStagingDirectory) {
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
- // Delete the apex file in staging directory
- DeleteDirContent(GetStagedDir(123));
-
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("No APEX packages found"));
-}
-
-TEST_F(ApexActivationFailureTests, MultipleApexFileInStagingDirectory) {
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- CreateStagedSession("com.android.apex.compressed.v1_original.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("More than one APEX package found"));
-}
-
-TEST_F(ApexActivationFailureTests, PostInstallFailsForApex) {
- auto apex_session =
- CreateStagedSession("apex.apexd_test_corrupt_superblock_apex.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("Postinstall failed for session"));
-}
-
-TEST_F(ApexActivationFailureTests, CorruptedApexCannotBeStaged) {
- auto apex_session = CreateStagedSession("corrupted_b146895998.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("Activation failed for packages"));
-}
-
-TEST_F(ApexActivationFailureTests, ActivatePackageImplFails) {
- auto shim_path = AddPreInstalledApex("com.android.apex.cts.shim.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
- auto apex_session =
- CreateStagedSession("com.android.apex.cts.shim.v2_wrong_sha.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- UnmountOnTearDown(shim_path);
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("Failed to activate packages"));
- ASSERT_THAT(apex_session->GetErrorMessage(),
- HasSubstr("has unexpected SHA512 hash"));
-}
-
-TEST_F(ApexActivationFailureTests,
- StagedSessionFailsWhenNotInFsCheckpointMode) {
- MockCheckpointInterface checkpoint_interface;
- checkpoint_interface.SetSupportsCheckpoint(true);
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- auto pre_installed_apex = AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- UnmountOnTearDown(pre_installed_apex);
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_EQ(apex_session->GetState(), SessionState::ACTIVATION_FAILED);
- ASSERT_THAT(
- apex_session->GetErrorMessage(),
- HasSubstr("Cannot install apex session if not in fs-checkpoint mode"));
-}
-
-TEST_F(ApexActivationFailureTests, StagedSessionRevertsWhenInFsRollbackMode) {
- MockCheckpointInterface checkpoint_interface;
- checkpoint_interface.SetSupportsCheckpoint(true);
- checkpoint_interface.SetNeedsRollback(true);
- // Need to call InitializeVold before calling OnStart
- InitializeVold(&checkpoint_interface);
-
- auto pre_installed_apex = AddPreInstalledApex("apex.apexd_test.apex");
- auto& instance = ApexFileRepository::GetInstance();
- ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
- auto apex_session = CreateStagedSession("apex.apexd_test.apex", 123);
- apex_session->UpdateStateAndCommit(SessionState::STAGED);
-
- UnmountOnTearDown(pre_installed_apex);
- OnStart();
-
- apex_session = ApexSession::GetSession(123);
- ASSERT_EQ(apex_session->GetState(), SessionState::REVERTED);
-}
-
-} // namespace apex
-} // namespace android
diff --git a/apexd/apexd_test_utils.h b/apexd/apexd_test_utils.h
index 5e3689d3..0e43477d 100644
--- a/apexd/apexd_test_utils.h
+++ b/apexd/apexd_test_utils.h
@@ -14,34 +14,14 @@
* limitations under the License.
*/
-#include <filesystem>
-#include <fstream>
-
-#include <asm-generic/errno-base.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <sched.h>
-#include <sys/mount.h>
-
-#include <android-base/errors.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/result.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
#include <android/apex/ApexInfo.h>
#include <android/apex/ApexSessionInfo.h>
#include <binder/IServiceManager.h>
-#include <selinux/android.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
-#include "apex_file.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 {
@@ -52,7 +32,6 @@ 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) {
@@ -106,22 +85,6 @@ MATCHER_P(ApexInfoEq, other, "") {
arg, result_listener);
}
-MATCHER_P(ApexFileEq, other, "") {
- return ExplainMatchResult(
- AllOf(Property("path", &ApexFile::GetPath, Eq(other.get().GetPath())),
- Property("image_offset", &ApexFile::GetImageOffset,
- Eq(other.get().GetImageOffset())),
- Property("image_size", &ApexFile::GetImageSize,
- Eq(other.get().GetImageSize())),
- Property("fs_type", &ApexFile::GetFsType,
- Eq(other.get().GetFsType())),
- Property("public_key", &ApexFile::GetBundledPublicKey,
- Eq(other.get().GetBundledPublicKey())),
- Property("is_compressed", &ApexFile::IsCompressed,
- Eq(other.get().IsCompressed()))),
- arg, result_listener);
-}
-
inline ApexSessionInfo CreateSessionInfo(int session_id) {
ApexSessionInfo info;
info.sessionId = session_id;
@@ -165,194 +128,5 @@ inline void PrintTo(const ApexInfo& apex, std::ostream* os) {
*os << "}";
}
-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 Error() << "Could not open one of the file";
- }
-
- std::istreambuf_iterator<char> begin1(file1);
- std::istreambuf_iterator<char> begin2(file2);
-
- return std::equal(begin1, std::istreambuf_iterator<char>(), begin2);
-}
-
-inline android::base::Result<std::string> GetCurrentMountNamespace() {
- std::string result;
- if (!android::base::Readlink("/proc/self/ns/mnt", &result)) {
- return android::base::ErrnoError() << "Failed to read /proc/self/ns/mnt";
- }
- return result;
-}
-
-// A helper class to switch back to the original mount namespace of a process
-// upon exiting current scope.
-class MountNamespaceRestorer final {
- public:
- explicit MountNamespaceRestorer() {
- original_namespace_.reset(open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC));
- if (original_namespace_.get() < 0) {
- PLOG(ERROR) << "Failed to open /proc/self/ns/mnt";
- }
- }
-
- ~MountNamespaceRestorer() {
- if (original_namespace_.get() != -1) {
- if (setns(original_namespace_.get(), CLONE_NEWNS) == -1) {
- PLOG(ERROR) << "Failed to switch back to " << original_namespace_.get();
- }
- }
- }
-
- private:
- android::base::unique_fd original_namespace_;
- DISALLOW_COPY_AND_ASSIGN(MountNamespaceRestorer);
-};
-
-inline std::vector<std::string> GetApexMounts() {
- std::vector<std::string> apex_mounts;
- std::string mount_info;
- if (!android::base::ReadFileToString("/proc/self/mountinfo", &mount_info)) {
- return apex_mounts;
- }
- for (const auto& line : android::base::Split(mount_info, "\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 && android::base::StartsWith(tokens[4], "/apex/")) {
- apex_mounts.push_back(tokens[4]);
- }
- }
- return apex_mounts;
-}
-
-// Sets up a test environment for unit testing logic around mounting/unmounting
-// apexes. For examples of usage see apexd_test.cpp
-inline android::base::Result<void> SetUpApexTestEnvironment() {
- using android::base::ErrnoError;
-
- // 1. Switch to new mount namespace.
- if (unshare(CLONE_NEWNS) != 0) {
- return ErrnoError() << "Failed to unshare";
- }
-
- // 2. Make everything private, so that changes don't propagate.
- if (mount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr) == -1) {
- return ErrnoError() << "Failed to mount / as private";
- }
-
- // 3. Unmount all apexes. This needs to happen in two phases:
- // Note: unlike regular unmount flow in apexd, we don't destroy dm and loop
- // devices, since that would've propagated outside of the test environment.
- std::vector<std::string> apex_mounts = GetApexMounts();
-
- // 3a. First unmount all bind mounds (without @version_code).
- for (const auto& mount : apex_mounts) {
- if (mount.find('@') == std::string::npos) {
- if (umount2(mount.c_str(), 0) != 0) {
- return ErrnoError() << "Failed to unmount " << mount;
- }
- }
- }
-
- // 3.b Now unmount versioned mounts.
- for (const auto& mount : apex_mounts) {
- if (mount.find('@') != std::string::npos) {
- if (umount2(mount.c_str(), 0) != 0) {
- return ErrnoError() << "Failed to unmount " << mount;
- }
- }
- }
-
- static constexpr const char* kApexMountForTest = "/mnt/scratch/apex";
-
- // Clean up in case previous test left directory behind.
- if (access(kApexMountForTest, F_OK) == 0) {
- if (umount2(kApexMountForTest, MNT_FORCE | UMOUNT_NOFOLLOW) != 0) {
- PLOG(WARNING) << "Failed to unmount " << kApexMountForTest;
- }
- if (rmdir(kApexMountForTest) != 0) {
- return ErrnoError() << "Failed to rmdir " << kApexMountForTest;
- }
- }
-
- // 4. Create an empty tmpfs that will substitute /apex in tests.
- if (mkdir(kApexMountForTest, 0755) != 0) {
- return ErrnoError() << "Failed to mkdir " << kApexMountForTest;
- }
-
- if (mount("tmpfs", kApexMountForTest, "tmpfs", 0, nullptr) == -1) {
- return ErrnoError() << "Failed to mount " << kApexMountForTest;
- }
-
- // 5. Overlay it over /apex via bind mount.
- if (mount(kApexMountForTest, "/apex", nullptr, MS_BIND, nullptr) == -1) {
- return ErrnoError() << "Failed to bind mount " << kApexMountForTest
- << " over /apex";
- }
-
- // Just in case, run restorecon -R on /apex.
- if (selinux_android_restorecon("/apex", SELINUX_ANDROID_RESTORECON_RECURSE) <
- 0) {
- return android::base::ErrnoError() << "Failed to restorecon /apex";
- }
-
- return {};
-}
-
-} // namespace apex
-} // namespace android
-
-namespace com {
-namespace android {
-namespace apex {
-
-namespace testing {
-MATCHER_P(ApexInfoXmlEq, other, "") {
- using ::testing::AllOf;
- using ::testing::Eq;
- using ::testing::ExplainMatchResult;
- using ::testing::Field;
- using ::testing::Property;
-
- return ExplainMatchResult(
- AllOf(
- Property("moduleName", &ApexInfo::getModuleName,
- Eq(other.getModuleName())),
- Property("modulePath", &ApexInfo::getModulePath,
- Eq(other.getModulePath())),
- Property("preinstalledModulePath",
- &ApexInfo::getPreinstalledModulePath,
- Eq(other.getPreinstalledModulePath())),
- Property("versionCode", &ApexInfo::getVersionCode,
- Eq(other.getVersionCode())),
- Property("isFactory", &ApexInfo::getIsFactory,
- Eq(other.getIsFactory())),
- Property("isActive", &ApexInfo::getIsActive, Eq(other.getIsActive())),
- Property("lastUpdateMillis", &ApexInfo::getLastUpdateMillis,
- Eq(other.getLastUpdateMillis()))),
- arg, result_listener);
-}
-
-} // namespace testing
-
-// Must be in com::android::apex namespace for gtest to pick it up.
-inline void PrintTo(const ApexInfo& apex, std::ostream* os) {
- *os << "apex_info: {\n";
- *os << " moduleName : " << apex.getModuleName() << "\n";
- *os << " modulePath : " << apex.getModulePath() << "\n";
- *os << " preinstalledModulePath : " << apex.getPreinstalledModulePath()
- << "\n";
- *os << " versionCode : " << apex.getVersionCode() << "\n";
- *os << " isFactory : " << apex.getIsFactory() << "\n";
- *os << " isActive : " << apex.getIsActive() << "\n";
- *os << "}";
-}
-
} // namespace apex
} // namespace android
-} // namespace com
diff --git a/apexd/apexd_testdata/Android.bp b/apexd/apexd_testdata/Android.bp
index 0e7039a0..1f74a532 100644
--- a/apexd/apexd_testdata/Android.bp
+++ b/apexd/apexd_testdata/Android.bp
@@ -15,10 +15,6 @@
// These apex definitions will generate the prebuilt test data. The modules
// are disabled so as not to pollute the build.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
apex_key {
name: "com.android.apex.test_package.key",
public_key: "com.android.apex.test_package.avbpubkey",
@@ -26,13 +22,6 @@ apex_key {
installable: false,
}
-apex_key {
- name: "com.android.apex.compressed.key",
- public_key: "com.android.apex.compressed.avbpubkey",
- private_key: "com.android.apex.compressed.pem",
- installable: false,
-}
-
apex {
name: "apex.apexd_test",
manifest: "manifest.json",
@@ -44,173 +33,13 @@ apex {
}
apex {
- name: "com.android.apex.compressed.v1",
- manifest: "manifest_compressed.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.compressed.key",
- installable: false,
- test_only_force_compression: true,
- updatable: false,
-}
-
-apex {
- name: "com.android.apex.compressed.v1_different_digest",
- manifest: "manifest_compressed.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["hash_of_dev_null"],
- key: "com.android.apex.compressed.key",
- installable: false,
- test_only_force_compression: true,
- updatable: false,
-}
-
-genrule {
- // Generates a compressed apex which doesn't have an original_apex file in it
- name: "gen_capex_without_apex",
- out: ["com.android.apex.compressed.v1_without_apex.capex"],
- srcs: [":com.android.apex.compressed.v1"],
- tools: ["soong_zip"],
- cmd: "unzip -q $(in) -d $(genDir) && rm $(genDir)/original_apex && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) -L 9 " +
- "-o $(genDir)/com.android.apex.compressed.v1_without_apex.capex"
-}
-
-genrule {
- // Generates a compressed apex which has different version of original_apex in it
- name: "gen_capex_with_v2_apex",
- out: ["com.android.apex.compressed.v1_with_v2_apex.capex"],
- srcs: [":com.android.apex.compressed.v2"],
- tools: ["soong_zip", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "$(location conv_apex_manifest) setprop version 1 $(genDir)/apex_manifest.pb && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) -L 9 " +
- "-o $(genDir)/com.android.apex.compressed.v1_with_v2_apex.capex"
-}
-
-genrule {
- // Generates a compressed apex which can be opened but not decompressed
- name: "gen_capex_not_decompressible",
- out: ["com.android.apex.compressed.v1_not_decompressible.capex"],
- srcs: [":com.android.apex.compressed.v1"],
- tools: ["soong_zip", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && echo '' > $(genDir)/original_apex && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) -L 9 " +
- "-o $(genDir)/com.android.apex.compressed.v1_not_decompressible.capex"
-}
-
-genrule {
- // Generates a capex which has same module name as com.android.apex.compressed, but
- // is contains a different public key.
- 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"],
- 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) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/com.android.apex.compressed_different_key.apex && " +
- "$(location apex_compression_tool) compress " +
- "--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"
-}
-
-genrule {
- // Generates a capex which has a different public key than original_apex
- name: "gen_key_mismatch_with_original_capex",
- out: ["com.android.apex.compressed_key_mismatch_with_original.capex"],
- srcs: [":com.android.apex.compressed.v1"],
- tools: ["soong_zip"],
- cmd: "unzip -q $(in) -d $(genDir) && " + // unzip input
- "echo 'different-key' >> $(genDir)/apex_pubkey && " + // modify the public key
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) -L 9 " +// repack the compressed APEX
- "-o $(genDir)/com.android.apex.compressed_key_mismatch_with_original.capex",
-}
-
-genrule {
- // Generates an apex which has a different manifest outside the filesystem
- // image.
- name: "gen_manifest_mismatch_compressed_apex_v2",
- out: ["com.android.apex.compressed.v2_manifest_mismatch.apex"],
- srcs: [":com.android.apex.compressed.v2_original"],
- tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
- cmd: "unzip -q $(in) -d $(genDir) && " +
- "$(location conv_apex_manifest) setprop version 137 $(genDir)/apex_manifest.pb && " +
- "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
- "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
- "-o $(genDir)/unaligned.apex && " +
- "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
- "$(genDir)/com.android.apex.compressed.v2_manifest_mismatch.apex"
-}
-
-apex {
- name: "com.android.apex.compressed.v1_original",
- manifest: "manifest_compressed.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.compressed.key",
- installable: false,
- compressible: false,
- updatable: false,
-}
-
-apex {
- name: "com.android.apex.compressed.v1_different_digest_original",
- manifest: "manifest_compressed.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["hash_of_dev_null"],
- key: "com.android.apex.compressed.key",
- installable: false,
- compressible: false,
- updatable: false,
-}
-
-apex {
- name: "com.android.apex.compressed.v2",
- manifest: "manifest_compressed_v2.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.compressed.key",
- installable: false,
- test_only_force_compression: true,
- updatable: false,
-}
-
-apex {
- name: "com.android.apex.compressed.v2_original",
- manifest: "manifest_compressed_v2.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.compressed.key",
- installable: false,
- compressible: false,
- updatable: false,
-}
-
-apex {
- name: "apex.apexd_test_f2fs",
- 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: "f2fs",
-}
-
-apex {
name: "apex.apexd_test_no_hashtree",
manifest: "manifest.json",
file_contexts: ":apex.test-file_contexts",
prebuilts: ["sample_prebuilt_file"],
key: "com.android.apex.test_package.key",
installable: false,
- generate_hashtree: false,
- updatable: false,
+ test_only_no_hashtree: true,
}
// This APEX has same name and version as apex.apexd_test_no_hashtree, but has
@@ -226,8 +55,7 @@ apex {
],
key: "com.android.apex.test_package.key",
installable: false,
- generate_hashtree: false,
- updatable: false,
+ test_only_no_hashtree: true,
}
apex {
@@ -237,7 +65,6 @@ apex {
prebuilts: ["sample_prebuilt_file"],
key: "com.android.apex.test_package.key",
installable: false,
- updatable: false,
}
apex {
@@ -265,7 +92,6 @@ apex {
prebuilts: ["sample_prebuilt_file"],
key: "com.android.apex.test_package.key",
installable: false,
- updatable: false,
}
apex_key {
@@ -283,7 +109,6 @@ apex {
key: "com.android.apex.test_package.preinstall.key",
binaries: ["apex_test_preInstallHook"],
installable: false,
- updatable: false,
}
apex_key {
@@ -301,7 +126,6 @@ apex {
key: "com.android.apex.test_package.postinstall.key",
binaries: ["apex_test_postInstallHook"],
installable: false,
- updatable: false,
}
apex_key {
@@ -319,7 +143,6 @@ apex {
key: "com.android.apex.test_package.prepostinstall.fail.key",
binaries: ["apex_test_prePostInstallHookFail"],
installable: false,
- updatable: false,
}
apex_key {
@@ -336,18 +159,6 @@ apex {
prebuilts: ["sample_prebuilt_file"],
key: "com.android.apex.test_package.no_inst_key.key",
installable: false,
- updatable: false,
-}
-
-apex {
- name: "apex.apexd_test_f2fs_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: "f2fs",
- updatable: false,
}
apex_key {
@@ -364,7 +175,6 @@ apex {
prebuilts: ["sample_prebuilt_file"],
key: "com.android.apex.test_package_2.key",
installable: false,
- updatable: false,
}
sh_binary {
@@ -389,7 +199,6 @@ apex {
prebuilts: ["sample_prebuilt_file"],
key: "com.android.apex.test_package.key",
installable: false,
- updatable: false,
}
prebuilt_etc {
@@ -403,156 +212,3 @@ prebuilt_apex {
filename: "corrupted_b146895998.apex",
installable: false,
}
-
-// APEX for banned name test cannot be generated at build time.
-// This file can be generated manually by creating new apex target
-// with manifest name 'sharedlibs', and modify aapt2 to skip validating
-// package name from aapt::util::IsAndroidPackageName().
-prebuilt_apex {
- name: "apex.banned_name",
- src: "sharedlibs.apex",
- filename: "sharedlibs.apex",
- installable: false,
-}
-
-// A compressed apex that also provides shared libs.
-// Should be declined by ApexFile::Open.
-apex {
- name: "com.android.apex.compressed_sharedlibs",
- manifest: "manifest_compressed_sharedlibs.json",
- file_contexts: ":apex.test-file_contexts",
- prebuilts: ["sample_prebuilt_file"],
- key: "com.android.apex.compressed.key",
- installable: false,
- test_only_force_compression: true,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_v1",
- manifest: "manifest_rebootless.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
- // TODO(ioffe): we should have a separate field to hashtree presence.
- min_sdk_version: "29", // test requires hashtree to be present.
-}
-
-apex {
- name: "test.rebootless_apex_v2",
- manifest: "manifest_rebootless_v2.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
- // TODO(ioffe): we should have a separate field to hashtree presence.
- min_sdk_version: "29", // test requires hashtree to be present.
-}
-
-apex {
- name: "test.rebootless_apex_v2_no_hashtree",
- manifest: "manifest_rebootless_v2.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
- generate_hashtree: false,
-}
-
-apex {
- name: "test.rebootless_apex_provides_sharedlibs",
- manifest: "manifest_rebootless_provides_sharedlibs.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_provides_native_libs",
- manifest: "manifest_rebootless_provides_native_libs.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_requires_shared_apex_libs",
- manifest: "manifest_rebootless_requires_shared_apex_libs.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_jni_libs",
- manifest: "manifest_rebootless_jni_libs.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_add_native_lib",
- manifest: "manifest_rebootless_add_native_lib.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_remove_native_lib",
- manifest: "manifest_rebootless_remove_native_lib.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "test.rebootless_apex_app_in_apex",
- manifest: "manifest_rebootless_v2.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
- apps: ["AppInRebootlessApex"],
- // TODO(ioffe): we should have a separate field to hashtree presence.
- min_sdk_version: "29", // test requires hashtree to be present.
-}
-
-apex {
- name: "test.rebootless_apex_priv_app_in_apex",
- manifest: "manifest_rebootless_v2.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test_package.key",
- installable: false,
- updatable: false,
- apps: ["PrivAppInRebootlessApex"],
- // TODO(ioffe): we should have a separate field to hashtree presence.
- min_sdk_version: "29", // test requires hashtree to be present.
-}
-
-android_app {
- name: "AppInRebootlessApex",
- sdk_version: "29",
- manifest: "AppInRebootlessApex_AndroidManifest.xml",
- apex_available: [
- "test.rebootless_apex_app_in_apex",
- ],
-}
-
-android_app {
- name: "PrivAppInRebootlessApex",
- sdk_version: "29",
- privileged: true,
- manifest: "AppInRebootlessApex_AndroidManifest.xml",
- apex_available: [
- "test.rebootless_apex_priv_app_in_apex",
- ],
-}
diff --git a/apexd/apexd_testdata/AppInRebootlessApex_AndroidManifest.xml b/apexd/apexd_testdata/AppInRebootlessApex_AndroidManifest.xml
deleted file mode 100644
index 242d1be4..00000000
--- a/apexd/apexd_testdata/AppInRebootlessApex_AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2017 Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.rebootless_tests.app">
-</manifest>
diff --git a/apexd/apexd_testdata/com.android.apex.compressed.avbpubkey b/apexd/apexd_testdata/com.android.apex.compressed.avbpubkey
deleted file mode 100644
index 92767eac..00000000
--- a/apexd/apexd_testdata/com.android.apex.compressed.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/apexd/apexd_testdata/com.android.apex.compressed.pem b/apexd/apexd_testdata/com.android.apex.compressed.pem
deleted file mode 100644
index bc2c0a72..00000000
--- a/apexd/apexd_testdata/com.android.apex.compressed.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAqvAUWzu1+JmgUDTMx22v3Wcdv05CwE3y7roVbIhIFtfQjvjY
-NNStwnl5r+2er0BmlNDWAPC20x46uF2kfSecIjoWMOAjMtkgWHYX6nZqE2BXo6Mj
-KnxC+D+zdj6FO+QCbAZ1JKlfy/zGyq37VTIQu1OF9a3FyusOP2qapWr4jYiZ2WLr
-gHhk/qvurN2GhpeTX7TMSEOVfg2Q7kKTxxXE5blw5lRaF9FzX4FMfU296qyXJ1qE
-8pLjcVwVjTjrAO69AQ3S+lZZXA5WJwbHqU5WaRL5k+XjXASyoxTRvOHOsQ3mxQ+B
-Ad227pk/x5lZLnnuc7d3Qe5cB2yJNDaENEptCA5VKaBG1QbRBL8ykD45w2OwIP7p
-2H58b/2tEgtjA4bpWEFqwVa8LXMBg2x56Sbo8YWmQL4FE14XAYyI3eAs171JZV6e
-nf9/ll+45oIXI2wY0jttfnYyGErLlbCIWYYByAnV5mwZ9eBrXl/xu65+MUKVnZOA
-2y1KJch1eXUjLqMRAW6DBwOmAjsJhuiF8u2gZlF/zgnzPzWbbvfMWi/aztdCV2Yb
-rRhKZT6i2A0a9o3lghwGpHJjXwJ23ELWmfWI6mxGGJyhrVRLvUlRp2a8QRmw6mcc
-sWVWdichcjvx20fIPHanzC/TtgKe/smQjZ1GQClPbqRvbhoxleklLDk+NWkCAwEA
-AQKCAgAJLwbY8/dN2OsdBAkwebsmGQEnIwxBCq8Pll3KS/QbjhK9a68p/3cqaJ5a
-DlklLz+TpTiqKkSYSRp8h0NsGfGwgRBqJdCeTb4IIqgcR6phSh7LQtuDz9NFRR7e
-LnO4CQL8TMiEZLkp23XOs9Q5+oudlNowndpvkXtdetu+IWYjLICfhkoCx/UdHZ2g
-GfK9Tm1zieIjy8W/VPlBY8BOxOOkN/dR2JxShUU+j1LNtJyMfCNO0PUtlyizEXBy
-+ujdTvZGlTiNjJAWewqz5BBcD0JjOMrB4Gr7qaDzVA4EqNkS+B063x9eO0w1u3QK
-xDlfXtupyeSVXToCiBlC/d7SdGExJBqpebCKWLvdIXxDbgU5tNeKXcbHNp9zOduV
-RTulPxseqKgvO/wDc27F1AChG68GYyWcEm7kWQd6BVmOOwxRurssrTgchFk/HrY+
-Vzlbqs+CTyrYoyZuMF8W7E0U7pQtLx4VMv1AEfHyzLmbPgsdwmlPZ4On+yks4rGt
-jHGtUergxsAiiYBHZqXbmuK7UTg1wi5u8p4QgTUxC5jkKMetkgqGajWf5BDpf02E
-+0P+58VGHkd3ACPFG4PcS8gnmjpx/EXicWq855w+nshr8Ff4Gs9LbUv0pg8s9mZA
-2JGfGyjxp8h9/06OrKq5pM5HVuOCZ0AgEHEf++AeBSq24mrgkQKCAQEA28JaiH83
-7NCiK8XJebgPgVGl/wwugsA+Ea3Kv/prQGmFW/IVJNAbMAREkzDi4IaVGySPHDpo
-OaDFFPOiC9zyveK8LdJyqaInEdN6nerGuM4ubA27DKP52MHfMBr6FDYgru5hcskw
-4gHGZAWhD242rzhFGgfTTDbRXRhqn93f/6+yHbjyjybs5vPM2gU/qPlwdjUPxXFo
-g3Nrx3TyrMtfUL/dhHniF+SiiVfu8hNqi4EuQ295jGtwMZl8U0/UVuQ6UQUMe6cT
-VfKuunxyCq2AOvd4XLODZ9BcZDtTDLIsXaPyVzJUPGxugqlid/i7SuV+c3unT0dD
-Ma2+7n6gdStuPQKCAQEAxyCeECT3Yhx1rB3SvloGVCMQY3ajs4/a3qIPLa18X8ZL
-K1qUevlq7mpJVbnI0KmbuyNzPyGkPbQtuGU0g8kvchD7nH3Pi9SabB2ereIi9YO0
-s5a+ZVVPdtD69oCfhhKh9BPrjsSDnci2ZjCYkxzKHVtSvlJQmWAaxcUCwUKPvXen
-LBQ4QNC9bnVj6v9XJwWy3YgrwpRetdBPU/jnSAjLOpjWKlXz4pokHpIR1kAsRY9O
-In2gkP27PwSBMEZ4qxKa0uujQ5L4odqtDm4O15fF1IQ0/y+sNTrZArg54X3MYG6J
-UyR9ReKXUL5nWYYSEsVJ6D9J8fiow21hiYnSt82inQKCAQEAlrW+QtgEcYtPfHeD
-Sc96CrUFA1nGV/MhXhxy7J//h8gWJk1qRLnXu2Fh6hPftB14CopS/wfrTII+RrUj
-D8GyU5k4drBZ5I4I/0eqUrydFkaIPaBZBD08bnPe7W3CzbOlTHK9L+xcctLGzPez
-UhLCu/36HfT56s25XYAON58BLKfAnnOlHZmTZHwUo/xvgSG4B8kyDLVO+L9iTgKd
-HvXGY2mBsIWqEbrB4TEF9MxuCEhKgwLjN/LCmbFqOvSHaiPQ/plYy0B0mT/6pngL
-+ditFUN8Lw8JclvJ0Q+CUDWtCXcTDsu8S0gNrdweZKqXP7ENvIMz5cG4ikxeoc8D
-mfdz/QKCAQBZkzGnX4mtJ9JDV7Maj9Ky/Ib9xzvCpZ62cb5UNOtzBfeAjCGo5BQX
-JdbRal6Mhw+X8k2Ag7inTSsX/ObPtavTKxKUhf/cDgpdQkHERKqnONULyG7jlKnH
-cCDEzH12SWFzM5bORVZTnxt2ArxPyS6eYBtrpAm/xPymJIaluzR/7ZhU+s+HUJ82
-VjZZWv2wfx7ECuJsiGPGc+uLgbdArzwEowYMS1gHgoFnAxxk/b8sl1d1qn+VWZ5m
-rbcTqU/U3Oyqnvd1iWKxJHaevCGPGCYVAFf6x043L765O3hGGFncszyxGwQDcPfS
-iaRiIC53JSqm//lakRoRt12eClKw/h79AoIBAQC0uu/kwB//HdQbzJkejoBZDWpu
-2eTZKnLs/5hsU/CPfJnL2cJfStJIFh6WgutNoW++Xi79OfagEQx6hAyfl5HexV8V
-2PNDMgcgxauAObhkZtg8x5ZDAyrOiXVHR+T3cm8qQbVtrHdiX97hrg9tTj923baK
-TpI9qQw+2Jg627BR2t/rYIrZwdL2oqbznihIIPg6FkCT/53AfX8W1U9GWPnUyIkn
-KvRdtY6osOS/C/Dju/Eg6710umACRPLa5928A5q+1jY6TntRIG8Q/agL4IXjR/0E
-O0OkoRArOFt2NGN88Vqy7ses0VfP2UIpjjRP3/8xwUFmUo8vdoR5oy4kC/Sz
------END RSA PRIVATE KEY-----
diff --git a/apexd/apexd_testdata/manifest_compressed.json b/apexd/apexd_testdata/manifest_compressed.json
deleted file mode 100644
index 8c07cc82..00000000
--- a/apexd/apexd_testdata/manifest_compressed.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.compressed",
- "version": 1
-}
diff --git a/apexd/apexd_testdata/manifest_compressed_sharedlibs.json b/apexd/apexd_testdata/manifest_compressed_sharedlibs.json
deleted file mode 100644
index 30d2835f..00000000
--- a/apexd/apexd_testdata/manifest_compressed_sharedlibs.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "com.android.apex.compressed",
- "version": 1,
- "provideSharedApexLibs": true
-}
diff --git a/apexd/apexd_testdata/manifest_compressed_v2.json b/apexd/apexd_testdata/manifest_compressed_v2.json
deleted file mode 100644
index c5adb514..00000000
--- a/apexd/apexd_testdata/manifest_compressed_v2.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.compressed",
- "version": 2
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless.json b/apexd/apexd_testdata/manifest_rebootless.json
deleted file mode 100644
index a37fa005..00000000
--- a/apexd/apexd_testdata/manifest_rebootless.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar"
- ]
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_add_native_lib.json b/apexd/apexd_testdata/manifest_rebootless_add_native_lib.json
deleted file mode 100644
index eab172c9..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_add_native_lib.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar",
- "libnew"
- ]
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_jni_libs.json b/apexd/apexd_testdata/manifest_rebootless_jni_libs.json
deleted file mode 100644
index bf88d2eb..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_jni_libs.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar"
- ],
- "jniLibs": [
- "libjniwow"
- ]
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_provides_native_libs.json b/apexd/apexd_testdata/manifest_rebootless_provides_native_libs.json
deleted file mode 100644
index ef829b07..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_provides_native_libs.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar"
- ],
- "provideNativeLibs": [
- "libbaz"
- ]
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_provides_sharedlibs.json b/apexd/apexd_testdata/manifest_rebootless_provides_sharedlibs.json
deleted file mode 100644
index d91c21e4..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_provides_sharedlibs.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar"
- ],
- "provideSharedApexLibs": true
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_remove_native_lib.json b/apexd/apexd_testdata/manifest_rebootless_remove_native_lib.json
deleted file mode 100644
index 0926e70f..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_remove_native_lib.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libbar"
- ]
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_requires_shared_apex_libs.json b/apexd/apexd_testdata/manifest_rebootless_requires_shared_apex_libs.json
deleted file mode 100644
index faaadfda..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_requires_shared_apex_libs.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 1,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar"
- ],
- "requireSharedApexLibs": [
- "libabc"
- ]
-}
diff --git a/apexd/apexd_testdata/manifest_rebootless_v2.json b/apexd/apexd_testdata/manifest_rebootless_v2.json
deleted file mode 100644
index dfcb21fe..00000000
--- a/apexd/apexd_testdata/manifest_rebootless_v2.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "test.apex.rebootless",
- "version": 2,
- "supportsRebootlessUpdate": true,
- "requireNativeLibs": [
- "libfoo",
- "libbar"
- ]
-}
diff --git a/apexd/apexd_testdata/sharedlibs.apex b/apexd/apexd_testdata/sharedlibs.apex
deleted file mode 100644
index cde11d51..00000000
--- a/apexd/apexd_testdata/sharedlibs.apex
+++ /dev/null
Binary files differ
diff --git a/apexd/apexd_utils.h b/apexd/apexd_utils.h
index 23194ebf..2759f9aa 100644
--- a/apexd/apexd_utils.h
+++ b/apexd/apexd_utils.h
@@ -18,11 +18,9 @@
#define ANDROID_APEXD_APEXD_UTILS_H_
#include <chrono>
-#include <cstdint>
#include <filesystem>
#include <string>
#include <thread>
-#include <type_traits>
#include <vector>
#include <dirent.h>
@@ -32,14 +30,17 @@
#include <android-base/chrono_utils.h>
#include <android-base/logging.h>
-#include <android-base/properties.h>
#include <android-base/result.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <cutils/android_reboot.h>
-#include <selinux/android.h>
#include "apex_constants.h"
+#include "string_log.h"
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
namespace android {
namespace apex {
@@ -60,18 +61,21 @@ inline int WaitChild(pid_t pid) {
}
}
-inline android::base::Result<void> ForkAndRun(
- const std::vector<std::string>& args) {
+// TODO(ioffe): change to Result<void>?
+inline int ForkAndRun(const std::vector<std::string>& args,
+ std::string* error_msg) {
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(); });
+ // 3) Fork.
pid_t pid = fork();
if (pid == -1) {
// Fork failed.
- return android::base::ErrnoError() << "Unable to fork";
+ *error_msg = PStringLog() << "Unable to fork";
+ return -1;
}
if (pid == 0) {
@@ -82,13 +86,13 @@ inline android::base::Result<void> ForkAndRun(
int rc = WaitChild(pid);
if (rc != 0) {
- return android::base::Error() << "Failed run: status=" << rc;
+ *error_msg = StringLog() << "Failed run: status=" << rc;
}
- return {};
+ return rc;
}
template <typename Fn>
-android::base::Result<void> WalkDir(const std::string& path, Fn fn) {
+Result<void> WalkDir(const std::string& path, Fn fn) {
namespace fs = std::filesystem;
std::error_code ec;
auto it = fs::directory_iterator(path, ec);
@@ -98,15 +102,14 @@ android::base::Result<void> WalkDir(const std::string& path, Fn fn) {
it.increment(ec);
}
if (ec) {
- return android::base::Error()
- << "Can't open " << path << " for reading : " << ec.message();
+ return Error() << "Can't open " << path
+ << " for reading : " << ec.message();
}
return {};
}
template <typename FilterFn>
-android::base::Result<std::vector<std::string>> ReadDir(const std::string& path,
- FilterFn fn) {
+Result<std::vector<std::string>> ReadDir(const std::string& path, FilterFn fn) {
namespace fs = std::filesystem;
std::vector<std::string> ret;
@@ -126,70 +129,72 @@ inline bool IsEmptyDirectory(const std::string& path) {
return res.ok() && res->empty();
}
-inline android::base::Result<void> CreateDirIfNeeded(const std::string& path,
- mode_t mode) {
+inline Result<void> createDirIfNeeded(const std::string& path, mode_t mode) {
struct stat stat_data;
if (stat(path.c_str(), &stat_data) != 0) {
if (errno == ENOENT) {
if (mkdir(path.c_str(), mode) != 0) {
- return android::base::ErrnoError() << "Could not mkdir " << path;
+ return ErrnoError() << "Could not mkdir " << path;
}
} else {
- return android::base::ErrnoError() << "Could not stat " << path;
+ return ErrnoError() << "Could not stat " << path;
}
} else {
if (!S_ISDIR(stat_data.st_mode)) {
- return android::base::Error()
- << path << " exists and is not a directory.";
+ return Error() << path << " exists and is not a directory.";
}
}
// Need to manually call chmod because mkdir will create a folder with
// permissions mode & ~umask.
if (chmod(path.c_str(), mode) != 0) {
- return android::base::ErrnoError() << "Could not chmod " << path;
+ return ErrnoError() << "Could not chmod " << path;
}
return {};
}
-inline android::base::Result<void> DeleteDirContent(const std::string& path) {
+inline Result<void> DeleteDirContent(const std::string& path) {
auto files = ReadDir(path, [](auto _) { return true; });
if (!files.ok()) {
- return android::base::Error()
- << "Failed to delete " << path << " : " << files.error();
+ return Error() << "Failed to delete " << path << " : " << files.error();
}
for (const std::string& file : *files) {
- std::error_code ec;
- std::filesystem::remove_all(file, ec);
- if (ec) {
- return android::base::Error()
- << "Failed to delete path " << file << " : " << ec.message();
+ if (unlink(file.c_str()) != 0) {
+ return ErrnoError() << "Failed to delete " << file;
}
}
return {};
}
-inline android::base::Result<void> DeleteDir(const std::string& path) {
+inline Result<void> DeleteDir(const std::string& path) {
namespace fs = std::filesystem;
std::error_code ec;
fs::remove_all(path, ec);
if (ec) {
- return android::base::Error()
- << "Failed to delete path " << path << " : " << ec.message();
+ return Error() << "Failed to delete path " << path << " : " << ec.message();
}
return {};
}
-inline android::base::Result<bool> PathExists(const std::string& path) {
+inline Result<ino_t> get_path_inode(const std::string& path) {
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ if (stat(path.c_str(), &buf) != 0) {
+ return ErrnoError() << "Failed to stat " << path;
+ } else {
+ return buf.st_ino;
+ }
+}
+
+inline Result<bool> PathExists(const std::string& path) {
namespace fs = std::filesystem;
std::error_code ec;
if (!fs::exists(fs::path(path), ec)) {
if (ec) {
- return android::base::Error()
- << "Failed to access " << path << " : " << ec.message();
+ return Error() << "Failed to access " << path << " : " << ec.message();
} else {
return false;
}
@@ -204,8 +209,8 @@ inline void Reboot() {
}
}
-inline android::base::Result<void> WaitForFile(
- const std::string& path, std::chrono::nanoseconds timeout) {
+inline Result<void> WaitForFile(const std::string& path,
+ std::chrono::nanoseconds timeout) {
android::base::Timer t;
bool has_slept = false;
while (t.duration() < timeout) {
@@ -219,12 +224,10 @@ inline android::base::Result<void> WaitForFile(
std::this_thread::sleep_for(5ms);
has_slept = true;
}
- return android::base::ErrnoError()
- << "wait for '" << path << "' timed out and took " << t;
+ return ErrnoError() << "wait for '" << path << "' timed out and took " << t;
}
-inline android::base::Result<std::vector<std::string>> GetSubdirs(
- const std::string& path) {
+inline Result<std::vector<std::string>> GetSubdirs(const std::string& path) {
namespace fs = std::filesystem;
auto filter_fn = [](const std::filesystem::directory_entry& entry) {
std::error_code ec;
@@ -238,140 +241,10 @@ inline android::base::Result<std::vector<std::string>> GetSubdirs(
return ReadDir(path, filter_fn);
}
-inline android::base::Result<std::vector<std::string>> GetDeUserDirs() {
+inline Result<std::vector<std::string>> GetDeUserDirs() {
return GetSubdirs(kDeNDataDir);
}
-inline android::base::Result<std::vector<std::string>> FindFilesBySuffix(
- const std::string& path, const std::vector<std::string>& suffix_list) {
- auto filter_fn =
- [&suffix_list](const std::filesystem::directory_entry& entry) {
- for (const std::string& suffix : suffix_list) {
- std::error_code ec;
- auto name = entry.path().filename().string();
- if (entry.is_regular_file(ec) &&
- android::base::EndsWith(name, suffix)) {
- return true; // suffix matches, take.
- }
- }
- return false;
- };
- return ReadDir(path, filter_fn);
-}
-
-inline android::base::Result<std::vector<std::string>> FindApexes(
- const std::vector<std::string>& paths) {
- std::vector<std::string> result;
- for (const auto& path : paths) {
- auto exist = PathExists(path);
- if (!exist.ok()) {
- return exist.error();
- }
- if (!*exist) continue;
-
- const auto& apexes = FindFilesBySuffix(path, {kApexPackageSuffix});
- if (!apexes.ok()) {
- return apexes;
- }
-
- result.insert(result.end(), apexes->begin(), apexes->end());
- }
- return result;
-}
-
-// Returns first path between |first_dir| and |second_dir| that correspond to a
-// existing directory. Returns error if neither |first_dir| nor |second_dir|
-// correspond to an existing directory.
-inline android::base::Result<std::string> FindFirstExistingDirectory(
- const std::string& first_dir, const std::string& second_dir) {
- struct stat stat_buf;
- if (stat(first_dir.c_str(), &stat_buf) != 0) {
- PLOG(WARNING) << "Failed to stat " << first_dir;
- if (stat(second_dir.c_str(), &stat_buf) != 0) {
- return android::base::ErrnoError() << "Failed to stat " << second_dir;
- }
- if (!S_ISDIR(stat_buf.st_mode)) {
- return android::base::Error() << second_dir << " is not a directory";
- }
- return second_dir;
- }
-
- if (S_ISDIR(stat_buf.st_mode)) {
- return first_dir;
- }
- LOG(WARNING) << first_dir << " is not a directory";
-
- if (stat(second_dir.c_str(), &stat_buf) != 0) {
- return android::base::ErrnoError() << "Failed to stat " << second_dir;
- }
- if (!S_ISDIR(stat_buf.st_mode)) {
- return android::base::Error() << second_dir << " is not a directory";
- }
- return second_dir;
-}
-
-// Copies all entries under |from| directory to |to| directory, and then them.
-// Leaving |from| empty.
-inline android::base::Result<void> MoveDir(const std::string& from,
- const std::string& to) {
- struct stat stat_buf;
- if (stat(to.c_str(), &stat_buf) != 0) {
- return android::base::ErrnoError() << "Failed to stat " << to;
- }
- if (!S_ISDIR(stat_buf.st_mode)) {
- return android::base::Error() << to << " is not a directory";
- }
-
- namespace fs = std::filesystem;
- std::error_code ec;
- auto it = fs::directory_iterator(from, ec);
- if (ec) {
- return android::base::Error()
- << "Can't read " << from << " : " << ec.message();
- }
-
- for (const auto& end = fs::directory_iterator(); it != end;) {
- auto from_path = it->path();
- it.increment(ec);
- if (ec) {
- return android::base::Error()
- << "Can't read " << from << " : " << ec.message();
- }
- auto to_path = to / from_path.filename();
- fs::copy(from_path, to_path, fs::copy_options::recursive, ec);
- if (ec) {
- return android::base::Error() << "Failed to copy " << from_path << " to "
- << to_path << " : " << ec.message();
- }
- fs::remove_all(from_path, ec);
- if (ec) {
- return android::base::Error()
- << "Failed to delete " << from_path << " : " << ec.message();
- }
- }
- return {};
-}
-
-inline android::base::Result<uintmax_t> GetFileSize(
- const std::string& file_path) {
- std::error_code ec;
- auto value = std::filesystem::file_size(file_path, ec);
- if (ec) {
- return android::base::Error() << "Failed to get file size of " << file_path
- << " : " << ec.message();
- }
-
- return value;
-}
-
-inline android::base::Result<void> RestoreconPath(const std::string& path) {
- unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
- if (selinux_android_restorecon(path.c_str(), seflags) < 0) {
- return android::base::ErrnoError() << "Failed to restorecon " << path;
- }
- return {};
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexd_utils_test.cpp b/apexd/apexd_utils_test.cpp
deleted file mode 100644
index cbbc45e1..00000000
--- a/apexd/apexd_utils_test.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <filesystem>
-#include <fstream>
-#include <new>
-#include <string>
-
-#include <errno.h>
-
-#include <android-base/file.h>
-#include <android-base/result.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <gtest/gtest.h>
-
-#include "apexd.h"
-#include "apexd_test_utils.h"
-#include "apexd_utils.h"
-
-namespace android {
-namespace apex {
-namespace {
-
-namespace fs = std::filesystem;
-
-using android::apex::testing::IsOk;
-using android::base::Basename;
-using android::base::Join;
-using android::base::StringPrintf;
-using ::testing::UnorderedElementsAre;
-using ::testing::UnorderedElementsAreArray;
-
-// TODO(b/170327382): add unit tests for apexd_utils.h
-
-TEST(ApexdUtilTest, DeleteDirContent) {
- TemporaryDir root_dir;
- TemporaryFile child_file_1(root_dir.path);
- TemporaryFile child_file_2(root_dir.path);
- std::string child_dir = StringPrintf("%s/child-dir", root_dir.path);
- CreateDirIfNeeded(child_dir, 0755);
- TemporaryFile nested_file(child_dir);
-
- auto content = ReadDir(root_dir.path, [](auto _) { return true; });
- IsOk(content);
- ASSERT_EQ(content->size(), 3u);
-
- auto del_result = DeleteDirContent(root_dir.path);
- IsOk(del_result);
- content = ReadDir(root_dir.path, [](auto _) { return true; });
- IsOk(content);
- ASSERT_EQ(content->size(), 0u);
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryBothExist) {
- TemporaryDir first_dir;
- TemporaryDir second_dir;
- auto result = FindFirstExistingDirectory(first_dir.path, second_dir.path);
- ASSERT_TRUE(IsOk(result));
- ASSERT_EQ(*result, first_dir.path);
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryOnlyFirstExist) {
- TemporaryDir first_dir;
- auto second_dir = "/data/local/tmp/does/not/exist";
- auto result = FindFirstExistingDirectory(first_dir.path, second_dir);
- ASSERT_TRUE(IsOk(result));
- ASSERT_EQ(*result, first_dir.path);
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryOnlySecondExist) {
- auto first_dir = "/data/local/tmp/does/not/exist";
- TemporaryDir second_dir;
- auto result = FindFirstExistingDirectory(first_dir, second_dir.path);
- ASSERT_TRUE(IsOk(result));
- ASSERT_EQ(*result, second_dir.path);
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryNoneExist) {
- auto first_dir = "/data/local/tmp/does/not/exist";
- auto second_dir = "/data/local/tmp/also/does/not/exist";
- auto result = FindFirstExistingDirectory(first_dir, second_dir);
- ASSERT_FALSE(IsOk(result));
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryFirstFileSecondDir) {
- TemporaryFile first_file;
- TemporaryDir second_dir;
- auto result = FindFirstExistingDirectory(first_file.path, second_dir.path);
- ASSERT_TRUE(IsOk(result));
- ASSERT_EQ(*result, second_dir.path);
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryFirstDirSecondFile) {
- TemporaryDir first_dir;
- TemporaryFile second_file;
- auto result = FindFirstExistingDirectory(first_dir.path, second_file.path);
- ASSERT_TRUE(IsOk(result));
- ASSERT_EQ(*result, first_dir.path);
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryBothFiles) {
- TemporaryFile first_file;
- TemporaryFile second_file;
- auto result = FindFirstExistingDirectory(first_file.path, second_file.path);
- ASSERT_FALSE(IsOk(result));
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryFirstFileSecondDoesNotExist) {
- TemporaryFile first_file;
- auto second_dir = "/data/local/tmp/does/not/exist";
- auto result = FindFirstExistingDirectory(first_file.path, second_dir);
- ASSERT_FALSE(IsOk(result));
-}
-
-TEST(ApexdUtilTest, FindFirstExistingDirectoryFirsDoesNotExistSecondFile) {
- auto first_dir = "/data/local/tmp/does/not/exist";
- TemporaryFile second_file;
- auto result = FindFirstExistingDirectory(first_dir, second_file.path);
- ASSERT_FALSE(IsOk(result));
-}
-
-TEST(ApexdUtilTest, MoveDir) {
- TemporaryDir from;
- TemporaryDir to;
-
- TemporaryFile from_1(from.path);
- auto from_subdir = StringPrintf("%s/subdir", from.path);
- if (mkdir(from_subdir.c_str(), 07000) != 0) {
- FAIL() << "Failed to mkdir " << from_subdir << " : " << strerror(errno);
- }
- TemporaryFile from_2(from_subdir);
-
- auto result = MoveDir(from.path, to.path);
- ASSERT_TRUE(IsOk(result));
- ASSERT_TRUE(fs::is_empty(from.path));
-
- std::vector<std::string> content;
- for (const auto& it : fs::recursive_directory_iterator(to.path)) {
- content.push_back(it.path());
- }
-
- static const std::vector<std::string> expected = {
- StringPrintf("%s/%s", to.path, Basename(from_1.path).c_str()),
- StringPrintf("%s/subdir", to.path),
- StringPrintf("%s/subdir/%s", to.path, Basename(from_2.path).c_str()),
- };
- ASSERT_THAT(content, UnorderedElementsAreArray(expected));
-}
-
-TEST(ApexdUtilTest, MoveDirFromIsNotDirectory) {
- TemporaryFile from;
- TemporaryDir to;
- ASSERT_FALSE(IsOk(MoveDir(from.path, to.path)));
-}
-
-TEST(ApexdUtilTest, MoveDirToIsNotDirectory) {
- TemporaryDir from;
- TemporaryFile to;
- TemporaryFile from_1(from.path);
- ASSERT_FALSE(IsOk(MoveDir(from.path, to.path)));
-}
-
-TEST(ApexdUtilTest, MoveDirFromDoesNotExist) {
- TemporaryDir to;
- ASSERT_FALSE(IsOk(MoveDir("/data/local/tmp/does/not/exist", to.path)));
-}
-
-TEST(ApexdUtilTest, MoveDirToDoesNotExist) {
- namespace fs = std::filesystem;
-
- TemporaryDir from;
- TemporaryFile from_1(from.path);
- auto from_subdir = StringPrintf("%s/subdir", from.path);
- if (mkdir(from_subdir.c_str(), 07000) != 0) {
- FAIL() << "Failed to mkdir " << from_subdir << " : " << strerror(errno);
- }
- TemporaryFile from_2(from_subdir);
-
- ASSERT_FALSE(IsOk(MoveDir(from.path, "/data/local/tmp/does/not/exist")));
-
- // Check that |from| directory is not empty.
- std::vector<std::string> content;
- for (const auto& it : fs::recursive_directory_iterator(from.path)) {
- content.push_back(it.path());
- }
-
- ASSERT_THAT(content,
- UnorderedElementsAre(from_1.path, from_subdir, from_2.path));
-}
-
-TEST(ApexdUtilTest, FindFilesBySuffix) {
- TemporaryDir td;
-
- // create files with different suffix
- const std::string first_filename = StringPrintf("%s/first.a", td.path);
- const std::string second_filename = StringPrintf("%s/second.b", td.path);
- const std::string third_filename = StringPrintf("%s/third.c", td.path);
- const std::string fourth_filename = StringPrintf("%s/fourth.c", td.path);
-
- std::ofstream first_file(first_filename);
- std::ofstream second_file(second_filename);
- std::ofstream third_file(third_filename);
- std::ofstream fourth_file(fourth_filename);
-
- auto result = FindFilesBySuffix(td.path, {".b", ".c"});
- ASSERT_TRUE(IsOk(result));
- ASSERT_THAT(*result, UnorderedElementsAre(second_filename, third_filename,
- fourth_filename));
-}
-
-TEST(ApexdTestUtilsTest, MountNamespaceRestorer) {
- auto original_namespace = GetCurrentMountNamespace();
- ASSERT_RESULT_OK(original_namespace);
- {
- MountNamespaceRestorer restorer;
- // Switch to new mount namespace.
- ASSERT_NE(-1, unshare(CLONE_NEWNS));
- auto current_namespace = GetCurrentMountNamespace();
- ASSERT_RESULT_OK(current_namespace);
- ASSERT_NE(original_namespace, current_namespace);
- }
- // Check that we switched back to the original namespace upon exiting the
- // scope.
- auto current_namespace = GetCurrentMountNamespace();
- ASSERT_RESULT_OK(current_namespace);
- ASSERT_EQ(*original_namespace, *current_namespace);
-}
-
-TEST(ApexdTestUtilsTest, SetUpApexTestEnvironment) {
- auto original_apex_mounts = GetApexMounts();
- ASSERT_GT(original_apex_mounts.size(), 0u);
- auto original_dir_content = ReadDir("/apex", [](auto _) { return true; });
- ASSERT_TRUE(IsOk(original_dir_content));
- {
- MountNamespaceRestorer restorer;
- ASSERT_TRUE(IsOk(SetUpApexTestEnvironment()));
- // Check /apex is apex_mnt_dir.
- char* context;
- ASSERT_GT(getfilecon("/apex", &context), 0);
- EXPECT_EQ(std::string(context), "u:object_r:apex_mnt_dir:s0");
- freecon(context);
- // Check no apexes are mounted in our test environment.
- auto new_apex_mounts = GetApexMounts();
- ASSERT_EQ(new_apex_mounts.size(), 0u);
- // Check that /apex is empty.
- auto dir_content = ReadDir("/apex", [](auto _) { return true; });
- ASSERT_TRUE(IsOk(dir_content));
- ASSERT_EQ(dir_content->size(), 0u)
- << "Found following entries: " << Join(*dir_content, ',');
- // Check that we can still access /data.
- std::string test_dir = android::base::GetExecutableDirectory();
- ASSERT_TRUE(android::base::StartsWith(test_dir, "/data"));
- TemporaryFile tf(test_dir);
- // Check that we can write.
- ASSERT_TRUE(android::base::WriteStringToFile("secret", tf.path));
- // And check that we can still read it
- std::string content;
- ASSERT_TRUE(android::base::ReadFileToString(tf.path, &content));
- ASSERT_EQ(content, "secret");
- }
- auto apex_mounts = GetApexMounts();
- ASSERT_THAT(apex_mounts, UnorderedElementsAreArray(original_apex_mounts));
- auto apex_dir_content = ReadDir("/apex", [](auto _) { return true; });
- ASSERT_TRUE(IsOk(apex_dir_content));
- ASSERT_EQ(apex_dir_content->size(), original_dir_content->size());
-}
-
-} // namespace
-} // namespace apex
-} // namespace android
diff --git a/apexd/apexd_verity.cpp b/apexd/apexd_verity.cpp
index 0008f6d2..a4be3363 100644
--- a/apexd/apexd_verity.cpp
+++ b/apexd/apexd_verity.cpp
@@ -29,7 +29,6 @@
#include "apex_file.h"
#include "apexd_utils.h"
-using android::base::Dirname;
using android::base::ErrnoError;
using android::base::Error;
using android::base::ReadFully;
@@ -60,8 +59,7 @@ std::vector<uint8_t> HexToBin(const std::string& hex) {
Result<void> GenerateHashTree(const ApexFile& apex,
const ApexVerityData& verity_data,
const std::string& hashtree_file) {
- unique_fd fd(
- TEMP_FAILURE_RETRY(open(apex.GetPath().c_str(), O_RDONLY | O_CLOEXEC)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(apex.GetPath().c_str(), O_RDONLY)));
if (fd.get() == -1) {
return ErrnoError() << "Failed to open " << apex.GetPath();
}
@@ -80,10 +78,7 @@ Result<void> GenerateHashTree(const ApexFile& apex,
return Error() << "Invalid image size " << image_size;
}
- if (!apex.GetImageOffset()) {
- return Error() << "Cannot generate HashTree without image offset";
- }
- if (lseek(fd, apex.GetImageOffset().value(), SEEK_SET) == -1) {
+ if (lseek(fd, apex.GetImageOffset(), SEEK_SET) == -1) {
return ErrnoError() << "Failed to seek";
}
@@ -110,8 +105,8 @@ Result<void> GenerateHashTree(const ApexFile& apex,
return Error() << "Failed to build hashtree: root digest mismatch";
}
- unique_fd out_fd(TEMP_FAILURE_RETRY(open(
- hashtree_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600)));
+ unique_fd out_fd(TEMP_FAILURE_RETRY(
+ open(hashtree_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0600)));
if (!builder->WriteHashTreeToFd(out_fd, 0)) {
return Error() << "Failed to write hashtree to " << hashtree_file;
}
@@ -120,8 +115,7 @@ Result<void> GenerateHashTree(const ApexFile& apex,
Result<std::string> CalculateRootDigest(const std::string& hashtree_file,
const ApexVerityData& verity_data) {
- unique_fd fd(
- TEMP_FAILURE_RETRY(open(hashtree_file.c_str(), O_RDONLY | O_CLOEXEC)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(hashtree_file.c_str(), O_RDONLY)));
if (fd.get() == -1) {
return ErrnoError() << "Failed to open " << hashtree_file;
}
@@ -155,11 +149,7 @@ Result<std::string> CalculateRootDigest(const std::string& hashtree_file,
Result<PrepareHashTreeResult> PrepareHashTree(
const ApexFile& apex, const ApexVerityData& verity_data,
const std::string& hashtree_file) {
- if (apex.IsCompressed()) {
- return Error() << "Cannot prepare HashTree of compressed APEX";
- }
-
- if (auto st = CreateDirIfNeeded(Dirname(hashtree_file), 0700); !st.ok()) {
+ if (auto st = createDirIfNeeded(kApexHashTreeDir, 0700); !st.ok()) {
return st.error();
}
bool should_regenerate_hashtree = false;
diff --git a/apexd/apexd_verity_test.cpp b/apexd/apexd_verity_test.cpp
index 4e53ccbf..cf2317c8 100644
--- a/apexd/apexd_verity_test.cpp
+++ b/apexd/apexd_verity_test.cpp
@@ -25,6 +25,7 @@
#include <gtest/gtest.h>
#include "apex_file.h"
+#include "apex_preinstalled_data.h"
#include "apexd_test_utils.h"
#include "apexd_verity.h"
@@ -44,11 +45,12 @@ static std::string GetTestFile(const std::string& name) {
}
TEST(ApexdVerityTest, ReusesHashtree) {
+ ASSERT_TRUE(IsOk(collectPreinstalledData({"/system_ext/apex"})));
TemporaryDir td;
auto apex = ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree.apex"));
ASSERT_TRUE(IsOk(apex));
- auto verity_data = apex->VerifyApexVerity(apex->GetBundledPublicKey());
+ auto verity_data = apex->VerifyApexVerity();
ASSERT_TRUE(IsOk(verity_data));
auto hashtree_file = StringPrintf("%s/hashtree", td.path);
@@ -76,11 +78,12 @@ TEST(ApexdVerityTest, ReusesHashtree) {
}
TEST(ApexdVerityTest, RegenerateHashree) {
+ ASSERT_TRUE(IsOk(collectPreinstalledData({"/system_ext/apex"})));
TemporaryDir td;
auto apex = ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree.apex"));
ASSERT_TRUE(IsOk(apex));
- auto verity_data = apex->VerifyApexVerity(apex->GetBundledPublicKey());
+ auto verity_data = apex->VerifyApexVerity();
ASSERT_TRUE(IsOk(verity_data));
auto hashtree_file = StringPrintf("%s/hashtree", td.path);
@@ -95,7 +98,7 @@ TEST(ApexdVerityTest, RegenerateHashree) {
auto apex2 =
ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree_2.apex"));
ASSERT_TRUE(IsOk(apex2));
- auto verity_data2 = apex2->VerifyApexVerity(apex2->GetBundledPublicKey());
+ auto verity_data2 = apex2->VerifyApexVerity();
ASSERT_TRUE(IsOk(verity_data2));
// Now call PrepareHashTree again. Since digest doesn't match, hashtree
@@ -112,20 +115,5 @@ TEST(ApexdVerityTest, RegenerateHashree) {
ASSERT_NE(first_hashtree, second_hashtree) << hashtree_file << " was reused";
}
-TEST(ApexdVerityTest, CannotPrepareHashTreeForCompressedApex) {
- TemporaryDir td;
-
- auto apex =
- ApexFile::Open(GetTestFile("com.android.apex.compressed.v1.capex"));
- ASSERT_TRUE(IsOk(apex));
- std::string hash_tree;
- ApexVerityData verity_data;
- auto result = PrepareHashTree(*apex, verity_data, hash_tree);
- ASSERT_FALSE(IsOk(result));
- ASSERT_THAT(
- result.error().message(),
- ::testing::HasSubstr("Cannot prepare HashTree of compressed APEX"));
-}
-
} // namespace apex
} // namespace android
diff --git a/apexd/apexservice.cpp b/apexd/apexservice.cpp
index 4f3d2fc3..b8aced60 100644
--- a/apexd/apexservice.cpp
+++ b/apexd/apexservice.cpp
@@ -36,14 +36,13 @@
#include <utils/String16.h>
#include "apex_file.h"
-#include "apex_file_repository.h"
+#include "apex_preinstalled_data.h"
#include "apexd.h"
#include "apexd_session.h"
#include "string_log.h"
#include <android/apex/BnApexService.h>
-using android::base::Join;
using android::base::Result;
namespace android {
@@ -79,10 +78,10 @@ class ApexService : public BnApexService {
BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
BinderStatus getStagedSessionInfo(
int session_id, ApexSessionInfo* apex_session_info) override;
- BinderStatus activatePackage(const std::string& package_path) override;
- BinderStatus deactivatePackage(const std::string& package_path) override;
+ BinderStatus activatePackage(const std::string& packagePath) override;
+ BinderStatus deactivatePackage(const std::string& packagePath) override;
BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
- BinderStatus getActivePackage(const std::string& package_name,
+ BinderStatus getActivePackage(const std::string& packageName,
ApexInfo* aidl_return) override;
BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
BinderStatus preinstallPackages(
@@ -93,26 +92,14 @@ class ApexService : public BnApexService {
BinderStatus revertActiveSessions() override;
BinderStatus resumeRevertIfNeeded() override;
BinderStatus snapshotCeData(int user_id, int rollback_id,
- const std::string& apex_name) override;
+ const std::string& apex_name,
+ int64_t* _aidl_return) override;
BinderStatus restoreCeData(int user_id, int rollback_id,
const std::string& apex_name) override;
BinderStatus destroyDeSnapshots(int rollback_id) override;
- BinderStatus destroyCeSnapshots(int user_id, int rollback_id) override;
BinderStatus destroyCeSnapshotsNotSpecified(
int user_id, const std::vector<int>& retain_rollback_ids) override;
BinderStatus remountPackages() override;
- BinderStatus recollectPreinstalledData(
- const std::vector<std::string>& paths) override;
- BinderStatus recollectDataApex(const std::string& path,
- const std::string& decompression_dir) override;
- BinderStatus markBootCompleted() override;
- BinderStatus calculateSizeForCompressedApex(
- const CompressedApexInfoList& compressed_apex_info_list,
- int64_t* required_size) override;
- BinderStatus reserveSpaceForCompressedApex(
- const CompressedApexInfoList& compressed_apex_info_list) override;
- BinderStatus installAndActivatePackage(const std::string& package_path,
- ApexInfo* aidl_return) override;
status_t dump(int fd, const Vector<String16>& args) override;
@@ -133,37 +120,39 @@ BinderStatus CheckDebuggable(const std::string& name) {
}
BinderStatus ApexService::stagePackages(const std::vector<std::string>& paths) {
- BinderStatus debug_check = CheckDebuggable("stagePackages");
- if (!debug_check.isOk()) {
- return debug_check;
+ BinderStatus debugCheck = CheckDebuggable("stagePackages");
+ if (!debugCheck.isOk()) {
+ return debugCheck;
}
LOG(DEBUG) << "stagePackages() received by ApexService, paths "
<< android::base::Join(paths, ',');
- Result<void> res = ::android::apex::StagePackages(paths);
+ Result<void> res = ::android::apex::stagePackages(paths);
if (res.ok()) {
return BinderStatus::ok();
}
+ // TODO: Get correct binder error status.
LOG(ERROR) << "Failed to stage " << android::base::Join(paths, ',') << ": "
<< res.error();
return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
+ BinderStatus::EX_ILLEGAL_ARGUMENT,
String8(res.error().message().c_str()));
}
BinderStatus ApexService::unstagePackages(
const std::vector<std::string>& paths) {
- Result<void> res = ::android::apex::UnstagePackages(paths);
+ Result<void> res = ::android::apex::unstagePackages(paths);
if (res.ok()) {
return BinderStatus::ok();
}
+ // TODO: Get correct binder error status.
LOG(ERROR) << "Failed to unstage " << android::base::Join(paths, ',') << ": "
<< res.error();
return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
+ BinderStatus::EX_ILLEGAL_ARGUMENT,
String8(res.error().message().c_str()));
}
@@ -173,7 +162,7 @@ BinderStatus ApexService::submitStagedSession(const ApexSessionParams& params,
<< params.sessionId << " child sessions: ["
<< android::base::Join(params.childSessionIds, ',') << "]";
- Result<std::vector<ApexFile>> packages = ::android::apex::SubmitStagedSession(
+ Result<std::vector<ApexFile>> packages = ::android::apex::submitStagedSession(
params.sessionId, params.childSessionIds, params.hasRollbackEnabled,
params.isRollback, params.rollbackId);
if (!packages.ok()) {
@@ -197,7 +186,7 @@ BinderStatus ApexService::submitStagedSession(const ApexSessionParams& params,
BinderStatus ApexService::markStagedSessionReady(int session_id) {
LOG(DEBUG) << "markStagedSessionReady() received by ApexService, session id "
<< session_id;
- Result<void> success = ::android::apex::MarkStagedSessionReady(session_id);
+ Result<void> success = ::android::apex::markStagedSessionReady(session_id);
if (!success.ok()) {
LOG(ERROR) << "Failed to mark session id " << session_id
<< " as ready: " << success.error();
@@ -212,7 +201,7 @@ BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
LOG(DEBUG)
<< "markStagedSessionSuccessful() received by ApexService, session id "
<< session_id;
- Result<void> ret = ::android::apex::MarkStagedSessionSuccessful(session_id);
+ Result<void> ret = ::android::apex::markStagedSessionSuccessful(session_id);
if (!ret.ok()) {
LOG(ERROR) << "Failed to mark session " << session_id
<< " as SUCCESS: " << ret.error();
@@ -223,43 +212,6 @@ BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
return BinderStatus::ok();
}
-BinderStatus ApexService::markBootCompleted() {
- ::android::apex::OnBootCompleted();
- return BinderStatus::ok();
-}
-
-BinderStatus ApexService::calculateSizeForCompressedApex(
- const CompressedApexInfoList& compressed_apex_info_list,
- int64_t* required_size) {
- *required_size = 0;
- const auto& instance = ApexFileRepository::GetInstance();
- 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();
-}
-
-BinderStatus ApexService::reserveSpaceForCompressedApex(
- const CompressedApexInfoList& compressed_apex_info_list) {
- int64_t required_size;
- if (auto res = calculateSizeForCompressedApex(compressed_apex_info_list,
- &required_size);
- !res.isOk()) {
- return res;
- }
- if (auto res = ReserveSpaceForCompressedApex(required_size, kOtaReservedDir);
- !res.ok()) {
- return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
- String8(res.error().message().c_str()));
- }
- return BinderStatus::ok();
-}
-
static void ClearSessionInfo(ApexSessionInfo* session_info) {
session_info->sessionId = -1;
session_info->isUnknown = false;
@@ -273,14 +225,13 @@ static void ClearSessionInfo(ApexSessionInfo* session_info) {
session_info->isRevertFailed = false;
}
-void ConvertToApexSessionInfo(const ApexSession& session,
+void convertToApexSessionInfo(const ApexSession& session,
ApexSessionInfo* session_info) {
using SessionState = ::apex::proto::SessionState;
ClearSessionInfo(session_info);
session_info->sessionId = session.GetId();
session_info->crashingNativeProcess = session.GetCrashingNativeProcess();
- session_info->errorMessage = session.GetErrorMessage();
switch (session.GetState()) {
case SessionState::VERIFIED:
@@ -314,24 +265,23 @@ void ConvertToApexSessionInfo(const ApexSession& session,
}
}
-static ApexInfo GetApexInfo(const ApexFile& package) {
- auto& instance = ApexFileRepository::GetInstance();
+static ApexInfo getApexInfo(const ApexFile& package) {
ApexInfo out;
out.moduleName = package.GetManifest().name();
out.modulePath = package.GetPath();
out.versionCode = package.GetManifest().version();
out.versionName = package.GetManifest().versionname();
- out.isFactory = instance.IsPreInstalledApex(package);
+ out.isFactory = package.IsBuiltin();
out.isActive = false;
- Result<std::string> preinstalled_path =
- instance.GetPreinstalledPath(package.GetManifest().name());
- if (preinstalled_path.ok()) {
- out.preinstalledModulePath = *preinstalled_path;
+ Result<std::string> preinstalledPath =
+ getApexPreinstalledPath(package.GetManifest().name());
+ if (preinstalledPath.ok()) {
+ out.preinstalledModulePath = *preinstalledPath;
}
return out;
}
-static std::string ToString(const ApexInfo& package) {
+static std::string toString(const ApexInfo& package) {
std::string msg = StringLog()
<< "Module: " << package.moduleName
<< " Version: " << package.versionCode
@@ -347,9 +297,9 @@ BinderStatus ApexService::getSessions(
std::vector<ApexSessionInfo>* aidl_return) {
auto sessions = ApexSession::GetSessions();
for (const auto& session : sessions) {
- ApexSessionInfo session_info;
- ConvertToApexSessionInfo(session, &session_info);
- aidl_return->push_back(session_info);
+ ApexSessionInfo sessionInfo;
+ convertToApexSessionInfo(session, &sessionInfo);
+ aidl_return->push_back(sessionInfo);
}
return BinderStatus::ok();
@@ -367,80 +317,82 @@ BinderStatus ApexService::getStagedSessionInfo(
return BinderStatus::ok();
}
- ConvertToApexSessionInfo(*session, apex_session_info);
+ convertToApexSessionInfo(*session, apex_session_info);
return BinderStatus::ok();
}
-BinderStatus ApexService::activatePackage(const std::string& package_path) {
- BinderStatus debug_check = CheckDebuggable("activatePackage");
- if (!debug_check.isOk()) {
- return debug_check;
+BinderStatus ApexService::activatePackage(const std::string& packagePath) {
+ BinderStatus debugCheck = CheckDebuggable("activatePackage");
+ if (!debugCheck.isOk()) {
+ return debugCheck;
}
LOG(DEBUG) << "activatePackage() received by ApexService, path "
- << package_path;
+ << packagePath;
- Result<void> res = ::android::apex::ActivatePackage(package_path);
+ Result<void> res = ::android::apex::activatePackage(packagePath);
if (res.ok()) {
return BinderStatus::ok();
}
- LOG(ERROR) << "Failed to activate " << package_path << ": " << res.error();
+ // TODO: Get correct binder error status.
+ LOG(ERROR) << "Failed to activate " << packagePath << ": " << res.error();
return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
+ BinderStatus::EX_ILLEGAL_ARGUMENT,
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;
+BinderStatus ApexService::deactivatePackage(const std::string& packagePath) {
+ BinderStatus debugCheck = CheckDebuggable("deactivatePackage");
+ if (!debugCheck.isOk()) {
+ return debugCheck;
}
LOG(DEBUG) << "deactivatePackage() received by ApexService, path "
- << package_path;
+ << packagePath;
- Result<void> res = ::android::apex::DeactivatePackage(package_path);
+ Result<void> res = ::android::apex::deactivatePackage(packagePath);
if (res.ok()) {
return BinderStatus::ok();
}
- LOG(ERROR) << "Failed to deactivate " << package_path << ": " << res.error();
+ // TODO: Get correct binder error status.
+ LOG(ERROR) << "Failed to deactivate " << packagePath << ": " << res.error();
return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
+ BinderStatus::EX_ILLEGAL_ARGUMENT,
String8(res.error().message().c_str()));
}
BinderStatus ApexService::getActivePackages(
std::vector<ApexInfo>* aidl_return) {
- auto packages = ::android::apex::GetActivePackages();
+ auto packages = ::android::apex::getActivePackages();
for (const auto& package : packages) {
- ApexInfo apex_info = GetApexInfo(package);
- apex_info.isActive = true;
- aidl_return->push_back(std::move(apex_info));
+ ApexInfo apexInfo = getApexInfo(package);
+ apexInfo.isActive = true;
+ aidl_return->push_back(std::move(apexInfo));
}
return BinderStatus::ok();
}
-BinderStatus ApexService::getActivePackage(const std::string& package_name,
+BinderStatus ApexService::getActivePackage(const std::string& packageName,
ApexInfo* aidl_return) {
- Result<ApexFile> apex = ::android::apex::GetActivePackage(package_name);
+ Result<ApexFile> apex = ::android::apex::getActivePackage(packageName);
if (apex.ok()) {
- *aidl_return = GetApexInfo(*apex);
+ *aidl_return = getApexInfo(*apex);
aidl_return->isActive = true;
}
return BinderStatus::ok();
}
BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
- const auto& active = ::android::apex::GetActivePackages();
- const auto& factory = ::android::apex::GetFactoryPackages();
+ const auto& active = ::android::apex::getActivePackages();
+ const auto& factory = ::android::apex::getFactoryPackages();
for (const ApexFile& pkg : active) {
- ApexInfo apex_info = GetApexInfo(pkg);
+ ApexInfo apex_info = getApexInfo(pkg);
apex_info.isActive = true;
aidl_return->push_back(std::move(apex_info));
}
@@ -449,70 +401,55 @@ BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
return o.GetPath() == pkg.GetPath();
};
if (std::find_if(active.begin(), active.end(), same_path) == active.end()) {
- aidl_return->push_back(GetApexInfo(pkg));
+ aidl_return->push_back(getApexInfo(pkg));
}
}
return BinderStatus::ok();
}
-BinderStatus ApexService::installAndActivatePackage(
- const std::string& package_path, ApexInfo* aidl_return) {
- LOG(DEBUG) << "installAndActivatePackage() received by ApexService, path: "
- << package_path;
- auto res = InstallPackage(package_path);
- if (!res.ok()) {
- LOG(ERROR) << "Failed to install package " << package_path << " : "
- << res.error();
- return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
- String8(res.error().message().c_str()));
- }
- *aidl_return = GetApexInfo(*res);
- aidl_return->isActive = true;
- return BinderStatus::ok();
-}
-
BinderStatus ApexService::preinstallPackages(
const std::vector<std::string>& paths) {
- BinderStatus debug_check = CheckDebuggable("preinstallPackages");
- if (!debug_check.isOk()) {
- return debug_check;
+ BinderStatus debugCheck = CheckDebuggable("preinstallPackages");
+ if (!debugCheck.isOk()) {
+ return debugCheck;
}
- Result<void> res = ::android::apex::PreinstallPackages(paths);
+ Result<void> res = ::android::apex::preinstallPackages(paths);
if (res.ok()) {
return BinderStatus::ok();
}
+ // TODO: Get correct binder error status.
LOG(ERROR) << "Failed to preinstall packages "
<< android::base::Join(paths, ',') << ": " << res.error();
return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
+ BinderStatus::EX_ILLEGAL_ARGUMENT,
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;
+ BinderStatus debugCheck = CheckDebuggable("postinstallPackages");
+ if (!debugCheck.isOk()) {
+ return debugCheck;
}
- Result<void> res = ::android::apex::PostinstallPackages(paths);
+ Result<void> res = ::android::apex::postinstallPackages(paths);
if (res.ok()) {
return BinderStatus::ok();
}
+ // TODO: Get correct binder error status.
LOG(ERROR) << "Failed to postinstall packages "
<< android::base::Join(paths, ',') << ": " << res.error();
return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
+ BinderStatus::EX_ILLEGAL_ARGUMENT,
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);
+ Result<void> res = ::android::apex::abortStagedSession(session_id);
if (!res.ok()) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_ILLEGAL_ARGUMENT,
@@ -523,7 +460,7 @@ BinderStatus ApexService::abortStagedSession(int session_id) {
BinderStatus ApexService::revertActiveSessions() {
LOG(DEBUG) << "revertActiveSessions() received by ApexService.";
- Result<void> res = ::android::apex::RevertActiveSessions("", "");
+ Result<void> res = ::android::apex::revertActiveSessions("");
if (!res.ok()) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_ILLEGAL_ARGUMENT,
@@ -533,13 +470,13 @@ BinderStatus ApexService::revertActiveSessions() {
}
BinderStatus ApexService::resumeRevertIfNeeded() {
- BinderStatus debug_check = CheckDebuggable("resumeRevertIfNeeded");
- if (!debug_check.isOk()) {
- return debug_check;
+ BinderStatus debugCheck = CheckDebuggable("resumeRevertIfNeeded");
+ if (!debugCheck.isOk()) {
+ return debugCheck;
}
LOG(DEBUG) << "resumeRevertIfNeeded() received by ApexService.";
- Result<void> res = ::android::apex::ResumeRevertIfNeeded();
+ Result<void> res = ::android::apex::resumeRevertIfNeeded();
if (!res.ok()) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_ILLEGAL_ARGUMENT,
@@ -549,15 +486,17 @@ BinderStatus ApexService::resumeRevertIfNeeded() {
}
BinderStatus ApexService::snapshotCeData(int user_id, int rollback_id,
- const std::string& apex_name) {
+ const std::string& apex_name,
+ int64_t* _aidl_return) {
LOG(DEBUG) << "snapshotCeData() received by ApexService.";
- Result<void> res =
- ::android::apex::SnapshotCeData(user_id, rollback_id, apex_name);
+ Result<ino_t> res =
+ ::android::apex::snapshotCeData(user_id, rollback_id, apex_name);
if (!res.ok()) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_SERVICE_SPECIFIC,
String8(res.error().message().c_str()));
}
+ *_aidl_return = static_cast<uint64_t>(*res);
return BinderStatus::ok();
}
@@ -565,7 +504,7 @@ BinderStatus ApexService::restoreCeData(int user_id, int rollback_id,
const std::string& apex_name) {
LOG(DEBUG) << "restoreCeData() received by ApexService.";
Result<void> res =
- ::android::apex::RestoreCeData(user_id, rollback_id, apex_name);
+ ::android::apex::restoreCeData(user_id, rollback_id, apex_name);
if (!res.ok()) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_SERVICE_SPECIFIC,
@@ -576,19 +515,8 @@ BinderStatus ApexService::restoreCeData(int user_id, int rollback_id,
BinderStatus ApexService::destroyDeSnapshots(int rollback_id) {
LOG(DEBUG) << "destroyDeSnapshots() received by ApexService.";
- Result<void> res = ::android::apex::DestroyDeSnapshots(rollback_id);
- if (!res.ok()) {
- return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
- String8(res.error().message().c_str()));
- }
- return BinderStatus::ok();
-}
-
-BinderStatus ApexService::destroyCeSnapshots(int user_id, int rollback_id) {
- LOG(DEBUG) << "destroyCeSnapshots() received by ApexService.";
- Result<void> res = ::android::apex::DestroyCeSnapshots(user_id, rollback_id);
- if (!res.ok()) {
+ Result<void> res = ::android::apex::destroyDeSnapshots(rollback_id);
+ if (!res) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_SERVICE_SPECIFIC,
String8(res.error().message().c_str()));
@@ -599,9 +527,9 @@ BinderStatus ApexService::destroyCeSnapshots(int user_id, int rollback_id) {
BinderStatus ApexService::destroyCeSnapshotsNotSpecified(
int user_id, const std::vector<int>& retain_rollback_ids) {
LOG(DEBUG) << "destroyCeSnapshotsNotSpecified() received by ApexService.";
- Result<void> res = ::android::apex::DestroyCeSnapshotsNotSpecified(
+ Result<void> res = ::android::apex::destroyCeSnapshotsNotSpecified(
user_id, retain_rollback_ids);
- if (!res.ok()) {
+ if (!res) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_SERVICE_SPECIFIC,
String8(res.error().message().c_str()));
@@ -617,47 +545,7 @@ BinderStatus ApexService::remountPackages() {
if (auto root = CheckCallerIsRoot("remountPackages"); !root.isOk()) {
return root;
}
- if (auto res = ::android::apex::RemountPackages(); !res.ok()) {
- return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
- String8(res.error().message().c_str()));
- }
- return BinderStatus::ok();
-}
-
-BinderStatus ApexService::recollectPreinstalledData(
- const std::vector<std::string>& paths) {
- LOG(DEBUG) << "recollectPreinstalledData() received by ApexService, paths: "
- << Join(paths, ',');
- if (auto debug = CheckDebuggable("recollectPreinstalledData");
- !debug.isOk()) {
- return debug;
- }
- if (auto root = CheckCallerIsRoot("recollectPreinstalledData");
- !root.isOk()) {
- return root;
- }
- ApexFileRepository& instance = ApexFileRepository::GetInstance();
- if (auto res = instance.AddPreInstalledApex(paths); !res.ok()) {
- return BinderStatus::fromExceptionCode(
- BinderStatus::EX_SERVICE_SPECIFIC,
- String8(res.error().message().c_str()));
- }
- return BinderStatus::ok();
-}
-
-BinderStatus ApexService::recollectDataApex(
- const std::string& path, const std::string& decompression_dir) {
- LOG(DEBUG) << "recollectDataApex() received by ApexService, paths " << path
- << " and " << decompression_dir;
- if (auto debug = CheckDebuggable("recollectDataApex"); !debug.isOk()) {
- return debug;
- }
- if (auto root = CheckCallerIsRoot("recollectDataApex"); !root.isOk()) {
- return root;
- }
- ApexFileRepository& instance = ApexFileRepository::GetInstance();
- if (auto res = instance.AddDataApex(path); !res.ok()) {
+ if (auto res = ::android::apex::remountPackages(); !res.ok()) {
return BinderStatus::fromExceptionCode(
BinderStatus::EX_SERVICE_SPECIFIC,
String8(res.error().message().c_str()));
@@ -677,18 +565,16 @@ status_t ApexService::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) {
args.add(_aidl_data.readString16());
}
- sp<IBinder> unused_callback;
- sp<IResultReceiver> result_receiver;
+ sp<IBinder> unusedCallback;
+ sp<IResultReceiver> resultReceiver;
status_t status;
- if ((status = _aidl_data.readNullableStrongBinder(&unused_callback)) !=
- OK)
+ if ((status = _aidl_data.readNullableStrongBinder(&unusedCallback)) != OK)
return status;
- if ((status = _aidl_data.readNullableStrongBinder(&result_receiver)) !=
- OK)
+ if ((status = _aidl_data.readNullableStrongBinder(&resultReceiver)) != OK)
return status;
status = shellCommand(in, out, err, args);
- if (result_receiver != nullptr) {
- result_receiver->send(status);
+ if (resultReceiver != nullptr) {
+ resultReceiver->send(status);
}
return OK;
}
@@ -707,7 +593,7 @@ status_t ApexService::dump(int fd, const Vector<String16>& /*args*/) {
return BAD_VALUE;
} else {
for (const auto& item : list) {
- std::string msg = ToString(item);
+ std::string msg = toString(item);
dprintf(fd, "%s", msg.c_str());
}
}
@@ -725,19 +611,14 @@ status_t ApexService::dump(int fd, const Vector<String16>& /*args*/) {
}
}
std::string revert_reason = "";
- const auto& crashing_native_process = session.GetCrashingNativeProcess();
+ std::string crashing_native_process = session.GetCrashingNativeProcess();
if (!crashing_native_process.empty()) {
revert_reason = " Revert Reason: " + crashing_native_process;
}
- std::string error_message_dump = "";
- const auto& error_message = session.GetErrorMessage();
- if (!error_message.empty()) {
- error_message_dump = " Error Message: " + error_message;
- }
std::string msg =
StringLog() << "Session ID: " << session.GetId() << child_ids_str
<< " State: " << SessionState_State_Name(session.GetState())
- << revert_reason << error_message_dump << std::endl;
+ << revert_reason << std::endl;
dprintf(fd, "%s", msg.c_str());
}
@@ -756,25 +637,25 @@ status_t ApexService::shellCommand(int in, int out, int err,
}
log << "ApexService:" << std::endl
<< " help - display this help" << std::endl
- << " stagePackages [package_path1] ([package_path2]...) - stage "
+ << " stagePackages [packagePath1] ([packagePath2]...) - stage "
"multiple packages from the given path"
<< std::endl
- << " getActivePackage [package_name] - return info for active package "
+ << " getActivePackage [packageName] - return info for active package "
"with given name, if present"
<< std::endl
<< " getAllPackages - return the list of all packages" << std::endl
<< " getActivePackages - return the list of active packages"
<< std::endl
- << " activatePackage [package_path] - activate package from the "
+ << " activatePackage [packagePath] - activate package from the "
"given path"
<< std::endl
- << " deactivatePackage [package_path] - deactivate package from the "
+ << " deactivatePackage [packagePath] - deactivate package from the "
"given path"
<< std::endl
- << " preinstallPackages [package_path1] ([package_path2]...) - run "
+ << " preinstallPackages [packagePath1] ([packagePath2]...) - run "
"pre-install hooks of the given packages"
<< std::endl
- << " postinstallPackages [package_path1] ([package_path2]...) - run "
+ << " postinstallPackages [packagePath1] ([packagePath2]...) - run "
"post-install hooks of the given packages"
<< std::endl
<< " getStagedSessionInfo [sessionId] - displays information about a "
@@ -806,7 +687,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
if (cmd == String16("stagePackages")) {
if (args.size() < 2) {
- print_help(err, "stagePackages requires at least one package_path");
+ print_help(err, "stagePackages requires at least one packagePath");
return BAD_VALUE;
}
std::vector<std::string> pkgs;
@@ -832,7 +713,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
BinderStatus status = getAllPackages(&list);
if (status.isOk()) {
for (const auto& item : list) {
- std::string msg = ToString(item);
+ std::string msg = toString(item);
dprintf(out, "%s", msg.c_str());
}
return OK;
@@ -852,7 +733,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
BinderStatus status = getActivePackages(&list);
if (status.isOk()) {
for (const auto& item : list) {
- std::string msg = ToString(item);
+ std::string msg = toString(item);
dprintf(out, "%s", msg.c_str());
}
return OK;
@@ -872,7 +753,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
ApexInfo package;
BinderStatus status = getActivePackage(String8(args[1]).string(), &package);
if (status.isOk()) {
- std::string msg = ToString(package);
+ std::string msg = toString(package);
dprintf(out, "%s", msg.c_str());
return OK;
}
@@ -887,7 +768,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
if (cmd == String16("activatePackage")) {
if (args.size() != 2) {
- print_help(err, "activatePackage requires one package_path");
+ print_help(err, "activatePackage requires one packagePath");
return BAD_VALUE;
}
BinderStatus status = activatePackage(String8(args[1]).string());
@@ -902,7 +783,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
if (cmd == String16("deactivatePackage")) {
if (args.size() != 2) {
- print_help(err, "deactivatePackage requires one package_path");
+ print_help(err, "deactivatePackage requires one packagePath");
return BAD_VALUE;
}
BinderStatus status = deactivatePackage(String8(args[1]).string());
@@ -975,7 +856,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
BinderStatus status = submitStagedSession(params, &list);
if (status.isOk()) {
for (const auto& item : list.apexInfos) {
- std::string msg = ToString(item);
+ std::string msg = toString(item);
dprintf(out, "%s", msg.c_str());
}
return OK;
@@ -991,7 +872,7 @@ status_t ApexService::shellCommand(int in, int out, int err,
if (args.size() < 2) {
print_help(err,
"preinstallPackages/postinstallPackages requires at least"
- " one package_path");
+ " one packagePath");
return BAD_VALUE;
}
std::vector<std::string> pkgs;
@@ -1048,15 +929,15 @@ void CreateAndRegisterService() {
sp<ProcessState> ps(ProcessState::self());
// Create binder service and register with LazyServiceRegistrar
- sp<ApexService> apex_service = sp<ApexService>::make();
- auto lazy_registrar = LazyServiceRegistrar::getInstance();
- lazy_registrar.forcePersist(true);
- lazy_registrar.registerService(apex_service, kApexServiceName);
+ sp<ApexService> apexService = new ApexService();
+ auto lazyRegistrar = LazyServiceRegistrar::getInstance();
+ lazyRegistrar.forcePersist(true);
+ lazyRegistrar.registerService(apexService, kApexServiceName);
}
void AllowServiceShutdown() {
- auto lazy_registrar = LazyServiceRegistrar::getInstance();
- lazy_registrar.forcePersist(false);
+ auto lazyRegistrar = LazyServiceRegistrar::getInstance();
+ lazyRegistrar.forcePersist(false);
}
void StartThreadPool() {
diff --git a/apexd/apexservice_test.cpp b/apexd/apexservice_test.cpp
index 545bb38d..7f78610c 100644
--- a/apexd/apexservice_test.cpp
+++ b/apexd/apexservice_test.cpp
@@ -59,8 +59,8 @@
#include "apexd_session.h"
#include "apexd_test_utils.h"
#include "apexd_utils.h"
+
#include "session_state.pb.h"
-#include "string_log.h"
using apex::proto::SessionState;
@@ -73,8 +73,6 @@ 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::ErrnoError;
using android::base::Join;
using android::base::ReadFully;
using android::base::StartsWith;
@@ -84,7 +82,6 @@ using android::dm::DeviceMapper;
using android::fs_mgr::Fstab;
using android::fs_mgr::GetEntryForMountPoint;
using android::fs_mgr::ReadFstabFromFile;
-using ::apex::proto::ApexManifest;
using ::testing::Contains;
using ::testing::EndsWith;
using ::testing::HasSubstr;
@@ -126,7 +123,6 @@ class ApexServiceTest : public ::testing::Test {
vold_service_->supportsCheckpoint(&supports_fs_checkpointing_);
ASSERT_TRUE(IsOk(status));
CleanUp();
- service_->recollectPreinstalledData(kApexPackageBuiltinDirs);
}
void TearDown() override { CleanUp(); }
@@ -300,8 +296,9 @@ class ApexServiceTest : public ::testing::Test {
"-f",
file,
};
- auto res = ForkAndRun(args);
- CHECK(res.ok()) << res.error();
+ std::string error_msg;
+ int res = ForkAndRun(args, &error_msg);
+ CHECK_EQ(0, res) << error_msg;
std::string data;
CHECK(android::base::ReadFileToString(file, &data));
@@ -450,10 +447,21 @@ class ApexServiceTest : public ::testing::Test {
private:
void CleanUp() {
- DeleteDirContent(kActiveApexPackagesDataDir);
- DeleteDirContent(kApexBackupDir);
- DeleteDirContent(kApexHashTreeDir);
- DeleteDirContent(ApexSession::GetSessionsDir());
+ auto status = WalkDir(kApexDataDir, [](const fs::directory_entry& p) {
+ std::error_code ec;
+ fs::file_status status = p.status(ec);
+ ASSERT_FALSE(ec) << "Failed to stat " << p.path() << " : "
+ << ec.message();
+ if (fs::is_directory(status)) {
+ fs::remove_all(p.path(), ec);
+ } else {
+ fs::remove(p.path(), ec);
+ }
+ ASSERT_FALSE(ec) << "Failed to delete " << p.path() << " : "
+ << ec.message();
+ });
+ fs::remove_all(kApexSessionsDir);
+ ASSERT_TRUE(IsOk(status));
DeleteIfExists("/data/misc_ce/0/apexdata/apex.apexd_test");
DeleteIfExists("/data/misc_ce/0/apexrollback/123456");
@@ -518,8 +526,7 @@ Result<void> ReadDevice(const std::string& block_device) {
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)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(block_device.c_str(), O_RDONLY)));
if (fd.get() == -1) {
return ErrnoError() << "Can't open " << block_device;
}
@@ -635,7 +642,7 @@ TEST_F(ApexServiceTest, StageFailKey) {
// May contain one of two errors.
std::string error = st.exceptionMessage().c_str();
- ASSERT_THAT(error, HasSubstr("No preinstalled apex found for package "
+ ASSERT_THAT(error, HasSubstr("No preinstalled data found for package "
"com.android.apex.test_package.no_inst_key"));
}
@@ -711,7 +718,7 @@ TEST_F(ApexServiceTest, SubmitStagedSessionFailDoesNotLeakTempVerityDevices) {
}
}
-TEST_F(ApexServiceTest, StageSuccessClearsPreviouslyActivePackage) {
+TEST_F(ApexServiceTest, StageSuccess_ClearsPreviouslyActivePackage) {
PrepareTestApexForInstall installer1(GetTestFile("apex.apexd_test_v2.apex"));
PrepareTestApexForInstall installer2(
GetTestFile("apex.apexd_test_different_app.apex"));
@@ -775,6 +782,7 @@ TEST_F(ApexServiceTest, MultiStageSuccess) {
}
ASSERT_EQ(std::string("com.android.apex.test_package"), installer.package);
+ // TODO: Add second test. Right now, just use a separate version.
PrepareTestApexForInstall installer2(GetTestFile("apex.apexd_test_v2.apex"));
if (!installer2.Prepare()) {
return;
@@ -832,10 +840,18 @@ TEST_F(ApexServiceTest, SnapshotCeData) {
ASSERT_TRUE(
RegularFileExists("/data/misc_ce/0/apexdata/apex.apexd_test/hello.txt"));
- service_->snapshotCeData(0, 123456, "apex.apexd_test");
+ int64_t result;
+ service_->snapshotCeData(0, 123456, "apex.apexd_test", &result);
ASSERT_TRUE(RegularFileExists(
"/data/misc_ce/0/apexrollback/123456/apex.apexd_test/hello.txt"));
+
+ // Check that the return value is the inode of the snapshot directory.
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ ASSERT_EQ(0,
+ stat("/data/misc_ce/0/apexrollback/123456/apex.apexd_test", &buf));
+ ASSERT_EQ(int64_t(buf.st_ino), result);
}
TEST_F(ApexServiceTest, RestoreCeData) {
@@ -862,7 +878,7 @@ TEST_F(ApexServiceTest, RestoreCeData) {
DirExists("/data/misc_ce/0/apexrollback/123456/apex.apexd_test"));
}
-TEST_F(ApexServiceTest, DestroyDeSnapshotsDeSys) {
+TEST_F(ApexServiceTest, DestroyDeSnapshots_DeSys) {
CreateDir("/data/misc/apexrollback/123456");
CreateDir("/data/misc/apexrollback/123456/my.apex");
CreateFile("/data/misc/apexrollback/123456/my.apex/hello.txt");
@@ -880,7 +896,7 @@ TEST_F(ApexServiceTest, DestroyDeSnapshotsDeSys) {
ASSERT_FALSE(DirExists("/data/misc/apexrollback/123456"));
}
-TEST_F(ApexServiceTest, DestroyDeSnapshotsDeUser) {
+TEST_F(ApexServiceTest, DestroyDeSnapshots_DeUser) {
CreateDir("/data/misc_de/0/apexrollback/123456");
CreateDir("/data/misc_de/0/apexrollback/123456/my.apex");
CreateFile("/data/misc_de/0/apexrollback/123456/my.apex/hello.txt");
@@ -898,31 +914,6 @@ TEST_F(ApexServiceTest, DestroyDeSnapshotsDeUser) {
ASSERT_FALSE(DirExists("/data/misc_de/0/apexrollback/123456"));
}
-TEST_F(ApexServiceTest, DestroyCeSnapshots) {
- CreateDir("/data/misc_ce/0/apexrollback/123456");
- CreateDir("/data/misc_ce/0/apexrollback/123456/apex.apexd_test");
- CreateFile("/data/misc_ce/0/apexrollback/123456/apex.apexd_test/file.txt");
-
- CreateDir("/data/misc_ce/0/apexrollback/77777");
- CreateDir("/data/misc_ce/0/apexrollback/77777/apex.apexd_test");
- CreateFile("/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt");
-
- ASSERT_TRUE(RegularFileExists(
- "/data/misc_ce/0/apexrollback/123456/apex.apexd_test/file.txt"));
- ASSERT_TRUE(RegularFileExists(
- "/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt"));
-
- android::binder::Status st = service_->destroyCeSnapshots(0, 123456);
- ASSERT_TRUE(IsOk(st));
- // Should be OK if the directory doesn't exist.
- st = service_->destroyCeSnapshots(1, 123456);
- ASSERT_TRUE(IsOk(st));
-
- ASSERT_TRUE(RegularFileExists(
- "/data/misc_ce/0/apexrollback/77777/apex.apexd_test/thing.txt"));
- ASSERT_FALSE(DirExists("/data/misc_ce/0/apexrollback/123456"));
-}
-
TEST_F(ApexServiceTest, DestroyCeSnapshotsNotSpecified) {
CreateDir("/data/misc_ce/0/apexrollback/123456");
CreateDir("/data/misc_ce/0/apexrollback/123456/apex.apexd_test");
@@ -954,31 +945,6 @@ TEST_F(ApexServiceTest, DestroyCeSnapshotsNotSpecified) {
ASSERT_FALSE(DirExists("/data/misc_ce/0/apexrollback/98765"));
}
-TEST_F(ApexServiceTest, SubmitStagedSessionCleanupsTempMountOnFailure) {
- // Parent session id: 23
- // Children session ids: 37 73
- PrepareTestApexForInstall installer(
- GetTestFile("apex.apexd_test_different_app.apex"),
- "/data/app-staging/session_37", "staging_data_file");
- PrepareTestApexForInstall installer2(
- GetTestFile("apex.apexd_test_manifest_mismatch.apex"),
- "/data/app-staging/session_73", "staging_data_file");
- if (!installer.Prepare() || !installer2.Prepare()) {
- FAIL() << GetDebugStr(&installer) << GetDebugStr(&installer2);
- }
- ApexInfoList list;
- ApexSessionParams params;
- params.sessionId = 23;
- params.childSessionIds = {37, 73};
- ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)))
- << GetDebugStr(&installer);
-
- // Check that temp mounts were cleanded up.
- for (const auto& mount : GetApexMounts()) {
- EXPECT_FALSE(EndsWith(mount, ".tmp")) << "Found temp mount " << mount;
- }
-}
-
template <typename NameProvider>
class ApexServiceActivationTest : public ApexServiceTest {
public:
@@ -1165,8 +1131,7 @@ TEST_F(ApexServiceActivationSuccessTest, ShowsUpInMountedApexDatabase) {
<< GetDebugStr(installer_.get());
MountedApexDatabase db;
- db.PopulateFromMounts(kActiveApexPackagesDataDir, kApexDecompressedDir,
- kApexHashTreeDir);
+ db.PopulateFromMounts();
std::optional<MountedApexData> mounted_apex;
db.ForallMountedApexes(installer_->package,
@@ -1292,8 +1257,7 @@ TEST_F(ApexServiceNoHashtreeApexActivationTest, ShowsUpInMountedApexDatabase) {
<< GetDebugStr(installer_.get());
MountedApexDatabase db;
- db.PopulateFromMounts(kActiveApexPackagesDataDir, kApexDecompressedDir,
- kApexHashTreeDir);
+ db.PopulateFromMounts();
std::optional<MountedApexData> mounted_apex;
db.ForallMountedApexes(installer_->package,
@@ -1363,7 +1327,7 @@ TEST_F(ApexServiceTest, NoHashtreeApexStagePackagesMovesHashtree) {
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)));
+ unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY)));
if (fd.get() == -1) {
PLOG(ERROR) << "Failed to open " << path;
ADD_FAILURE();
@@ -1415,78 +1379,53 @@ TEST_F(ApexServiceTest, NoHashtreeApexStagePackagesMovesHashtree) {
}
TEST_F(ApexServiceTest, GetFactoryPackages) {
- Result<std::vector<ApexInfo>> factory_packages = GetFactoryPackages();
- ASSERT_TRUE(IsOk(factory_packages));
- ASSERT_TRUE(factory_packages->size() > 0);
-
- std::vector<std::string> builtin_dirs;
- for (const auto& d : kApexPackageBuiltinDirs) {
- std::string realpath;
- if (android::base::Realpath(d, &realpath)) {
- builtin_dirs.push_back(realpath);
- }
- // realpath might fail in case when dir is a non-existing path. We can
- // ignore non-existing paths.
- }
-
- // Decompressed APEX is also considred factory package
- builtin_dirs.push_back(kApexDecompressedDir);
+ Result<std::vector<ApexInfo>> factoryPackages = GetFactoryPackages();
+ ASSERT_TRUE(IsOk(factoryPackages));
+ ASSERT_TRUE(factoryPackages->size() > 0);
- for (const ApexInfo& package : *factory_packages) {
- bool is_builtin = false;
- for (const auto& dir : builtin_dirs) {
- if (StartsWith(package.modulePath, dir)) {
- is_builtin = true;
- }
- }
- ASSERT_TRUE(is_builtin);
+ for (const ApexInfo& package : *factoryPackages) {
+ ASSERT_TRUE(isPathForBuiltinApexes(package.modulePath));
}
}
TEST_F(ApexServiceTest, NoPackagesAreBothActiveAndInactive) {
- Result<std::vector<ApexInfo>> active_packages = GetActivePackages();
- ASSERT_TRUE(IsOk(active_packages));
- ASSERT_TRUE(active_packages->size() > 0);
- Result<std::vector<ApexInfo>> inactive_packages = GetInactivePackages();
- ASSERT_TRUE(IsOk(inactive_packages));
- std::vector<std::string> active_packages_strings =
- GetPackagesStrings(*active_packages);
- std::vector<std::string> inactive_packages_strings =
- GetPackagesStrings(*inactive_packages);
- std::sort(active_packages_strings.begin(), active_packages_strings.end());
- std::sort(inactive_packages_strings.begin(), inactive_packages_strings.end());
+ Result<std::vector<ApexInfo>> activePackages = GetActivePackages();
+ ASSERT_TRUE(IsOk(activePackages));
+ ASSERT_TRUE(activePackages->size() > 0);
+ Result<std::vector<ApexInfo>> inactivePackages = GetInactivePackages();
+ ASSERT_TRUE(IsOk(inactivePackages));
+ std::vector<std::string> activePackagesStrings =
+ GetPackagesStrings(*activePackages);
+ std::vector<std::string> inactivePackagesStrings =
+ GetPackagesStrings(*inactivePackages);
+ std::sort(activePackagesStrings.begin(), activePackagesStrings.end());
+ std::sort(inactivePackagesStrings.begin(), inactivePackagesStrings.end());
std::vector<std::string> intersection;
std::set_intersection(
- active_packages_strings.begin(), active_packages_strings.end(),
- inactive_packages_strings.begin(), inactive_packages_strings.end(),
+ activePackagesStrings.begin(), activePackagesStrings.end(),
+ inactivePackagesStrings.begin(), inactivePackagesStrings.end(),
std::back_inserter(intersection));
ASSERT_THAT(intersection, SizeIs(0));
}
TEST_F(ApexServiceTest, GetAllPackages) {
- Result<std::vector<ApexInfo>> all_packages = GetAllPackages();
- ASSERT_TRUE(IsOk(all_packages));
- ASSERT_TRUE(all_packages->size() > 0);
- Result<std::vector<ApexInfo>> active_packages = GetActivePackages();
- std::vector<std::string> active_strings =
- GetPackagesStrings(*active_packages);
- Result<std::vector<ApexInfo>> factory_packages = GetFactoryPackages();
- std::vector<std::string> factory_strings =
- GetPackagesStrings(*factory_packages);
- for (ApexInfo& apexInfo : *all_packages) {
- std::string package_string = GetPackageString(apexInfo);
- bool should_be_active =
- std::find(active_strings.begin(), active_strings.end(),
- package_string) != active_strings.end();
- bool should_be_factory =
- std::find(factory_strings.begin(), factory_strings.end(),
- package_string) != factory_strings.end();
- ASSERT_EQ(should_be_active, apexInfo.isActive)
- << package_string << " should " << (should_be_active ? "" : "not ")
- << "be active";
- ASSERT_EQ(should_be_factory, apexInfo.isFactory)
- << package_string << " should " << (should_be_factory ? "" : "not ")
- << "be factory";
+ Result<std::vector<ApexInfo>> allPackages = GetAllPackages();
+ ASSERT_TRUE(IsOk(allPackages));
+ ASSERT_TRUE(allPackages->size() > 0);
+ Result<std::vector<ApexInfo>> activePackages = GetActivePackages();
+ std::vector<std::string> activeStrings = GetPackagesStrings(*activePackages);
+ Result<std::vector<ApexInfo>> factoryPackages = GetFactoryPackages();
+ std::vector<std::string> factoryStrings =
+ GetPackagesStrings(*factoryPackages);
+ for (ApexInfo& apexInfo : *allPackages) {
+ std::string packageString = GetPackageString(apexInfo);
+ bool shouldBeActive = std::find(activeStrings.begin(), activeStrings.end(),
+ packageString) != activeStrings.end();
+ bool shouldBeFactory =
+ std::find(factoryStrings.begin(), factoryStrings.end(),
+ packageString) != factoryStrings.end();
+ ASSERT_EQ(shouldBeActive, apexInfo.isActive);
+ ASSERT_EQ(shouldBeFactory, apexInfo.isFactory);
}
}
@@ -1913,11 +1852,6 @@ TEST_F(ApexServiceTest, SubmitMultiSessionTestSuccess) {
expected.isVerified = false;
expected.isStaged = true;
ASSERT_THAT(session, SessionInfoEq(expected));
-
- // Check that temp mounts were cleanded up.
- for (const auto& mount : GetApexMounts()) {
- EXPECT_FALSE(EndsWith(mount, ".tmp")) << "Found temp mount " << mount;
- }
}
TEST_F(ApexServiceTest, SubmitMultiSessionTestFail) {
@@ -2049,42 +1983,6 @@ TEST_F(ApexServiceTest, AbortStagedSessionActivatedFail) {
SessionInfoEq(expected2)));
}
-// Only finalized sessions should be deleted on DeleteFinalizedSessions()
-TEST_F(ApexServiceTest, DeleteFinalizedSessions) {
- // Fetch list of all session state
- std::vector<SessionState::State> states;
- for (int i = SessionState::State_MIN; i < SessionState::State_MAX; i++) {
- if (!SessionState::State_IsValid(i)) {
- continue;
- }
- states.push_back(SessionState::State(i));
- }
-
- // For every session state, create a new session. This is to verify we only
- // delete sessions in final state.
- auto nonFinalSessions = 0u;
- for (auto i = 0u; i < states.size(); i++) {
- auto session = ApexSession::CreateSession(230 + i);
- SessionState::State state = states[i];
- ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(state)));
- if (!session->IsFinalized()) {
- nonFinalSessions++;
- }
- }
- std::vector<ApexSession> sessions = ApexSession::GetSessions();
- ASSERT_EQ(states.size(), sessions.size());
-
- // Now try cleaning up all finalized sessions
- ApexSession::DeleteFinalizedSessions();
- sessions = ApexSession::GetSessions();
- ASSERT_EQ(nonFinalSessions, sessions.size());
-
- // Verify only finalized sessions have been deleted
- for (auto& session : sessions) {
- ASSERT_FALSE(session.IsFinalized());
- }
-}
-
TEST_F(ApexServiceTest, BackupActivePackages) {
if (supports_fs_checkpointing_) {
GTEST_SKIP() << "Can't run if filesystem checkpointing is enabled";
@@ -2141,7 +2039,7 @@ TEST_F(ApexServiceTest, BackupActivePackagesClearsPreviousBackup) {
}
// Make sure /data/apex/backups exists.
- ASSERT_TRUE(IsOk(CreateDirIfNeeded(std::string(kApexBackupDir), 0700)));
+ ASSERT_TRUE(IsOk(createDirIfNeeded(std::string(kApexBackupDir), 0700)));
// Create some bogus files in /data/apex/backups.
std::ofstream old_backup(StringPrintf("%s/file1", kApexBackupDir));
ASSERT_TRUE(old_backup.good());
@@ -2185,7 +2083,7 @@ TEST_F(ApexServiceTest, BackupActivePackagesZeroActivePackages) {
// Make sure that /data/apex/active exists and is empty
ASSERT_TRUE(
- IsOk(CreateDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0755)));
+ IsOk(createDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0755)));
auto active_pkgs = ReadEntireDir(kActiveApexPackagesDataDir);
ASSERT_TRUE(IsOk(active_pkgs));
ASSERT_EQ(0u, active_pkgs->size());
@@ -2200,7 +2098,7 @@ TEST_F(ApexServiceTest, BackupActivePackagesZeroActivePackages) {
ASSERT_EQ(0u, backups->size());
}
-TEST_F(ApexServiceTest, ActivePackagesDirEmpty) {
+TEST_F(ApexServiceTest, ActivePackagesFolderDoesNotExist) {
PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"),
"/data/app-staging/session_41",
"staging_data_file");
@@ -2209,8 +2107,10 @@ TEST_F(ApexServiceTest, ActivePackagesDirEmpty) {
return;
}
- // Make sure that /data/apex/active is empty
- DeleteDirContent(kActiveApexPackagesDataDir);
+ // Make sure that /data/apex/active does not exist
+ std::error_code ec;
+ fs::remove_all(fs::path(kActiveApexPackagesDataDir), ec);
+ ASSERT_FALSE(ec) << "Failed to delete " << kActiveApexPackagesDataDir;
ApexInfoList list;
ApexSessionParams params;
@@ -2267,24 +2167,12 @@ TEST_F(ApexServiceTest, UnstagePackagesFail) {
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(); }
void PrepareBackup(const std::vector<std::string>& pkgs) {
- ASSERT_TRUE(IsOk(CreateDirIfNeeded(std::string(kApexBackupDir), 0700)));
+ ASSERT_TRUE(IsOk(createDirIfNeeded(std::string(kApexBackupDir), 0700)));
for (const auto& pkg : pkgs) {
PrepareTestApexForInstall installer(pkg);
ASSERT_TRUE(installer.Prepare()) << " failed to prepare " << pkg;
@@ -2526,10 +2414,7 @@ TEST_F(ApexServiceRevertTest, RevertStoresCrashingNativeProcess) {
// 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, "");
+ Result<void> res = ::android::apex::revertActiveSessions(native_process);
session = ApexSession::GetSession(1543);
ASSERT_EQ(session->GetCrashingNativeProcess(), native_process);
}
@@ -2717,6 +2602,21 @@ TEST_F(ApexShimUpdateTest, UpdateToV2Success) {
ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
}
+TEST_F(ApexShimUpdateTest, UpdateToV2FailureWrongSHA512) {
+ PrepareTestApexForInstall installer(
+ GetTestFile("com.android.apex.cts.shim.v2_wrong_sha.apex"));
+
+ if (!installer.Prepare()) {
+ FAIL() << GetDebugStr(&installer);
+ }
+
+ const auto& status = service_->stagePackages({installer.test_file});
+ ASSERT_FALSE(IsOk(status));
+ const std::string& error_message =
+ std::string(status.exceptionMessage().c_str());
+ ASSERT_THAT(error_message, HasSubstr("has unexpected SHA512 hash"));
+}
+
TEST_F(ApexShimUpdateTest, SubmitStagedSessionFailureHasPreInstallHook) {
PrepareTestApexForInstall installer(
GetTestFile("com.android.apex.cts.shim.v2_with_pre_install_hook.apex"),
@@ -2815,7 +2715,7 @@ TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFails) {
ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
}
-TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFailsB146895998) {
+TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFails_b146895998) {
PrepareTestApexForInstall installer(GetTestFile("corrupted_b146895998.apex"),
"/data/app-staging/session_71",
"staging_data_file");
@@ -2830,7 +2730,7 @@ TEST_F(ApexServiceTest, SubmitStagedSessionCorruptApexFailsB146895998) {
ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
}
-TEST_F(ApexServiceTest, StageCorruptApexFailsB146895998) {
+TEST_F(ApexServiceTest, StageCorruptApexFails_b146895998) {
PrepareTestApexForInstall installer(GetTestFile("corrupted_b146895998.apex"));
if (!installer.Prepare()) {
@@ -2887,10 +2787,8 @@ TEST_F(ApexServiceTest, RemountPackagesPackageOnSystemChanged) {
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);
+ // Sanity check that module path didn't change.
+ ASSERT_EQ(kSystemPath, active_apex->modulePath);
}
TEST_F(ApexServiceActivationSuccessTest, RemountPackagesPackageOnDataChanged) {
@@ -2916,25 +2814,6 @@ TEST_F(ApexServiceActivationSuccessTest, RemountPackagesPackageOnDataChanged) {
ASSERT_EQ(installer_->test_installed_file, active_apex->modulePath);
}
-TEST_F(ApexServiceTest,
- SubmitStagedSessionFailsManifestMismatchCleansUpHashtree) {
- PrepareTestApexForInstall installer(
- GetTestFile("apex.apexd_test_no_hashtree_manifest_mismatch.apex"),
- "/data/app-staging/session_83", "staging_data_file");
- if (!installer.Prepare()) {
- return;
- }
-
- ApexInfoList list;
- ApexSessionParams params;
- params.sessionId = 83;
- ASSERT_FALSE(IsOk(service_->submitStagedSession(params, &list)));
- std::string hashtree_file = std::string(kApexHashTreeDir) + "/" +
- installer.package + "@" +
- std::to_string(installer.version) + ".new";
- ASSERT_FALSE(RegularFileExists(hashtree_file));
-}
-
class LogTestToLogcat : public ::testing::EmptyTestEventListener {
void OnTestStart(const ::testing::TestInfo& test_info) override {
#ifdef __ANDROID__
@@ -2943,7 +2822,7 @@ class LogTestToLogcat : public ::testing::EmptyTestEventListener {
using base::StringPrintf;
base::LogdLogger l;
std::string msg =
- StringPrintf("=== %s::%s (%s:%d)", test_info.test_suite_name(),
+ StringPrintf("=== %s::%s (%s:%d)", test_info.test_case_name(),
test_info.name(), test_info.file(), test_info.line());
l(LogId::MAIN, LogSeverity::INFO, "ApexTestCases", __FILE__, __LINE__,
msg.c_str());
@@ -2990,164 +2869,11 @@ TEST_F(ApexServiceActivationNoCode, NoCodeApexIsNotExecutable) {
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
int main(int argc, char** argv) {
android::base::InitLogging(argv, &android::base::StderrLogger);
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
::testing::InitGoogleTest(&argc, argv);
::testing::UnitTest::GetInstance()->listeners().Append(
new android::apex::LogTestToLogcat());
diff --git a/apexd/sysprop/Android.bp b/apexd/sysprop/Android.bp
index 0b81efd9..7e3ae611 100644
--- a/apexd/sysprop/Android.bp
+++ b/apexd/sysprop/Android.bp
@@ -1,7 +1,3 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
sysprop_library {
name: "com.android.sysprop.apex",
srcs: ["ApexProperties.sysprop"],
diff --git a/apexd/sysprop/ApexProperties.sysprop b/apexd/sysprop/ApexProperties.sysprop
index 8baf2730..bd768303 100644
--- a/apexd/sysprop/ApexProperties.sysprop
+++ b/apexd/sysprop/ApexProperties.sysprop
@@ -22,19 +22,3 @@ prop {
access: Readonly
prop_name: "ro.apex.updatable"
}
-
-prop {
- api_name: "dm_delete_timeout"
- type: UInt
- scope: Internal
- access: Readonly
- prop_name: "apexd.config.dm_delete.timeout"
-}
-
-prop {
- api_name: "dm_create_timeout"
- type: UInt
- scope: Internal
- access: Readonly
- prop_name: "apexd.config.dm_create.timeout"
-}
diff --git a/apexd/sysprop/api/com.android.sysprop.apex-current.txt b/apexd/sysprop/api/com.android.sysprop.apex-current.txt
index e69de29b..17983127 100644
--- a/apexd/sysprop/api/com.android.sysprop.apex-current.txt
+++ b/apexd/sysprop/api/com.android.sysprop.apex-current.txt
@@ -0,0 +1,8 @@
+props {
+ module: "android.sysprop.ApexProperties"
+ prop {
+ api_name: "updatable"
+ scope: Internal
+ prop_name: "ro.apex.updatable"
+ }
+}
diff --git a/apexer/Android.bp b/apexer/Android.bp
index 29be7d1c..a33aade4 100644
--- a/apexer/Android.bp
+++ b/apexer/Android.bp
@@ -12,32 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
apexer_tools = [
"apexer",
"aapt2",
"avbtool",
"e2fsdroid",
+ "merge_zips",
"mke2fs",
"resize2fs",
"sefcontext_compile",
+ "soong_zip",
"zipalign",
- "make_f2fs",
- "sload_f2fs",
// TODO(b/124476339) apex doesn't follow 'required' dependencies so we need to include this
// manually for 'avbtool'.
"fec",
]
-// TODO(b/157110982): cannot specify "required" dependency on go binary
-apexer_go_tools = [
- "merge_zips",
- "soong_zip",
-]
-
python_library_host {
name: "apex_manifest",
srcs: [
@@ -61,10 +51,6 @@ python_binary_host {
srcs: [
"apexer.py",
],
- // TODO(b/157625953) mke2fs.conf can't embedded directly.
- data: [
- ":mke2fs_conf",
- ],
version: {
py2: {
enabled: true,
@@ -117,8 +103,7 @@ apex_test {
manifest: "etc/manifest.json",
ignore_system_library_special_case: true,
key: "com.android.support.apexer.key",
- binaries: apexer_tools + apexer_go_tools,
- updatable: false,
+ binaries: apexer_tools,
}
// TODO(b/148659029): this test can't run in TEST_MAPPING.
@@ -133,7 +118,6 @@ python_test_host {
":com.android.example-legacy.apex",
":com.android.example-logging_parent.apex",
":com.android.example-overridden_package_name.apex",
- ":apexer_test_host_tools",
"testdata/com.android.example.apex.avbpubkey",
"testdata/com.android.example.apex.pem",
"testdata/com.android.example.apex.pk8",
@@ -151,59 +135,8 @@ python_test_host {
libs: [
"apex_manifest",
],
-}
-
-apexer_deps_minus_go_tools = apexer_tools + [
- "deapexer",
- "debugfs_static",
-]
-
-apexer_deps_tools = apexer_deps_minus_go_tools + apexer_go_tools
-
-genrule_defaults {
- name: "apexer_test_host_tools_list",
- tools: apexer_deps_tools + [
- "signapk",
- ],
-}
-
-genrule {
- name: "apexer_test_host_tools",
- srcs: [
- ":current_android_jar",
- ],
- out: ["apexer_test_host_tools.zip"],
- tools: apexer_deps_tools + [
- // To force signapk.jar generated in out/soong/host
- "signapk",
+ required: [
+ "apexer",
+ "deapexer"
],
- cmd: "HOST_OUT_BIN=$$(dirname $(location apexer)) && " +
- "HOST_SOONG_OUT=$$(dirname $$HOST_OUT_BIN) && " +
- "SIGNAPK_JAR=$$(find $${HOST_SOONG_OUT}/framework -name \"signapk*\") && " +
- "LIBCPLUSPLUS=$$(find $${HOST_SOONG_OUT}/lib64 -name \"libc++.*\") && " +
- "LIBCONSCRYPT_OPENJDK_JNI=$$(find $${HOST_SOONG_OUT}/lib64 -name \"libconscrypt_openjdk_jni.*\") && " +
- "BASE=$(genDir)/binary_files && " +
- "BIN=$$BASE/bin && " +
- "LIB=$$BASE/lib64 && " +
- "mkdir -p $$BIN && " +
- "mkdir -p $$LIB && " +
- "cp $(in) $$BIN && " +
- "cp $(location apexer) $$BIN && " +
- "cp $(location deapexer) $$BIN && " +
- "cp $(location avbtool) $$BIN && " +
- "cp $(location aapt2) $$BIN && " +
- "cp $(location e2fsdroid) $$BIN && " +
- "cp $(location merge_zips) $$BIN && " +
- "cp $(location mke2fs) $$BIN && " +
- "cp $(location resize2fs) $$BIN && " +
- "cp $(location sefcontext_compile) $$BIN && " +
- "cp $(location soong_zip) $$BIN && " +
- "cp $(location fec) $$BIN && " +
- "cp $(location zipalign) $$BIN && " +
- "cp $(location debugfs_static) $$BIN && " +
- "cp $$SIGNAPK_JAR $$BIN && " +
- "cp $$LIBCPLUSPLUS $$LIB && " +
- "cp $$LIBCONSCRYPT_OPENJDK_JNI $$LIB && " +
- "$(location soong_zip) -C $$BASE -D $$BASE -o $(out) && " +
- "rm -rf $$BASE",
}
diff --git a/apexer/TEST_MAPPING b/apexer/TEST_MAPPING
index 1ad30781..cbb6a858 100644
--- a/apexer/TEST_MAPPING
+++ b/apexer/TEST_MAPPING
@@ -1,9 +1,4 @@
{
- "presubmit": [
- {
- "name": "apexer_test"
- }
- ],
"imports": [
{
"path": "system/apex/tests"
diff --git a/apexer/apexer.py b/apexer/apexer.py
index f0c17f43..f698c8c8 100644
--- a/apexer/apexer.py
+++ b/apexer/apexer.py
@@ -23,7 +23,6 @@ import apex_build_info_pb2
import argparse
import hashlib
import os
-import pkgutil
import re
import shlex
import shutil
@@ -102,13 +101,6 @@ def ParseArgs(argv):
choices=['zip', 'image'],
help='type of APEX payload being built "zip" or "image"')
parser.add_argument(
- '--payload_fs_type',
- metavar='FS_TYPE',
- required=False,
- default='ext4',
- choices=['ext4', 'f2fs'],
- help='type of filesystem being used for payload image "ext4" or "f2fs"')
- parser.add_argument(
'--override_apk_package_name',
required=False,
help='package name of the APK container. Default is the apex name in --manifest.'
@@ -170,7 +162,7 @@ def ParseArgs(argv):
parser.add_argument(
'--unsigned_payload_only',
action='store_true',
- help="""Outputs the unsigned payload image/zip only. Also, setting this flag implies
+ help="""Outputs the unsigned payload image/zip only. Also, setting this flag implies
--payload_only is set too."""
)
parser.add_argument(
@@ -190,7 +182,7 @@ def FindBinaryPath(binary):
':'.join(tool_path_list))
-def RunCommand(cmd, verbose=False, env=None, expected_return_values={0}):
+def RunCommand(cmd, verbose=False, env=None):
env = env or {}
env.update(os.environ.copy())
@@ -202,10 +194,10 @@ def RunCommand(cmd, verbose=False, env=None, expected_return_values={0}):
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
output, _ = p.communicate()
- if verbose or p.returncode not in expected_return_values:
+ if verbose or p.returncode is not 0:
print(output.rstrip())
- assert p.returncode in expected_return_values, 'Failed to execute: ' + ' '.join(cmd)
+ assert p.returncode is 0, 'Failed to execute: ' + ' '.join(cmd)
return (output, p.returncode)
@@ -386,9 +378,6 @@ def GenerateBuildInfo(args):
if args.logging_parent:
build_info.logging_parent = args.logging_parent
- if args.payload_type == 'image':
- build_info.payload_fs_type = args.payload_fs_type
-
return build_info
def AddLoggingParent(android_manifest, logging_parent_value):
@@ -461,8 +450,9 @@ def CreateApex(args, work_dir):
print("Cannot read manifest file: '" + args.manifest + "'")
return False
- # create an empty image that is sufficiently big
- size_in_mb = (GetDirSize(args.input_dir) / (1024 * 1024))
+ # create an empty ext4 image that is sufficiently big
+ # sufficiently big = size + 16MB margin
+ size_in_mb = (GetDirSize(args.input_dir) / (1024 * 1024)) + 16
content_dir = os.path.join(work_dir, 'content')
os.mkdir(content_dir)
@@ -483,112 +473,67 @@ def CreateApex(args, work_dir):
else:
key_name = os.path.basename(os.path.splitext(args.key)[0])
+ if manifest_apex.name != key_name:
+ print("package name '" + manifest_apex.name +
+ "' does not match with key name '" + key_name + "'")
+ return False
img_file = os.path.join(content_dir, 'apex_payload.img')
- 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)
+ # 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')
+ RunCommand(cmd, args.verbose, {'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
- 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
+ # 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'})
if args.unsigned_payload_only:
shutil.copyfile(img_file, args.output)
diff --git a/apexer/apexer_test.py b/apexer/apexer_test.py
index 7fec4ec5..176b994c 100644
--- a/apexer/apexer_test.py
+++ b/apexer/apexer_test.py
@@ -21,7 +21,6 @@ import logging
import os
import re
import shutil
-import stat
import subprocess
import tempfile
import unittest
@@ -162,7 +161,6 @@ DEBUG_TEST = False
class ApexerRebuildTest(unittest.TestCase):
def setUp(self):
self._to_cleanup = []
- self._get_host_tools(os.path.join(get_current_dir(), "apexer_test_host_tools.zip"))
def tearDown(self):
if not DEBUG_TEST:
@@ -175,37 +173,6 @@ class ApexerRebuildTest(unittest.TestCase):
else:
print(self._to_cleanup)
- def _get_host_tools(self, host_tools_file_path):
- dir_name = tempfile.mkdtemp(prefix=self._testMethodName+"_host_tools_")
- self._to_cleanup.append(dir_name)
- if os.path.isfile(host_tools_file_path):
- with ZipFile(host_tools_file_path, 'r') as zip_obj:
- zip_obj.extractall(path=dir_name)
-
- files = {}
- for i in ["apexer", "deapexer", "avbtool", "mke2fs", "sefcontext_compile", "e2fsdroid",
- "resize2fs", "soong_zip", "aapt2", "merge_zips", "zipalign", "debugfs_static",
- "signapk.jar", "android.jar"]:
- file_path = os.path.join(dir_name, "bin", i)
- if os.path.exists(file_path):
- os.chmod(file_path, stat.S_IRUSR | stat.S_IXUSR);
- files[i] = file_path
- else:
- files[i] = i
- self.host_tools = files
- self.host_tools_path = os.path.join(dir_name, "bin")
-
- path = os.path.join(dir_name, "bin")
- if "PATH" in os.environ:
- path += ":" + os.environ["PATH"]
- os.environ["PATH"] = path
-
- ld_library_path = os.path.join(dir_name, "lib64")
- if "LD_LIBRARY_PATH" in os.environ:
- ld_library_path += ":" + os.environ["LD_LIBRARY_PATH"]
- if "ANDROID_HOST_OUT" in os.environ:
- ld_library_path += ":" + os.path.join(os.environ["ANDROID_HOST_OUT"], "lib64")
- os.environ["LD_LIBRARY_PATH"] = ld_library_path
def _get_container_files(self, apex_file_path):
dir_name = tempfile.mkdtemp(prefix=self._testMethodName+"_container_files_")
@@ -249,8 +216,7 @@ class ApexerRebuildTest(unittest.TestCase):
def _extract_payload(self, apex_file_path):
dir_name = tempfile.mkdtemp(prefix=self._testMethodName+"_extracted_payload_")
self._to_cleanup.append(dir_name)
- cmd = ["deapexer", "--debugfs_path", self.host_tools["debugfs_static"],
- "extract", apex_file_path, dir_name]
+ cmd = ["deapexer", "extract", apex_file_path, dir_name]
run_host_command(cmd)
# Remove payload files added by apexer and e2fs tools.
@@ -269,13 +235,9 @@ class ApexerRebuildTest(unittest.TestCase):
if unsigned_payload_only or "--payload_only" in args:
payload_only = True
- os.environ["APEXER_TOOL_PATH"] = (self.host_tools_path +
- ":out/soong/host/linux-x86/bin:prebuilts/sdk/tools/linux/bin")
+ os.environ["APEXER_TOOL_PATH"] = (
+ "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')
- cmd.extend(["--apexer_tool_path", os.environ["APEXER_TOOL_PATH"]])
- cmd.extend(["--android_jar_path", self.host_tools["android.jar"]])
cmd.extend(["--manifest", container_files["apex_manifest.pb"]])
if "apex_manifest.json" in container_files:
cmd.extend(["--manifest_json", container_files["apex_manifest.json"]])
@@ -299,35 +261,14 @@ class ApexerRebuildTest(unittest.TestCase):
run_host_command(cmd)
return fn
- def _get_java_toolchain(self):
- java_toolchain = "java"
- if os.path.isfile("prebuilts/jdk/jdk11/linux-x86/bin/java"):
- java_toolchain = "prebuilts/jdk/jdk11/linux-x86/bin/java"
- elif "ANDROID_JAVA_TOOLCHAIN" in os.environ:
- java_toolchain = os.path.join(os.environ["ANDROID_JAVA_TOOLCHAIN"], "java")
- elif "ANDROID_JAVA_HOME" in os.environ:
- java_toolchain = os.path.join(os.environ["ANDROID_JAVA_HOME"], "bin", "java")
- elif "JAVA_HOME" in os.environ:
- java_toolchain = os.path.join(os.environ["JAVA_HOME"], "bin", "java")
-
- java_dep_lib = os.environ["LD_LIBRARY_PATH"]
- if "ANDROID_HOST_OUT" in os.environ:
- 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/soong/host/linux-x86/lib64")
-
- return [java_toolchain, java_dep_lib]
-
def _sign_apk_container(self, unsigned_apex):
fd, fn = tempfile.mkstemp(prefix=self._testMethodName+"_repacked_", suffix=".apex")
os.close(fd)
self._to_cleanup.append(fn)
- java_toolchain, java_dep_lib = self._get_java_toolchain()
cmd = [
- java_toolchain,
- "-Djava.library.path=" + java_dep_lib,
- "-jar", self.host_tools['signapk.jar'],
+ "prebuilts/jdk/jdk11/linux-x86/bin/java",
+ "-Djava.library.path=out/soong/host/linux-x86/lib64",
+ "-jar", "out/soong/host/linux-x86/framework/signapk.jar",
"-a", "4096",
os.path.join(get_current_dir(), TEST_X509_KEY),
os.path.join(get_current_dir(), TEST_PK8_KEY),
diff --git a/apexer/runtests.sh b/apexer/runtests.sh
index e2eacc90..7a499c75 100755
--- a/apexer/runtests.sh
+++ b/apexer/runtests.sh
@@ -28,12 +28,10 @@ m -j apexer
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
-do
input_dir=$(mktemp -d)
output_dir=$(mktemp -d)
-function cleanup {
+function finish {
sudo umount /dev/loop10
sudo losetup --detach /dev/loop10
@@ -41,7 +39,7 @@ function cleanup {
rm -rf ${output_dir}
}
-trap cleanup ERR
+trap finish EXIT
#############################################
# prepare the inputs
#############################################
@@ -57,7 +55,7 @@ ln -s file1 ${input_dir}/sym1
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/soong/host/linux-x86/bin/conv_apex_manifest proto ${manifest_dir}/apex_manifest.json -o ${manifest_file}
+${ANDROID_HOST_OUT}/bin/conv_apex_manifest proto ${manifest_dir}/apex_manifest.json -o ${manifest_file}
# Create the file_contexts file
file_contexts_file=$(mktemp)
@@ -84,9 +82,7 @@ output_file=${output_dir}/test.apex
${ANDROID_HOST_OUT}/bin/apexer --verbose --manifest ${manifest_file} \
--file_contexts ${file_contexts_file} \
--canned_fs_config ${canned_fs_config_file} \
- --payload_fs_type ${fs_type} \
--key ${ANDROID_BUILD_TOP}/system/apex/apexer/testdata/com.android.example.apex.pem \
- --android_jar_path ${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar \
${input_dir} ${output_file}
#############################################
@@ -135,8 +131,4 @@ sudo diff ${input_dir}/sub/file3 ${output_dir}/mnt/sub/file3
# check the android manifest
aapt dump xmltree ${output_file} AndroidManifest.xml
-echo "Passed for ${fs_type}"
-cleanup
-done
-
-echo "Passed for all fs types"
+echo Passed
diff --git a/apexer/testdata/Android.bp b/apexer/testdata/Android.bp
index 951f849e..5f72dc9b 100644
--- a/apexer/testdata/Android.bp
+++ b/apexer/testdata/Android.bp
@@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
android_app_certificate {
name: "com.android.example.apex.certificate",
// This will use com.android.my.apex.x509.pem (the cert) and
@@ -37,8 +33,6 @@ apex {
key: "com.android.example.apex.key",
certificate: ":com.android.example.apex.certificate",
installable: false,
- updatable:false,
- generate_hashtree: false,
}
apex {
@@ -50,7 +44,6 @@ apex {
certificate: ":com.android.example.apex.certificate",
min_sdk_version: "29",
installable: false,
- generate_hashtree: false,
}
apex {
@@ -62,7 +55,6 @@ apex {
certificate: ":com.android.example.apex.certificate",
installable: false,
logging_parent: "foobar",
- updatable: false,
}
apex {
@@ -74,5 +66,4 @@ apex {
certificate: ":com.android.example.apex.certificate",
installable: false,
package_name: "com.android.overridden.example.apex",
- updatable: false,
}
diff --git a/docs/README.md b/docs/README.md
index 64867a2b..5ba0ab9c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,19 +1,15 @@
# APEX File Format
-Android Pony EXpress (APEX) is a container format introduced in Android Q that
-is used in the install flow for lower-level system modules. This format
-facilitates the updates of system components that don't fit into the standard
-Android application model. Some example components are native services and
-libraries, hardware abstraction layers
+Android Pony EXpress (APEX) is a container format introduced in Android Q
+that is used in the install flow for lower-level system
+modules. This format facilitates the updates of system components that don't fit
+into the standard Android application model. Some example components are native
+services and libraries, hardware abstraction layers
([HALs](/https://source.android.com/devices/architecture/hal-types)), runtime
([ART](/https://source.android.com/devices/tech/dalvik)), and class libraries.
The term "APEX" can also refer to an APEX file.
-This document describes technical details of the APEX file format. If you are
-looking at how to build an APEX package, kindly refer to [this how-to](howto.md)
-document.
-
## Background
Although Android supports updates of modules that fit within the standard app
@@ -33,7 +29,7 @@ has the following drawbacks:
This section describes the high-level design of the APEX file format and the
APEX manager, which is a service that manages APEX files.
-### APEX format {#apex-format}
+### APEX format
This is the format of an APEX file.
@@ -59,8 +55,8 @@ infrastructure such as ADB, PackageManager, and package installer apps (such as
Play Store). For example, the APEX file can use an existing tool such as `aapt`
to inspect basic metadata from the file. The file contains package name and
version information. This information is generally also available in
-`apex_manifest.json`. `AndroidManifest.xml` might contain additional targeting
-information that can be used by the existing app publishing tools.
+`apex_manifest.json`. `AndroidManifest.xml` might contain additional
+targeting information that can be used by the existing app publishing tools.
`apex_manifest.json` is recommended over `AndroidManifest.xml` for new code and
systems that deal with APEX.
@@ -72,16 +68,16 @@ metadata block are created using libavb. The file system payload isn't parsed
inside the `apex_payload.img` file.
`apex_pubkey` is the public key used to sign the file system image. At runtime,
-this key ensures that the downloaded APEX is signed with the same entity that
-signs the same APEX in the built-in partitions.
+this key ensures that the downloaded APEX is signed with the same entity
+that signs the same APEX in the built-in partitions.
### APEX manager
-The APEX manager (or `apexd`) is a native daemon responsible for verifying,
-installing, and uninstalling APEX files. This process is launched and is ready
-early in the boot sequence. APEX files are normally pre-installed on the device
-under `/system/apex`. The APEX manager defaults to using these packages if no
-updates are available.
+The APEX manager (or `apexd`) is a native daemon responsible for
+verifying, installing, and uninstalling APEX files. This process is launched and
+is ready early in the boot sequence. APEX files are normally pre-installed on
+the device under `/system/apex`. The APEX manager defaults to using these
+packages if no updates are available.
The update sequence of an APEX uses the
[PackageManager class](https://developer.android.com/reference/android/content/pm/PackageManager)
@@ -136,17 +132,17 @@ The APEX format supports these file types:
- Data files
- Config files
-The APEX format can only update some of these file types. Whether a file type
-can be updated depends on the platform and how stable the interfaces for the
-files types are defined.
+The APEX format can only update some of these file types. Whether a file
+type can be updated depends on the platform and how stable the interfaces for
+the files types are defined.
### Signing
APEX files are signed in two ways. First, the `apex_payload.img` (specifically,
the vbmeta descriptor appended to `apex_payload.img`) file is signed with a key.
Then, the entire APEX is signed using the
-[APK signature scheme v3](/https://source.android.com/security/apksigning/v3).
-Two different keys are used in this process.
+[APK signature scheme v3](/https://source.android.com/security/apksigning/v3). Two different keys are used
+in this process.
On the device side, a public key corresponding to the private key used to sign
the vbmeta descriptor is installed. The APEX manager uses the public key to
@@ -156,8 +152,9 @@ different keys and is enforced both at build time and runtime.
### APEX in built-in partitions
APEX files can be located in built-in partitions such as `/system`. The
-partition is already over dm-verity, so the APEX files are mounted directly over
-the loop device.
+partition is
+already over dm-verity, so the APEX files are mounted directly over the loop
+device.
If an APEX is present in a built-in partition, the APEX can be updated by
providing an APEX package with the same package name and a higher version code.
@@ -168,18 +165,18 @@ the newer version of the APEX is only activated after reboot.
## Kernel requirements
To support APEX mainline modules on an Android device, the following Linux
-kernel features are required: the loop driver and dm-verity. The loop driver
-mounts the file system image in an APEX module and dm-verity verifies the APEX
-module.
+kernel features are required: the loop driver and dm-verity. The loop
+driver mounts the file system image in an APEX module and dm-verity verifies the
+APEX module.
-The performance of the loop driver and dm-verity is important in achieving good
-system performance when using APEX modules.
+The performance of the loop driver and dm-verity is important in achieving
+good system performance when using APEX modules.
### Supported kernel versions
APEX mainline modules are supported on devices using kernel versions 4.4 or
-higher. New devices launching with Android Q or higher must use kernel version
-4.9 or higher to support APEX modules.
+higher. New devices launching with Android Q or higher
+must use kernel version 4.9 or higher to support APEX modules.
### Required kernel patches
@@ -190,9 +187,10 @@ of the Android common tree.
#### Kernel version 4.4
This version is only supported for devices that are upgraded from Android 9 to
-Android Q and want to support APEX modules. To get the required patches, a
-down-merge from the `android-4.4` branch is strongly recommended. The following
-is a list of the required individual patches for kernel version 4.4.
+Android Q and want to support APEX modules. To get the
+required patches, a down-merge from the `android-4.4` branch is strongly
+recommended. The following is a list of the required individual patches
+for kernel version 4.4.
- UPSTREAM: loop: add ioctl for changing logical block size
([4.4](https://android-review.googlesource.com/c/kernel/common/+/777013){: .external})
@@ -218,9 +216,9 @@ the `android-common` branch.
### Required kernel configuration options
-The following list shows the base configuration requirements for supporting APEX
-modules that were introduced in Android Q. The items with an asterisk (\*) are
-existing requirements from Android 9 and lower.
+The following list shows the base configuration requirements for supporting
+APEX modules that were introduced in Android Q. The
+items with an asterisk (\*) are existing requirements from Android 9 and lower.
```
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
@@ -244,8 +242,8 @@ requirements.
Note: Because the implementation details for APEX are still under development,
the content in this section is subject to change.
-This section describes how to build an APEX using the Android build system. The
-following is an example of `Android.bp` for an APEX named `apex.test`.
+This section describes how to build an APEX using the Android build system.
+The following is an example of `Android.bp` for an APEX named `apex.test`.
```
apex {
@@ -282,12 +280,12 @@ apex {
#### File types and locations in APEX
-File type | Location in APEX
----------------- | ----------------------------------------------------------
-Shared libraries | `/lib` and `/lib64` (`/lib/arm` for translated arm in x86)
-Executables | `/bin`
-Java libraries | `/javalib`
-Prebuilts | `/etc`
+|File type |Location in APEX |
+|-------------------|--------------------------------------------------------------|
+|Shared libraries |`/lib` and `/lib64` (`/lib/arm` for translated arm in x86) |
+|Executables |`/bin` |
+|Java libraries |`/javalib` |
+|Prebuilts |`/etc` |
### Transitive dependencies
@@ -378,7 +376,6 @@ $ avbtool extract_public_key --key foo.pem --output foo.avbpubkey
```
In Android.bp:
-
```
apex_key {
name: "apex.test.key",
@@ -510,21 +507,21 @@ kernel to fully support APEX. For example, the kernel might have been built
without `CONFIG_BLK_DEV_LOOP=Y`, which is crucial for mounting the file system
image inside an APEX.
-Flattened APEX is a specially built APEX that can be activated on devices with a
-legacy kernel. Files in a flattened APEX are directly installed to a directory
+Flattened APEX is a specially built APEX that can be activated on devices with
+a legacy kernel. Files in a flattened APEX are directly installed to a directory
under the built-in partition. For example, `lib/libFoo.so` in a flattend APEX
`my.apex` is installed to `/system/apex/my.apex/lib/libFoo.so`.
Activating a flattened APEX doesn't involve the loop device. The entire
directory `/system/apex/my.apex` is directly bind-mounted to `/apex/name@ver`.
-Flattened APEXs can't be updated by downloading updated versions of the APEXs
-from network because the downloaded APEXs can't be flattened. Flattened APEXs
-can be updated only via a regular OTA.
+Flattened APEXs can't be updated by downloading updated versions
+of the APEXs from network because the downloaded APEXs can't be flattened.
+Flattened APEXs can be updated only via a regular OTA.
Note that flattened APEX is the default configuration for now. This means all
-APEXes are by default flattened unless you explicitly configure your device to
-support updatable APEX (explained above).
+APEXes are by default flattened unless you explicitly configure your device
+to support updatable APEX (explained above).
Also note that, mixing flattened and non-flattened APEXes in a device is NOT
supported. It should be either all non-flattened or all flattened. This is
@@ -533,168 +530,22 @@ like Mainline. APEXes that are not pre-signed (i.e. built from the source)
should also be non-flattened and signed with proper keys in that case. The
device should inherit from `updatable_apex.mk` as explained above.
-## Compressed apexes {#compressed-apex}
-
-APEX compression is a new feature introduced in Android S. Its main purpose is
-to reduce the storage impact of updatable APEX packages: after an update to an
-APEX is installed, its pre-installed version is not used anymore, and space that
-is taken by it effectively becomes a dead weight.
-
-APEX compression minimizes the storage impact by using a highly-compressed
-set of APEX files on read-only partitions (e.g. `/system`). In Android S a
-DEFLATE zip compression is used.
-
-Note: compression doesn't provide any optimization in the following scenarios:
-
-* Bootstrap apexes that are required to be mounted very early in the boot
- sequence. List of bootstrap apexes is configured in `kBootstrapApexes`
- constant in `system/apex/apexd/apexd.cpp`.
-* Non-updatable apexes. Compression is only beneficial in case an updated
- version of an apex is installed on `/data partition`.
- Full list of updatable apexes is available at
- https://source.android.com/devices/architecture/modular-system.
-* Dynamic shared libs apexes. Since `apexd` will always activate both versions
- of such apexes (pre-installed and upgraded), compressing them doesn't provide
- any value.
-
-### Compressed APEX file format
-
-This is the format of a compressed APEX file.
-
-![Compressed APEX file format](compressed-apex-format.png)
-
-**Figure 2.** Compressed APEX file format
-
-At the top level, a compressed APEX file is a zip file containing the original apex in deflated
-form with compression level of 9 and other files stored uncompressed.
-
-The four files in an APEX file are:
-
-* `original_apex`: deflated with compression level of 9
-* `apex_manifest.pb`: stored only
-* `AndroidManifest.xml`: stored only
-* `apex_pubkey`: stored only
-
-
-`original_apex` is the original uncompressed [APEX file](#apex-format).
-
-`apex_manifest.pb` `AndroidManifest.xml` `apex_pubkey` are copies of the
-corresponding files from `original_apex`.
-
-
-### Building compressed apex
-
-Compressed apex can be built using `apex_compression_tool.py` located at
-`system/apex/tools`.
-
-Note: the outer apk container of the produced compressed apex file won't be
-automatically signed. You will need to manually sign it with using the correct
-certificate. See [Signing Builds for Release](
-https://source.android.com/devices/tech/ota/sign_builds#apex-signing-key-replacement).
-
-There are a few different parameters related to APEX compression available in
-the build system.
-
-In `Android.bp` whether an apex is compressible is controlled by `compressible`
-property:
-
-```
-apex {
- name: "apex.test",
- manifest: "apex_manifest.json",
- file_contexts: "file_contexts",
- compressible: true,
-}
-```
-
-Note: this only serves as a hint to build system that this apex can be
-compressed. Such property is required due to the fact that not all apexes are
-compressible as mentioned in the [section above](#compressed-apex).
-
-TODO(b/183208430): add docs on how this works for prebuilts.
-
-A `PRODUCT_COMPRESSED_APEX` product flag is used to control whether a system
-image built from source should contain compressed apexes or not.
-
-For local experimentation you can force a build to compress apexes by setting
-`OVERRIDE_PRODUCT_COMPRESSED_APEX=true`.
-
-Compressed APEX files generated by the build system will have `.capex`
-extension. It makes it easier to distinguish between compressed and uncompressed
-versions of an APEX.
-
-### Supported compression algorithms
-
-Android S only supports deflate zip compression.
-
-### Activating compressed apex during boot
-
-Before activating a compressed APEX, `original_apex` inside it will be
-decompressed into `/data/apex/decompressed` directory. The resulting
-decompressed APEX will be hard linked to the `/data/apex/active` directory.
-
-Note: because of the hard link step above, it's important that files under
-`/data/apex/decompressed` have the same SELinux label as files under
-`/data/apex/active`.
-
-Consider following example as an illustration of the process described above.
-
-Let's assume that `/system/apex/com.android.foo.capex` is a compressed APEX
-being activated, and it's `versionCode` is `37`.
-
-1. First `original_apex` inside `/system/apex/com.android.foo.capex` is
- decompressed into `/data/apex/decompressed/com.android.foo@37.apex`.
-2. After that `restorecon /data/apex/decompressed/com.android.foo@37.apex` is
- performed to make sure that it has a correct SELinux label.
-3. Verification checks are performed on
- `/data/apex/decompressed/com.android.foo@37.apex` to ensure it's validity:
- * `apexd` checks that public key bundled in
- `/data/apex/decompressed/com.android.foo@37.apex` is equal to the one
- bundled in `/system/apex/com.android.foo.capex`
-4. Next `/data/apex/decompressed/com.android.foo@37.apex` is hard linked to
- `/data/apex/active/com.android.foo@37.apex`.
-5. Finally, regular activation logic for uncompressed APEX files is performed
- for `/data/apex/active/com.android.foo@37.apex`.
-
-For more information see implementation of `OnStart` function in
-`system/apex/apexd/apexd.cpp`.
-
-### Interaction with OTA
-
-Compressed APEX files have some implications on the OTA delivery and
-application. Since an OTA might contain a compressed APEX file with higher
-version compared to what is currently active on the device, some free space must
-be reserved before rebooting a device to apply an OTA.
-
-To help OTA system, two new binder APIs are exposed by apexd:
-
-* `calculateSizeForCompressedApex` - calculates size required for decompressing
- APEX files in OTA package. It can be used to check if device has enough space
- before downloading an OTA.
-* `reserveSpaceForCompressedApex` - reserves space on the disk that in the
- future will be used by apexd for decompression of compressed APEX files inside
- the OTA package.
-
-
-In case of A/B OTA, `apexd` will attempt decompression in the background as part
-of the postinstall OTA routine. If decompression fails, `apexd` will fallback to
-decompressing during the boot that applies the OTA.
-
## Alternatives considered when developing APEX
-Here are some options that we considered when designing the APEX file format,
-and why we included or excluded them.
+Here are some options that we considered when designing the APEX file
+format, and why we included or excluded them.
### Regular package management systems
-Linux distributions have package management systems like `dpkg` and `rpm`, which
-are powerful, mature and robust. However, they weren't adopted for APEX because
-they can't protect the packages after installation. Verification is done only
-when packages are being installed. Attackers can break the integrity of the
-installed packages unnoticed. This is a regression for Android where all system
-components were stored in read-only file systems whose integrity is protected by
-dm-verity for every I/O. Any tampering to system components must be prohibited,
-or be detectable so that the device can refuse to boot if compromised.
+Linux distributions have package management systems like `dpkg` and `rpm`,
+which are powerful, mature and robust. However, they weren't
+adopted for APEX because they can't protect the packages after
+installation. Verification is done only when packages are being installed.
+Attackers can break the integrity of the installed packages unnoticed. This is
+a regression for Android where all system components were stored in read-only
+file systems whose integrity is protected by dm-verity for every I/O. Any
+tampering to system components must be prohibited, or be detectable so that
+the device can refuse to boot if compromised.
### dm-crypt for integrity
@@ -722,15 +573,15 @@ partition, they were accessible via paths such as `/system/lib/libfoo.so`. A
client of an APEX file (other APEX files or the platform) should use the new
paths. This change in paths might require updates to the existing code.
-One way to avoid the path change is to overlay the file contents in an APEX file
-over the `/system` partition. However, we decided not to overlay files over the
-`/system` partition because we believed this would negatively affect performance
-as the number of files being overlayed (possibly even stacked one after another)
-increases.
+One way to avoid the path change is to overlay the file contents in an APEX
+file over the `/system` partition. However, we decided not to overlay files over
+the `/system` partition because we believed this would negatively affect
+performance as the number of files being overlayed (possibly even stacked one
+after another) increases.
Another option was to hijack file access functions such as `open`, `stat`, and
`readlink`, so that paths that start with `/system` are redirected to their
corresponding paths under `/apex`. We discarded this option because it's
-practically infeasible to change all functions that accept paths. For example,
-some apps statically link Bionic, which implements the functions. In that case,
-the redirection won't happen for the app.
+practically infeasible to change all functions that accept paths. For
+example, some apps statically link Bionic, which implements the functions. In
+that case, the redirection won't happen for the app.
diff --git a/docs/compressed-apex-format.png b/docs/compressed-apex-format.png
deleted file mode 100644
index d67efcbc..00000000
--- a/docs/compressed-apex-format.png
+++ /dev/null
Binary files differ
diff --git a/docs/howto.md b/docs/howto.md
deleted file mode 100644
index a7042493..00000000
--- a/docs/howto.md
+++ /dev/null
@@ -1,556 +0,0 @@
-# How To APEX
-
-[go/android-apex-howto](http://go/android-apex-howto) (internal link)
-
-This doc reflects the current implementation status, and thus is expected to
-change regularly.
-
-## Reference
-
-To understand the design rationale, visit this
-[public doc](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/docs/README.md#alternatives-considered-when-developing-apex)
-and [go/android-apex](http://go/android-apex) (internal).
-
-## Building an APEX
-
-A cheat sheet:
-
-```
-apex {
- name: "com.android.my.apex",
-
- manifest: "apex_manifest.json",
-
- // optional. if unspecified, a default one is auto-generated
- androidManifest: "AndroidManifest.xml",
-
- // libc.so and libcutils.so are included in the apex
- native_shared_libs: ["libc", "libcutils"],
- binaries: ["vold"],
- java_libs: ["core-all"],
- apps: ["myapk"],
- prebuilts: ["my_prebuilt"],
-
- compile_multilib: "both",
-
- key: "com.android.my.apex.key",
- certificate: ":com.android.my.apex.certificate",
-}
-```
-
-`apex_manifest.json` should look like:
-
-```
-{
- "name": "com.android.my.apex",
- "version": 1
-}
-```
-
-The file contexts files should be created at
-`/system/sepolicy/apex/com.android.my.apex-file_contexts`:
-
-```
-(/.*)? u:object_r:system_file:s0
-/sub(/.*)? u:object_r:sub_file:s0
-/sub/file3 u:object_r:file3_file:s0
-```
-
-The file should describe the contents of your apex. Note that the file is
-amended by the build system so that the `apexd` can access the root directory of
-your apex and the `apex_manifest.pb` file. (Technically, they are labeled as
-`system_file`.) So if you're
-[building the apex without Soong](#building-apex-without-soong), please be sure
-that `apexd` can access the root directory and the `apex_manifest.pb` file. (In
-the example above, the first line does that.)
-
-#### A script to create a skeleton of APEX
-
-For convenience, you might want to use a
-[script](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tools/create_apex_skeleton.sh)
-that creates a skeleton (`Android.bp`, keys, etc.) of an APEX for you. You only
-need to adjust the `APEX_NAME` variable to be your actual APEX name.
-
-#### File types and places where they are installed in apex
-
-file type | place in apex
--------------- | ----------------------------------------------------------
-shared libs | `/lib` and `/lib64` (`/lib/arm` for translated arm in x86)
-executables | `/bin`
-java libraries | `/javalib`
-android apps | `/app` or `/priv-app`
-prebuilts | `/etc`
-
-### Transitive dependencies
-
-Transitive dependencies of a native shared lib or an executable are
-automatically included in the APEX. For example, if `libFoo` depends on
-`libBar`, then the two libs are included even when only `libFoo` is listed in
-`native_shared_libs` property.
-
-However, if a transitive dependency has a stable ABI, it is not included
-transitively. It can be included in an APEX only by directly being referenced.
-Currently (2019/08/05), the only module type that can provide stable ABI is
-`cc_library`. To do so, add `stubs.*` property as shown below:
-
-```
-cc_library {
- name: "foo",
- srcs: [...],
- stubs: {
- symbol_file: "foo.map.txt",
- versions: ["29", "30"],
- },
-}
-```
-
-Use this when a lib has to be accessed across the APEX boundary, e.g. between
-APEXes or between an APEX and the platform.
-
-### apex_available
-
-Any module that is “included” (not just referenced) in an APEX either via the
-direct dependency or the transitive dependency has to correctly set the
-`apex_available` property in its `Android.bp` file. The property can have one or
-more of the following values:
-
-* `<name_of_an_apex>`: Like `com.android.adbd`. By specifying the APEX names
- explicitly, the module is guaranteed to be included in those APEXes. This is
- useful when a module has to be kept as an implementation detail of an APEX
- and therefore shouldn’t be used from outside.
-* `//apex_available:anyapex`: This means that the module can be included in
- any APEX. This is useful for general-purpose utility libraries like
- `libbase`, `libcutils`, etc.
-* `//apex_available:platform`: The module can be installed to the platform,
- outside of APEXes. This is the default value. However, `if apex_available`
- is set to either of `<name_of_an_apex` or `//apex_available:anyapex`, the
- default is removed. If a module has to be included in both APEX and the
- platform, `//apex_available:platform` and`//apex_available:anyapex` should
- be specified together.
-
-The act of adding an APEX name to the `apex_available` property of a module has
-to be done or be reviewed by the author(s) of the module. Being included in an
-APEX means that the module will be portable, i.e., running on multiple versions
-of the current and previous platforms, whereas it usually was expected to run on
-the current (the up-to-date) platform. Therefore, the module might have to be
-prepared to not have version-specific dependencies to the platform, like the
-existence of a dev node, a system call, etc.
-
-### Handling multiple ABIs
-
-`compile_multilib`: specifies the ABI(s) that this APEX will compile native
-modules for. Can be either of `both`, `first`, `32`, `64`, `prefer32`. For most
-of the cases, this should be `both`.
-
-`native_shared_libs`: installed for **_both_** primary and secondary ABIs of the
-device. Of course, if the APEX is built for a target having single ABI (i.e.
-32-bit only or 64-bit only), only libraries with the corresponding ABI are
-installed.
-
-`binaries`: installed only for the **_primary_** ABI of the device. In other
-words,
-
-* If the device is 32-bit only, only the 32-bit variant of the binary is
- installed.
-* If the device supports both 32/64 ABIs, but with
- `TARGET_PREFER_32_BIT_EXECUTABLES=true`, then only the 32-bit variant of the
- binary is installed.
-* If the device is 64-bit only, then only the 64-bit variant of the binary is
- installed.
-* If the device supports both 32/64 ABIs, but without
- `TARGET_PREFER_32_BIT_EXECUTABLES=true`, then only the 64-bit variant of the
- binary is installed.
-
-In order to fine control the ABIs of the native libraries and binaries to be
-installed, use
-`multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]`
-properties.
-
-* `first`: matches with the primary ABI of the device. This is the default for
- `binaries`.
-* `lib32`: matches with the 32-bit ABI of the device, if supported
-* `lib64`: matches with the 64-bit ABI of the device, it supported
-* `prefer32`: matches with the 32-bit ABI of the device, if support. If 32-bit
- ABI is not supported, it is matched with the 64-bit ABI.
-* `both`: matches with the both ABIs. This is the default for
- `native_shared_libraries`.
-* `java libraries` and `prebuilts`: ABI-agnostic
-
-Example: (let’s assume that the device supports 32/64 and does not prefer32)
-
-```
-apex {
- // other properties are omitted
- compile_multilib: "both",
- native_shared_libs: ["libFoo"], // installed for 32 and 64
- binaries: ["exec1"], // installed for 64, but not for 32
- multilib: {
- first: {
- native_shared_libs: ["libBar"], // installed for 64, but not for 32
- binaries: ["exec2"], // same as binaries without multilib.first
- },
- both: {
- native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
- binaries: ["exec3"], // installed for 32 and 64
- },
- prefer32: {
- native_shared_libs: ["libX"], // installed for 32, but not for 64
- },
- lib64: {
- native_shared_libs: ["libY"], // installed for 64, but not for 32
- },
- },
-}
-```
-
-### APEX image signing
-
-**Note**: the APEX skeleton creation
-[script](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tools/create_apex_skeleton.sh)
-automates this step.
-
-Each APEX must be signed with different keys. There is no concept of the
-platform key. `apexd` in the future might reject if multiple APEXes are signed
-with the same key. When a new key is needed, create a public-private key pair
-and make an `apex_key` module. Use `key` property to sign an APEX using the key.
-The public key is included in the zip container of the APEX as a file entry
-`apex_pubkey`.
-
-How to generate the key pair:
-
-```
-# create an rsa key pair
-$ openssl genrsa -out com.android.my.apex.pem 4096
-
-# extract the public key from the key pair
-$ avbtool extract_public_key --key com.android.my.apex.pem \
---output com.android.my.apex.avbpubkey
-
-# in Android.bp
-apex_key {
- name: "com.android.my.apex.key",
- public_key: "com.android.my.apex.avbpubkey",
- private_key: "com.android.my.apex.pem",
-}
-```
-
-Important: In the above example, the name of the public key (that is
-`com.android.my.apex`) becomes the ID of the key. The ID of the key used to sign
-an APEX is recorded in the APEX. At runtime, a public key with the same ID in
-the device is used to verify the APEX.
-
-### APK (APEX container) signing
-
-**Note**: the APEX skeleton creation
-[script](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tools/create_apex_skeleton.sh)
-automates this step.
-
-An APEX should also be signed just like APKs. So, an APEX is signed twice; once
-for the mini file system (`apex_payload.img` file) and once for the entire file.
-
-Just like APK, the file-level signing is done via the `certificate` property. It
-can be set in three ways.
-
-* not set: if unset, the APEX is signed with the certificate located at
- `PRODUCT_DEFAULT_DEV_CERTIFICATE`. If the flag is also unset, it defaults to
- `build/target/product/security/testkey`
-* `<name>`: the APEX is signed with the certificate named `<name>` in the same
- directory as `PRODUCT_DEFAULT_DEV_CERTIFICATE`
-* `<name>`: the APEX signed with the certificate which is defined by a
- Soong module named `<name>`. The certificate module can be defined as
- follows.
-
-```
-android_app_certificate {
- name: "com.android.my.apex.certificate",
- // This will use com.android.my.apex.x509.pem (the cert) and
- // com.android.my.apex.pk8 (the private key)
- certificate: "com.android.my.apex",
-}
-```
-
-How to generate the certificate/private key pair:
-
-```
-# Create certificate and private in PEM form
-$ openssl req -x509 -newkey rsa:4096 -nodes -days 999999 -keyout key.pem -out com.android.my.apex.x509.pem
-
-# Enter following info via the interactive prompts
-# Country Name: US
-# State: California
-# Locality Name: Mountain View
-# Organization Name: Android
-# Organization Unit Name: Android
-# Common Name: <your-apk-name>
-# Email address: android@android.com
-
-# Convert the private to pkcs8 format
-$ openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out com.android.my.apex.pk8 -nocrypt
-```
-
-### Signing APEXs with release keys
-
-The procedures described in the [APEX image signing](#apex-image-signing) and
-[APK (APEX container) signing](#apk-apex-container_signing) sections require the
-private keys to be present in the tree. This is not suitable for public release.
-Please refer to the
-[APEX signing key replacement](https://source.android.com/devices/tech/ota/sign_builds#apex-signing-key-replacement)
-documentation to prepare the APEX packages for release.
-
-For the Google-specific procedure for release keys, the documentation is
-available at
-[go/android-apex-howto-internal](http://go/android-apex-howto-internal)
-(internal only).
-
-### Linker namespaces for native libraries and binaries
-
-The linker needs to be set up with separate namespaces for each APEX, for
-isolation. It is done through `ld.config.txt` files, which are autogenerated by
-`linkerconfig`. Normally you only need to ensure that the APEX manifest
-correctly lists the native libraries it requires (from platform or other APEXes)
-and provides, which by default is taken from the build system.
-
-Refer to the [design doc](go/linker-config-apex) for more information about
-linkerconfig and apex.
-
-## Installing an APEX
-
-Use
-
-```
-adb install --staged <path_to_apex> && adb reboot
-```
-
-The `adb install --staged` command triggers a verification for the staged APEX
-which might fail when the APEX is signed incorrectly.
-
-Note that on Q devices when the `adb install --staged` command completes you
-still will have to wait until the verification for the staged APEX is finished
-before issuing `adb reboot`.
-
-On R devices we added the `--wait` option to `adb install` to wait until the
-verification is completed before returning. On S devices the `--wait` option is
-implicit.
-
-## Hot swapping an APEX (development only)
-
-Use
-
-```
-adb sync && adb shell cmd -w apexservice remountPackages
-```
-
-Note that for this command to remount your APEX, you must ensure that all
-processes that have reference to your APEX are killed. E.g. if you are
-developing an APEX that contributes to system\_server, you can use the
-following:
-
-```
-adb root
-adb remount
-adb shell stop
-adb sync
-adb shell cmd -w apexservice remountPackages
-adb shell start
-```
-
-## Using an APEX
-
-After the reboot, the apex will be mounted at `/apex/<apex_name>@<version>`
-directory. Multiple versions of the same APEX can be mounted at the same time. A
-mount point that always points to the latest version of an APEX is provided:
-`/apex/<apex_name>`.
-
-Clients can use the latter path to read or execute something from APEX.
-
-So, typical usage of APEX is as follows.
-
-1. an APEX is pre-loaded under `/system/apex`when the device is shipped.
-2. Files in it are accessed via the `/apex/<apex_name>/`path.
-3. When an updated version of the APEX is installed in `/data/apex/active`, the
- path will point to the new APEX after the reboot.
-
-## Updating service with APEX
-
-Using APEX, you can update a service. To do so, you need …
-
-1) Mark the service in system partition as updatable. Add the new option
-‘updatable’ to the service definition.
-
-```
-/system/etc/init/myservice.rc:
-
-service myservice /system/bin/myservice
- class core
- user system
- …
- updatable
-```
-
-2) Create a new `.rc` file for the updated service. Use ‘`override`’ option to
-redefine the existing service.
-
-```
-/apex/my.apex/etc/init.rc:
-
-service myservice /apex/my.apex/bin/myservice
- class core
- user system
- …
- override
-```
-
-Note that you can only have service definitions in the rc file in APEX. You
-cannot have action triggers in APEXes.
-
-Also note that if a service marked as updatable is started before APEXes are
-activated, the start is delayed until the activation of APEXes is finished.
-
-## Configuring system to support APEX updates
-
-Set the following system property to true to support APEX file updates.
-
-```
-<device.mk>:
-
-PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
-
-BoardConfig.mk:
-TARGET_FLATTEN_APEX := false
-
-or just
-<device.mk>:
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
-```
-
-## Flattened APEX
-
-For legacy devices, it is sometimes impossible or infeasible to update the old
-kernel to fully support APEX. For example, the kernel might have been built
-without `CONFIG_BLK_DEV_LOOP=Y`, which is crucial for mounting the file system
-image inside an APEX.
-
-Flattened APEX is a specially built APEX that can be activated on devices with a
-legacy kernel. Files in a flattened APEX are directly installed to a directory
-under the built-in partition. For example, `lib/libFoo.so` in a flattened APEX
-my.apex is installed to `/system/apex/my.apex/lib/libFoo.so`.
-
-Activating a flattened APEX doesn't involve the loop device. The entire
-directory `/system/apex/my.apex` is directly bind-mounted to `/apex/name@ver`.
-
-Flattened APEXs can‘t be updated by downloading updated versions of the APEXs
-from network because the downloaded APEXs can’t be flattened. Flattened APEXs
-can be updated only via a regular OTA.
-
-Note that flattened APEX is the default configuration for now (2019/Aug). This
-means all APEXes are by default flattened unless you explicitly configure your
-device to support updatable APEX (explained above).
-
-Also note that, mixing flattened and non-flattened APEXes in a device is NOT
-supported. It should be either all non-flattened or all flattened. This is
-especially important when shipping pre-signed APEX prebuilts for the projects
-like Mainline. APEXes that are not pre-signed (i.e. built from the source)
-should also be non-flattened and signed with proper keys in that case. The
-device should inherit from `updatable_apex.mk` as explained above.
-
-## Building APEX without Soong
-
-An APEX can be built without relying on the build commands generated by Soong.
-
-1) Prepare following files:
-
-- APEX manifest file (in JSON)
-
-- AndroidManifest file (in XML, optional)
-
-- AVB private key
-
-- APK certificate (`*.x509.pem`)
-
-- APK private key (`*.pk8`)
-
-- `file_contexts` file
-
-- files to be packaged into the APEX
-
-2) Create `canned_fs_config` file
-
-It is a file that specifies access bits and uid/gid of each file in the APEX.
-
-```
-/ 1000 1000 0755
-/apex_manifest.json 1000 1000 0644
-/apex_manifest.pb 1000 1000 0644
-/file1 1000 1000 0644
-/file2 1000 1000 0644
-/dir 0 2000 0755
-/dir/file3 1000 1000 0644
-...
-```
-
-Note that ALL files AND directories must be specified. And don’t forget to have
-a line for `/`and `/apex_manifest.pb`. (`/apex_manifest.json` line is for
-Q-targeting modules)
-
-3) Invoke `apexer`
-
-```
-$ apexer \
- --manifest <apex_manifest_file> \
- --file_contexts <file_contexts_file> \
- --canned_fs_config <canned_fs_config_file> \
- --key <avb_private_key_file> \
- --payload_type image \
- --android_manifest <android_manifest_file> \
- --override_apk_package_name com.google.foo \
- <input_directory> \
- <output_apex_file>
-```
-
-`--android_manifest` and -`-override_apk_package` are optional arguments and
-thus can be omitted if not needed.
-
-Note: The `<apex_manifest_file>` shouldn’t be under `<input_directory>`.
-
-4) Sign it
-
-`apexer` signs the `apex_payload.img` file only. The entire apex (which is a zip
-file) has to be signed with `Signapk`.
-
-```
-$ java \
- -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> \
- <unsigned_input_file> \
- <signed_output_file>
-```
-
-This will sign the input file with the cert/privkey pairs to produce the output
-file.
-
-## Re-packaging an existing APEX
-
-If an APEX has been build by passing `--include_build_info` to `apexer` (this is
-the default when building via Soong), it will then include a file named
-`apex_build_info.pb` which will store as much information as possible about how
-the apex was built (see the `ApexBuildInfo` proto
-[definition](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/proto/apex_build_info.proto)
-for more info) with the exception of the signing keys.
-
-We also provide a tool named `deapexer` to extract the payload content of an
-APEX in a local directory.
-
-By using these tools, you can then adapt the procedure described in the
-[building the apex without Soong](#building-apex-without-soong) section and pass
-the `--build_info apex_build_info.pb` file where `apex_build_info.pb` contains
-all the build parameters that you would otherwise pass via flag to `apexer`.
-
-We do this programmatically in some unit test code to generate "unusual" APEX
-files, see for example
-[here](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/apexer/apexer_test.py)
-and
-[here](https://android.googlesource.com/platform/system/apex/+/refs/heads/master/tests/testdata/sharedlibs/build/shared_libs_repack.py).
diff --git a/library_linking_strategy.cc b/library_linking_strategy.cc
deleted file mode 100644
index a56d92e2..00000000
--- a/library_linking_strategy.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-int main() { return 0; }
diff --git a/libs/libapexutil/Android.bp b/libs/libapexutil/Android.bp
index 5ba3181d..edf66f2f 100644
--- a/libs/libapexutil/Android.bp
+++ b/libs/libapexutil/Android.bp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_defaults {
name: "libapexutil-deps",
static_libs: [
@@ -34,10 +30,6 @@ cc_library_static {
export_include_dirs: ["."],
srcs: ["apexutil.cpp"],
host_supported: true,
- apex_available: [
- "//apex_available:platform",
- "com.android.runtime",
- ],
}
cc_test {
@@ -53,4 +45,4 @@ cc_test {
"general-tests",
],
host_supported: true,
-}
+} \ No newline at end of file
diff --git a/libs/libapexutil/apexutil.cpp b/libs/libapexutil/apexutil.cpp
index 6203a3b4..e0b0787b 100644
--- a/libs/libapexutil/apexutil.cpp
+++ b/libs/libapexutil/apexutil.cpp
@@ -18,7 +18,6 @@
#include "apexutil.h"
#include <dirent.h>
-#include <string.h>
#include <memory>
@@ -68,8 +67,6 @@ GetActivePackages(const std::string &apex_root) {
continue;
if (strchr(entry->d_name, '@') != nullptr)
continue;
- if (strcmp(entry->d_name, "sharedlibs") == 0)
- continue;
std::string apex_path = apex_root + "/" + entry->d_name;
auto manifest = ParseApexManifest(apex_path + "/apex_manifest.pb");
if (manifest.ok()) {
diff --git a/proto/Android.bp b/proto/Android.bp
index 30b24e33..be9966a4 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
cc_library_static {
name: "lib_apex_manifest_proto",
host_supported: true,
@@ -37,10 +33,6 @@ cc_library_static {
type: "lite",
},
srcs: ["apex_manifest.proto"],
- apex_available: [
- "//apex_available:platform",
- "com.android.runtime",
- ],
}
python_library_host {
@@ -98,19 +90,3 @@ cc_library_static {
},
srcs: ["session_state.proto"],
}
-
-genrule {
- name: "apex-protos",
- tools: ["soong_zip"],
- dist: {
- targets: ["apexer_tools"],
- },
- srcs: [
- "apex_manifest.proto",
- "apex_build_info.proto",
- ],
- out: ["apex-protos.zip"],
- cmd: "mkdir $(genDir)/protos && " +
- "cp $(in) $(genDir)/protos && " +
- "$(location soong_zip) -o $(out) -C $(genDir)/protos -D $(genDir)/protos",
-}
diff --git a/proto/apex_build_info.proto b/proto/apex_build_info.proto
index fd8a3499..e25baa20 100644
--- a/proto/apex_build_info.proto
+++ b/proto/apex_build_info.proto
@@ -48,7 +48,4 @@ message ApexBuildInfo {
// Value of --logging_parent passed at build time.
string logging_parent = 9;
-
- // Value of --payload_fs_type passed at build time.
- string payload_fs_type = 10;
}
diff --git a/proto/apex_manifest.proto b/proto/apex_manifest.proto
index 22fb7d79..dfbf4d23 100644
--- a/proto/apex_manifest.proto
+++ b/proto/apex_manifest.proto
@@ -48,35 +48,4 @@ message ApexManifest {
// List of native libs which this apex uses from other apexes or system.
repeated string requireNativeLibs = 8;
-
- // List of JNI libs.
- // linkerconfig/libnativeloader use this field so that java libraries can
- // load JNI libraries in the same apex.
- // This is supposed to be filled by the build system with libraries which are
- // 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.
- // 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
- // causes libraries contained in the APEX to be made available under
- // /apex/sharedlibs .
- bool provideSharedApexLibs = 11;
-
- message CompressedApexMetadata {
-
- // Valid only for compressed APEX. This field contains the root digest of
- // the original_apex contained inside CAPEX.
- string originalApexDigest = 1;
- }
-
- // Exists only for compressed APEX
- CompressedApexMetadata capexMetadata = 12;
-
- // Indicates that this APEX can be updated without rebooting device.
- bool supportsRebootlessUpdate = 13;
}
-
diff --git a/proto/session_state.proto b/proto/session_state.proto
index cebf0adb..35319cf7 100644
--- a/proto/session_state.proto
+++ b/proto/session_state.proto
@@ -58,7 +58,4 @@ message SessionState {
// The names of the apexes within this session. Only populated for sessions
// that have been activated.
repeated string apex_names = 9;
-
- // Populated with error details when session fails to activate
- string error_message = 10;
}
diff --git a/pylintrc b/pylintrc
deleted file mode 100644
index 88750048..00000000
--- a/pylintrc
+++ /dev/null
@@ -1,447 +0,0 @@
-# This Pylint rcfile contains a best-effort configuration to uphold the
-# best-practices and style described in the Google Python style guide:
-# https://google.github.io/styleguide/pyguide.html
-#
-# Its canonical open-source location is:
-# https://google.github.io/styleguide/pylintrc
-
-[MASTER]
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=third_party
-
-# Add files or directories matching the regex patterns to the blacklist. The
-# regex matches against base names, not paths.
-ignore-patterns=
-
-# Pickle collected data for later comparisons.
-persistent=no
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-# Use multiple processes to speed up Pylint.
-jobs=4
-
-# Allow loading of arbitrary C extensions. Extensions are imported into the
-# active Python interpreter and may run arbitrary code.
-unsafe-load-any-extension=no
-
-# A comma-separated list of package or module names from where C extensions may
-# be loaded. Extensions are loading into the active Python interpreter and may
-# run arbitrary code
-extension-pkg-whitelist=
-
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once). See also the "--disable" option for examples.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-disable=abstract-method,
- apply-builtin,
- arguments-differ,
- attribute-defined-outside-init,
- backtick,
- bad-option-value,
- basestring-builtin,
- buffer-builtin,
- c-extension-no-member,
- consider-using-enumerate,
- cmp-builtin,
- cmp-method,
- coerce-builtin,
- coerce-method,
- delslice-method,
- div-method,
- duplicate-code,
- eq-without-hash,
- execfile-builtin,
- file-builtin,
- filter-builtin-not-iterating,
- fixme,
- getslice-method,
- global-statement,
- hex-method,
- idiv-method,
- implicit-str-concat-in-sequence,
- import-error,
- import-self,
- import-star-module-level,
- inconsistent-return-statements,
- input-builtin,
- intern-builtin,
- invalid-str-codec,
- locally-disabled,
- long-builtin,
- long-suffix,
- map-builtin-not-iterating,
- misplaced-comparison-constant,
- missing-function-docstring,
- metaclass-assignment,
- next-method-called,
- next-method-defined,
- no-absolute-import,
- no-else-break,
- no-else-continue,
- no-else-raise,
- no-else-return,
- no-init, # added
- no-member,
- no-name-in-module,
- no-self-use,
- nonzero-method,
- oct-method,
- old-division,
- old-ne-operator,
- old-octal-literal,
- old-raise-syntax,
- parameter-unpacking,
- print-statement,
- raising-string,
- range-builtin-not-iterating,
- raw_input-builtin,
- rdiv-method,
- reduce-builtin,
- relative-import,
- reload-builtin,
- round-builtin,
- setslice-method,
- signature-differs,
- standarderror-builtin,
- suppressed-message,
- sys-max-int,
- too-few-public-methods,
- too-many-ancestors,
- too-many-arguments,
- too-many-boolean-expressions,
- too-many-branches,
- too-many-instance-attributes,
- too-many-locals,
- too-many-nested-blocks,
- too-many-public-methods,
- too-many-return-statements,
- too-many-statements,
- trailing-newlines,
- unichr-builtin,
- unicode-builtin,
- unnecessary-pass,
- unpacking-in-except,
- useless-else-on-loop,
- useless-object-inheritance,
- useless-suppression,
- using-cmp-argument,
- wrong-import-order,
- xrange-builtin,
- zip-builtin-not-iterating,
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]". This option is deprecated
-# and it will be removed in Pylint 2.0.
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=no
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
-
-
-[BASIC]
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=main,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=
-
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
-
-# List of decorators that produce properties, such as abc.abstractproperty. Add
-# to this list to register other decorators that produce valid properties.
-property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl
-
-# Regular expression matching correct function names
-function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
-
-# Regular expression matching correct variable names
-variable-rgx=^[a-z][a-z0-9_]*$
-
-# Regular expression matching correct constant names
-const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
-
-# Regular expression matching correct attribute names
-attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
-
-# Regular expression matching correct argument names
-argument-rgx=^[a-z][a-z0-9_]*$
-
-# Regular expression matching correct class attribute names
-class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
-
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=^[a-z][a-z0-9_]*$
-
-# Regular expression matching correct class names
-class-rgx=^_?[A-Z][a-zA-Z0-9]*$
-
-# Regular expression matching correct module names
-module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$
-
-# Regular expression matching correct method names
-method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=10
-
-
-[TYPECHECK]
-
-# List of decorators that produce context managers, such as
-# contextlib.contextmanager. Add to this list to register other decorators that
-# produce valid context managers.
-contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of module names for which member attributes should not be checked
-# (useful for modules/projects where namespaces are manipulated during runtime
-# and thus existing member attributes cannot be deduced by static analysis. It
-# supports qualified module names, as well as Unix pattern matching.
-ignored-modules=
-
-# List of class names for which member attributes should not be checked (useful
-# for classes with dynamically set attributes). This supports the use of
-# qualified names.
-ignored-classes=optparse.Values,thread._local,_thread._local
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E1101 when accessed. Python regular
-# expressions are accepted.
-generated-members=
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=80
-
-# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
-# lines made too long by directives to pytype.
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=(?x)(
- ^\s*(\#\ )?<?https?://\S+>?$|
- ^\s*(from\s+\S+\s+)?import\s+.+$)
-
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=yes
-
-# List of optional constructs for which whitespace checking is disabled. `dict-
-# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
-# `trailing-comma` allows a space between comma and closing bracket: (a, ).
-# `empty-line` allows space-only lines.
-no-space-check=
-
-# Maximum number of lines in a module
-max-module-lines=99999
-
-# String used as indentation unit. The internal Google style guide mandates 2
-# spaces. Google's externaly-published style guide says 4, consistent with
-# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google
-# projects (like TensorFlow).
-indent-string=' '
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
-
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=TODO
-
-
-[STRING]
-
-# This flag controls whether inconsistent-quotes generates a warning when the
-# character used as a quote delimiter is used inconsistently within a module.
-check-quote-consistency=yes
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=cb_,_cb
-
-# List of qualified module names which can have objects that can redefine
-# builtins.
-redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
-
-
-[LOGGING]
-
-# Logging modules to check that the string format arguments are in logging
-# function parameter format
-logging-modules=logging,absl.logging,tensorflow.io.logging
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[SPELLING]
-
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
-
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
-spelling-store-unknown-words=no
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,
- TERMIOS,
- Bastion,
- rexec,
- sets
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-# Force import order to recognize a module as part of the standard
-# compatibility libraries.
-known-standard-library=
-
-# Force import order to recognize a module as part of a third party library.
-known-third-party=enchant, absl
-
-# Analyse import fallback blocks. This can be used to support both Python 2 and
-# 3 compatible code, which means that the block might have code that exists
-# only in one or another interpreter, leading to false positives when analysed.
-analyse-fallback-blocks=no
-
-
-[CLASSES]
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,
- __new__,
- setUp
-
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,
- _fields,
- _replace,
- _source,
- _make
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls,
- class_
-
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=StandardError,
- Exception,
- BaseException
diff --git a/shim/Android.bp b/shim/Android.bp
index b9952664..351e754f 100644
--- a/shim/Android.bp
+++ b/shim/Android.bp
@@ -15,10 +15,6 @@
// TODO: consider removing _prebuilt suffix from module names and make use of
// 'prefer: true'
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
prebuilt_apex {
name: "com.android.apex.cts.shim.v1_prebuilt",
overrides: ["CtsShimPrebuilt", "CtsShimPrivPrebuilt"],
@@ -180,43 +176,3 @@ prebuilt_apex {
filename: "com.android.apex.cts.shim.v3.apex",
installable: false,
}
-
-prebuilt_apex {
- name: "com.android.apex.cts.shim.v2_different_certificate_prebuilt",
- arch: {
- arm: {
- src: "prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex",
- },
- arm64: {
- src: "prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex",
- },
- x86: {
- src: "prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex",
- },
- x86_64: {
- src: "prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex",
- },
- },
- filename: "com.android.apex.cts.shim.v2_different_certificate.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.cts.shim.v2_unsigned_apk_container_prebuilt",
- arch: {
- arm: {
- src: "prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
- },
- arm64: {
- src: "prebuilts/arm/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
- },
- x86: {
- src: "prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
- },
- x86_64: {
- src: "prebuilts/x86/com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
- },
- },
- filename: "com.android.apex.cts.shim.v2_unsigned_apk_container.apex",
- installable: false,
-}
diff --git a/shim/build/Android.bp b/shim/build/Android.bp
index 2fa99bf5..2667984b 100644
--- a/shim/build/Android.bp
+++ b/shim/build/Android.bp
@@ -14,10 +14,6 @@
// Build rules to build shim apexes.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
genrule {
name: "com.android.apex.cts.shim.pem",
out: ["com.android.apex.cts.shim.pem"],
@@ -40,27 +36,6 @@ apex_key {
}
genrule {
- name: "com.android.apex.cts.shim.debug.pem",
- out: ["com.android.apex.cts.shim.debug.pem"],
- cmd: "openssl genrsa -out $(out) 4096",
-}
-
-genrule {
- name: "com.android.apex.cts.shim.debug.pubkey",
- srcs: [":com.android.apex.cts.shim.debug.pem"],
- out: ["com.android.apex.cts.shim.debug.pubkey"],
- tools: ["avbtool"],
- cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
-}
-
-apex_key {
- name: "com.android.apex.cts.shim.debug.key",
- private_key: ":com.android.apex.cts.shim.debug.pem",
- public_key: ":com.android.apex.cts.shim.debug.pubkey",
- installable: false,
-}
-
-genrule {
name: "generate_hash_of_dev_null",
out: ["hash.txt"],
cmd: "sha512sum -b /dev/null | cut -d' ' -f1 | tee $(out)",
@@ -83,7 +58,6 @@ apex {
apps: ["CtsShim", "CtsShimPriv"],
installable: false,
allowed_files: "default_shim_allowed_list.txt",
- updatable: false,
}
apex {
@@ -96,20 +70,6 @@ apex {
apps: ["CtsShim", "CtsShimPriv"],
installable: false,
allowed_files: "default_shim_allowed_list.txt",
- updatable: false,
-}
-
-apex {
- name: "com.android.apex.cts.shim.v2_sign_payload_with_different_key",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
- androidManifest: "AndroidManifest.xml",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.cts.shim.debug.key",
- prebuilts: ["hash_of_dev_null"],
- installable: false,
- allowed_files: "default_shim_allowed_list.txt",
- updatable: false,
}
apex {
@@ -121,7 +81,6 @@ apex {
prebuilts: ["hash_of_dev_null"],
installable: false,
allowed_files: "default_shim_allowed_list.txt",
- updatable: false,
}
apex {
@@ -134,14 +93,12 @@ apex {
apps: ["CtsShim", "CtsShimPriv"],
installable: false,
allowed_files: "default_shim_allowed_list.txt",
- generate_hashtree: false,
- updatable: false,
+ test_only_no_hashtree: true,
}
apex {
name: "com.android.apex.cts.shim.v2_unsigned_payload",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
+ manifest: "manifest_v2.json",
androidManifest: "AndroidManifest.xml",
file_contexts: ":apex.test-file_contexts",
key: "com.android.apex.cts.shim.key",
@@ -150,14 +107,12 @@ apex {
installable: false,
allowed_files: "default_shim_allowed_list.txt",
test_only_unsigned_payload: true,
- updatable: false,
}
override_apex {
name: "com.android.apex.cts.shim.v2_different_package_name",
package_name: "com.android.apex.cts.shim.different",
- // Use rebootless APEX to re-use this APEX in the rebootless update test case.
- base: "com.android.apex.cts.shim.v2_rebootless",
+ base: "com.android.apex.cts.shim.v2",
}
genrule {
@@ -177,14 +132,12 @@ prebuilt_etc {
// to stage it should fail.
apex {
name: "com.android.apex.cts.shim.v2_wrong_sha",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
+ manifest: "manifest_v2.json",
androidManifest: "AndroidManifest.xml",
file_contexts: ":apex.test-file_contexts",
key: "com.android.apex.cts.shim.key",
prebuilts: ["empty_hash"],
installable: false,
- updatable: false,
}
prebuilt_etc {
@@ -196,14 +149,12 @@ prebuilt_etc {
apex {
name: "com.android.apex.cts.shim.v2_additional_file",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
+ 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", "apex_shim_additional_file"],
installable: false,
- updatable: false,
}
prebuilt_etc {
@@ -216,14 +167,12 @@ prebuilt_etc {
apex {
name: "com.android.apex.cts.shim.v2_additional_folder",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
+ 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", "apex_shim_additional_folder"],
installable: false,
- updatable: false,
}
apex {
@@ -234,7 +183,6 @@ apex {
key: "com.android.apex.cts.shim.key",
prebuilts: ["hash_of_dev_null"],
installable: false,
- updatable: false,
}
apex {
@@ -245,7 +193,6 @@ apex {
key: "com.android.apex.cts.shim.key",
prebuilts: ["hash_of_dev_null"],
installable: false,
- updatable: false,
}
genrule {
@@ -265,9 +212,7 @@ genrule {
":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_rebootless",
":com.android.apex.cts.shim.v3",
- ":com.android.apex.cts.shim.v3_rebootless",
":com.android.apex.cts.shim.v3_signed_bob",
":com.android.apex.cts.shim.v3_signed_bob_rot",
],
@@ -291,7 +236,6 @@ apex {
prebuilts: ["hash_v1"],
apps: ["CtsShim", "CtsShimPriv"],
allowed_files: "default_shim_allowed_list.txt",
- updatable: false,
}
// This is to install the flattened version of com.android.apex.cts.shim.
@@ -332,25 +276,21 @@ apex_key {
apex {
name: "com.android.apex.cts.shim_not_pre_installed",
manifest: "manifest_not_pre_installed.json",
- androidManifest: "AndroidManifestNotPreInstalled.xml",
file_contexts: ":apex.test-file_contexts",
key: "com.android.apex.cts.shim_not_pre_installed.key",
prebuilts: ["hash_of_dev_null"],
installable: false,
- updatable: false,
}
apex {
name: "com.android.apex.cts.shim.v2_different_certificate",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
+ 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"],
installable: false,
certificate: ":com.android.apex.cts.shim.debug.cert",
- updatable: false,
}
android_app_certificate {
@@ -515,7 +455,6 @@ apex {
apps: ["CtsShim", "CtsShimPriv"],
installable: false,
min_sdk_version: "29",
- updatable: false,
}
genrule {
@@ -529,15 +468,13 @@ genrule {
// Apex shim that targets an old sdk (P)
apex {
name: "com.android.apex.cts.shim.v2_sdk_target_p",
- // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
- manifest: "manifest_v2_rebootless.json",
+ manifest: "manifest_v2.json",
androidManifest: "AndroidManifestSdkTargetP.xml",
file_contexts: ":apex.test-file_contexts",
key: "com.android.apex.cts.shim.key",
prebuilts: ["hash_of_dev_null"],
installable: false,
apps: ["CtsShim", "CtsShimPriv"],
- updatable: false,
}
// Apex shim with apk-in-apex that targets sdk P
@@ -550,35 +487,15 @@ apex {
prebuilts: ["hash_of_dev_null"],
apps: ["CtsShimTargetPSdk"],
installable: false,
- updatable: false,
}
// Apex shim with unsigned apk
genrule {
name: "com.android.apex.cts.shim.v2_unsigned_apk_container",
- // Use shim.v2_rebootless to re-use same APEX in the rebootless update test case.
- srcs: [":com.android.apex.cts.shim.v2_rebootless"],
+ srcs: [":com.android.apex.cts.shim.v2"],
out: ["com.android.apex.cts.shim.v2_unsigned_apk_container.apex"],
cmd: "cp -v $(in) $(out) && zip -d $(out) META-INF*",
-}
-
-// Apex shim for testing rebootless updates
-apex {
- name: "com.android.apex.cts.shim.v2_rebootless",
- manifest: "manifest_v2_rebootless.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.cts.shim.key",
- prebuilts: ["hash_of_dev_null"],
- installable: false,
- updatable: false,
-}
-
-apex {
- name: "com.android.apex.cts.shim.v3_rebootless",
- manifest: "manifest_v3_rebootless.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.cts.shim.key",
- prebuilts: ["hash_of_dev_null"],
- installable: false,
- updatable: false,
+ dist: {
+ targets: ["apps_only"],
+ }
}
diff --git a/shim/build/AndroidManifestNotPreInstalled.xml b/shim/build/AndroidManifestNotPreInstalled.xml
deleted file mode 100644
index 82955f77..00000000
--- a/shim/build/AndroidManifestNotPreInstalled.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.apex.cts.shim_not_pre_installed">
- <!-- APEX does not have classes.dex -->
- <application android:hasCode="false" />
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/>
-</manifest>
-
diff --git a/shim/build/manifest_not_pre_installed.json b/shim/build/manifest_not_pre_installed.json
index 6653f8da..078e1aec 100644
--- a/shim/build/manifest_not_pre_installed.json
+++ b/shim/build/manifest_not_pre_installed.json
@@ -1,5 +1,4 @@
{
"name": "com.android.apex.cts.shim_not_pre_installed",
- "version": 1,
- "supportsRebootlessUpdate": true
+ "version": 1
}
diff --git a/shim/build/manifest_v2_rebootless.json b/shim/build/manifest_v2_rebootless.json
deleted file mode 100644
index 5f6adfdb..00000000
--- a/shim/build/manifest_v2_rebootless.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "com.android.apex.cts.shim",
- "version": 2,
- "supportsRebootlessUpdate": true
-}
diff --git a/shim/build/manifest_v2_with_post_install_hook.json b/shim/build/manifest_v2_with_post_install_hook.json
index a4e3f019..7faecd8c 100644
--- a/shim/build/manifest_v2_with_post_install_hook.json
+++ b/shim/build/manifest_v2_with_post_install_hook.json
@@ -1,6 +1,5 @@
{
"name": "com.android.apex.cts.shim",
"version": 2,
- "postInstallHook": "/bin/false",
- "supportsRebootlessUpdate": true
+ "postInstallHook": "/bin/false"
}
diff --git a/shim/build/manifest_v2_with_pre_install_hook.json b/shim/build/manifest_v2_with_pre_install_hook.json
index e2a874c8..57bd6203 100644
--- a/shim/build/manifest_v2_with_pre_install_hook.json
+++ b/shim/build/manifest_v2_with_pre_install_hook.json
@@ -1,6 +1,5 @@
{
"name": "com.android.apex.cts.shim",
"version": 2,
- "preInstallHook": "/bin/true",
- "supportsRebootlessUpdate": true
+ "preInstallHook": "/bin/true"
}
diff --git a/shim/build/manifest_v3_rebootless.json b/shim/build/manifest_v3_rebootless.json
deleted file mode 100644
index 61e63ff0..00000000
--- a/shim/build/manifest_v3_rebootless.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "com.android.apex.cts.shim",
- "version": 3,
- "supportsRebootlessUpdate": true
-}
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 791d0dd9..7b5758dc 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 0a26d236..dc2c8c9d 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 5ed2c7e0..3cf81757 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 133f7f72..53358189 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 6ce53975..4f0edff6 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_different_certificate.apex b/shim/prebuilts/arm/com.android.apex.cts.shim.v2_different_certificate.apex
index 4228ffed..af89d200 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 de090f19..12b85e43 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 162044cf..00c0c197 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
deleted file mode 100644
index 9d688876..00000000
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_rebootless.apex
+++ /dev/null
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 44f7613c..50e77bdd 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
deleted file mode 100644
index 389871de..00000000
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
+++ /dev/null
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 f8fa44fb..3bde9ba5 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 96588183..26c3f27a 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 34400434..81aaecfc 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 d6f7d8ff..d2be4a2a 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 cc214f8c..e1f904e6 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 dab82a02..c8aa9d98 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 9706f2f2..41c29bfd 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 f305cff9..1447e7d2 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 3122c967..e538f831 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
deleted file mode 100644
index 0f5134da..00000000
--- a/shim/prebuilts/arm/com.android.apex.cts.shim.v3_rebootless.apex
+++ /dev/null
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 a83bf51f..86b418e0 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 703b6411..29a0877b 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 806ccc77..e8705c7f 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 a94ae752..04ec92da 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 a9c27586..ff547892 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 5ed2c7e0..3cf81757 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 133f7f72..53358189 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 6ce53975..4f0edff6 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_different_certificate.apex b/shim/prebuilts/x86/com.android.apex.cts.shim.v2_different_certificate.apex
index 4228ffed..af89d200 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 de090f19..eca1c375 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 19ec142a..19da8646 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
deleted file mode 100644
index 9d688876..00000000
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_rebootless.apex
+++ /dev/null
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 9929c3dc..6b7436b4 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
deleted file mode 100644
index 389871de..00000000
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex
+++ /dev/null
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 3f2fc505..659f4625 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 cf628abb..c5e22108 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 ba5af3b5..3ff88a91 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 38c073f8..cd702268 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 cc214f8c..e1f904e6 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 dab82a02..c8aa9d98 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 9706f2f2..41c29bfd 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 f305cff9..1447e7d2 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 7f3e9ecb..b3ecef76 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
deleted file mode 100644
index 0f5134da..00000000
--- a/shim/prebuilts/x86/com.android.apex.cts.shim.v3_rebootless.apex
+++ /dev/null
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 1aeb0b0c..9281ee39 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 20f1c850..23b23789 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 806ccc77..e8705c7f 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 425f2bc2..96fd30b4 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
java_defaults {
name: "apex_e2e_test_defaults",
libs: [
@@ -28,6 +24,17 @@ java_defaults {
}
java_test_host {
+ name: "adbd_e2e_tests",
+ srcs: ["src/**/AdbdHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.adbd",
+ ],
+ test_config: "adbd-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
name: "timezone_data_e2e_tests",
srcs: ["src/**/TimezoneDataHostTest.java"],
defaults: ["apex_e2e_test_defaults"],
@@ -42,6 +49,17 @@ java_test_host {
}
java_test_host {
+ name: "statsd_e2e_tests",
+ srcs: ["src/**/StatsdHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.os.statsd",
+ ],
+ test_config: "statsd-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
name: "media_e2e_tests",
srcs: ["src/**/MediaHostTest.java"],
defaults: ["apex_e2e_test_defaults"],
@@ -64,6 +82,95 @@ java_test_host {
}
java_test_host {
+ name: "mediaprovider_e2e_tests",
+ srcs: ["src/**/MediaProviderHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.mediaprovider",
+ ],
+ test_config: "mediaprovider-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
+ name: "conscrypt_e2e_tests",
+ srcs: ["src/**/ConscryptHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.conscrypt",
+ ],
+ test_config: "conscrypt-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
+ name: "neuralnetworks_e2e_tests",
+ srcs: ["src/**/NeuralNetworksHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.neuralnetworks",
+ ],
+ test_config: "neuralnetworks-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+
+java_test_host {
+ name: "cellbroadcast_e2e_tests",
+ srcs: ["src/**/CellbroadcastHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.cellbroadcast",
+ ],
+ test_config: "cellbroadcast-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
+ name: "ipsec_e2e_tests",
+ srcs: ["src/**/IpSecHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.ipsec",
+ ],
+ test_config: "ipsec-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
+ name: "permission_e2e_tests",
+ srcs: ["src/**/PermissionHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.permission",
+ ],
+ test_config: "permission-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
+ name: "wifi_e2e_tests",
+ srcs: ["src/**/WifiHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.wifi",
+ ],
+ test_config: "wifi-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
+ name: "extservices_e2e_tests",
+ srcs: ["src/**/ExtServicesHostTest.java"],
+ defaults: ["apex_e2e_test_defaults"],
+ data: [
+ ":test_com.android.extservices",
+ ],
+ test_config: "extservices-e2e-tests.xml",
+ test_suites: ["device-tests"],
+}
+
+java_test_host {
name: "apex_targetprep_tests",
libs: ["tradefed"],
srcs: ["src/**/ApexTargetPrepTest.java"],
@@ -76,14 +183,19 @@ java_library_host {
name: "apex_e2e_base_test",
srcs: ["src/**/ApexE2EBaseHostTest.java"],
static_libs: [
- "frameworks-base-hostutils",
- "cts-install-lib-host",
+ "module_test_util",
],
libs: [
"tradefed",
],
}
+java_library_host {
+ name: "module_test_util",
+ srcs: ["util/**/ModuleTestUtils.java"],
+ libs: ["tradefed", "truth-prebuilt"],
+}
+
apex {
name: "apex.test",
manifest: "testdata/apex_manifest.json",
@@ -91,7 +203,6 @@ apex {
key: "apex.test.key",
certificate: ":apex.test.certificate",
installable: false,
- updatable: false,
}
apex_key {
@@ -126,11 +237,21 @@ prebuilt_etc {
installable: false,
}
+cc_binary {
+ name: "sample_prefer32_binary",
+ srcs: ["sample_prefer32_binary.cc"],
+ target: {
+ android: {
+ compile_multilib: "prefer32",
+ },
+ },
+}
+
java_test_host {
name: "apex_rollback_tests",
- srcs: ["src/**/ApexRollbackTests.java"],
+ srcs: ["src/**/ApexRollbackTests.java", "src/**/ApexTestUtils.java"],
libs: ["tradefed", "truth-prebuilt"],
- static_libs: ["frameworks-base-hostutils", "cts-install-lib-host"],
+ static_libs: ["module_test_util"],
test_config: "apex-rollback-tests.xml",
test_suites: ["general-tests"],
@@ -144,17 +265,23 @@ java_test_host {
}
java_test_host {
+ name: "module_test_utils_tests",
+ srcs: ["src/**/ModuleTestUtilsTest.java"],
+ libs: ["tradefed", "truth-prebuilt"],
+ static_libs: ["module_test_util"],
+ test_config: "module-test-utils-tests.xml",
+ test_suites: ["general-tests"],
+ data: [":com.android.apex.cts.shim.v2_prebuilt"],
+}
+
+java_test_host {
name: "apexd_host_tests",
- srcs: [
- "src/**/ApexdHostTest.java",
- ":apex-info-list",
- ],
+ srcs: ["src/**/ApexdHostTest.java"],
libs: ["tradefed"],
static_libs: [
+ "module_test_util",
"truth-prebuilt",
"apex_manifest_proto_java",
- "frameworks-base-hostutils",
- "cts-install-lib-host"
],
test_config: "apexd-host-tests.xml",
test_suites: ["general-tests"],
@@ -165,67 +292,5 @@ java_test_host {
":apex.apexd_test_v3",
":com.android.apex.cts.shim.v2_prebuilt",
":com.android.apex.cts.shim.v2_no_pb",
- ":com.android.apex.cts.shim.v2_additional_file_prebuilt",
- ],
-}
-
-java_test_host {
- name: "sharedlibs_host_tests",
- srcs: [
- "src/**/SharedLibsApexTest.java"
- ],
- libs: ["tradefed"],
- java_resources: [
- ":com.android.apex.test.bar_stripped.v1.libvX_prebuilt",
- ":com.android.apex.test.bar_stripped.v2.libvY_prebuilt",
- ":com.android.apex.test.bar.v1.libvX_prebuilt",
- ":com.android.apex.test.bar.v2.libvY_prebuilt",
- ":com.android.apex.test.baz_stripped.v1.libvX_prebuilt",
- ":com.android.apex.test.foo_stripped.v1.libvX_prebuilt",
- ":com.android.apex.test.foo_stripped.v2.libvY_prebuilt",
- ":com.android.apex.test.foo.v1.libvX_prebuilt",
- ":com.android.apex.test.foo.v2.libvY_prebuilt",
- ":com.android.apex.test.pony_stripped.v1.libvZ_prebuilt",
- ":com.android.apex.test.pony.v1.libvZ_prebuilt",
- ":com.android.apex.test.sharedlibs_generated.v1.libvX_prebuilt",
- ":com.android.apex.test.sharedlibs_generated.v2.libvY_prebuilt",
- ":com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ_prebuilt",
],
- static_libs: [
- "compatibility-host-util",
- "cts-install-lib-host",
- "frameworks-base-hostutils",
- "truth-prebuilt"
- ],
- test_config: "shared-libs-apex-tests.xml",
- test_suites: ["general-tests"],
-}
-
-java_test_host {
- name: "apex_compression_platform_tests",
- srcs: ["src/**/ApexCompressionTests.java"],
- libs: ["tradefed", "truth-prebuilt"],
- static_libs: ["cts-install-lib-host", "testng"],
- test_config: "apex_compression_platform_tests.xml",
- test_suites: ["general-tests"],
- data: [
- ":com.android.apex.compressed.v1",
- ":com.android.apex.compressed.v1_original",
- ":com.android.apex.compressed.v1_different_digest",
- ":com.android.apex.compressed.v2",
- ":gen_manifest_mismatch_compressed_apex_v2",
- ":apex_compression_tests_app",
- ],
-}
-
-android_test_helper_app {
- name: "apex_compression_tests_app",
- 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: [
- ":com.android.apex.compressed.v1_original",
- ":com.android.apex.compressed.v2_original",
- ]
}
diff --git a/tests/TEST_MAPPING b/tests/TEST_MAPPING
index d3177a80..cd488fb2 100644
--- a/tests/TEST_MAPPING
+++ b/tests/TEST_MAPPING
@@ -1,25 +1,49 @@
{
"presubmit": [
{
+ "name": "apex_rollback_tests"
+ },
+ {
"name": "apex_targetprep_tests"
},
{
- "name": "timezone_data_e2e_tests"
+ "name": "adbd_e2e_tests"
},
{
- "name": "CtsApexSharedLibrariesTestCases"
- }
- ],
- "presubmit-large": [
- // TODO(b/190710217): uncomment this.
- //{
- // "name": "apex_rollback_tests"
- //},
+ "name": "apexd_host_tests"
+ },
+ {
+ "name": "conscrypt_e2e_tests"
+ },
+ {
+ "name": "extservices_e2e_tests"
+ },
+ {
+ "name": "neuralnetworks_e2e_tests"
+ },
+ {
+ "name": "permission_e2e_tests"
+ },
{
"name": "sdkextensions_e2e_tests"
},
{
- "name": "sharedlibs_host_tests"
+ "name": "statsd_e2e_tests"
+ },
+ {
+ "name": "timezone_data_e2e_tests"
+ },
+ {
+ "name": "ipsec_e2e_tests"
+ },
+ {
+ "name": "wifi_e2e_tests"
+ },
+ {
+ "name": "mediaprovider_e2e_tests"
+ },
+ {
+ "name": "cellbroadcast_e2e_tests"
}
],
"postsubmit": [
@@ -34,16 +58,57 @@
"name": "media_swcodec_e2e_tests",
"keywords": ["primary-device"]
},
+ // The following changes are in post-submit to restrict to physical
+ // devices (currently userspace reboot fails on cuttlefish).
+ // TODO(b/147726967): Remove when Userspace reboot works on cuttlefish
{
- "name": "apex_compression_platform_tests"
+ "name": "adbd_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "conscrypt_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "extservices_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "neuralnetworks_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "permission_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "sdkextensions_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "timezone_data_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "ipsec_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "wifi_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "mediaprovider_e2e_tests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "cellbroadcast_e2e_tests",
+ "keywords": ["primary-device"]
}
],
"imports": [
{
"path": "cts/hostsidetests/stagedinstall"
- },
- {
- "path": "frameworks/base/tests/StagedInstallTest"
}
]
}
diff --git a/tests/adbd-e2e-tests.xml b/tests/adbd-e2e-tests.xml
new file mode 100644
index 00000000..a144d834
--- /dev/null
+++ b/tests/adbd-e2e-tests.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Configuration for adbd module e2e tests">
+ <option name="test-suite-tag" value="adbd_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="adbd_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.adbd.apex" />
+ </test>
+</configuration>
diff --git a/tests/apex_compression_platform_tests.xml b/tests/apex_compression_platform_tests.xml
deleted file mode 100644
index a837fbad..00000000
--- a/tests/apex_compression_platform_tests.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Runs the apex compression test cases">
- <option name="test-suite-tag" value="apex_compression_platform_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_compression_tests_app.apk" />
- </target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="setprop persist.rollback.is_test 1" />
- <option name="teardown-command" value="setprop persist.rollback.is_test 0" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.HostTest" >
- <option name="class"
- value="com.android.tests.apex.host.ApexCompressionTests" />
- </test>
-</configuration>
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
deleted file mode 100644
index 0644ba7e..00000000
--- a/tests/app/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tests.apex.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.app"
- android:label="ApexCompression Test"/>
-
-</manifest>
diff --git a/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java b/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java
deleted file mode 100644
index a97293ce..00000000
--- a/tests/app/src/com/android/tests/apex/app/ApexCompressionTests.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.apex.app;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.rollback.RollbackInfo;
-
-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;
-
-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 ApexCompressionTests {
- private static final String COMPRESSED_APEX_PACKAGE_NAME = "com.android.apex.compressed";
- private final Context mContext = InstrumentationRegistry.getContext();
- private final PackageManager mPm = mContext.getPackageManager();
-
- private static final TestApp UNCOMPRESSED_APEX_V1 = new TestApp(
- "TestAppUncompressedApexV1", COMPRESSED_APEX_PACKAGE_NAME, 2, /*isApex*/ true,
- "com.android.apex.compressed.v1_original.apex");
- private static final TestApp UNCOMPRESSED_APEX_V2 = new TestApp(
- "TestAppUncompressedApexV2", COMPRESSED_APEX_PACKAGE_NAME, 2, /*isApex*/ true,
- "com.android.apex.compressed.v2_original.apex");
-
- @Before
- public void adoptShellPermissions() {
- androidx.test.platform.app.InstrumentationRegistry
- .getInstrumentation()
- .getUiAutomation()
- .adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- }
-
- @After
- public void dropShellPermissions() {
- androidx.test.platform.app.InstrumentationRegistry
- .getInstrumentation()
- .getUiAutomation()
- .dropShellPermissionIdentity();
- }
-
- @Test
- public void testDecompressedApexIsConsideredFactory() throws Exception {
- // Only retrieve active apex package
- PackageInfo pi = mPm.getPackageInfo(
- COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
- assertThat(pi).isNotNull();
- assertThat(pi.isApex).isTrue();
- assertThat(pi.packageName).isEqualTo(COMPRESSED_APEX_PACKAGE_NAME);
- assertThat(pi.getLongVersionCode()).isEqualTo(1);
- boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- assertThat(isFactoryPackage).isTrue();
- }
-
- @Test
- public void testUnusedDecompressedApexIsCleanedUp_HigherVersion() throws Exception {
- Install.single(UNCOMPRESSED_APEX_V2).setStaged().commit();
- }
-
- @Test
- public void testUnusedDecompressedApexIsCleanedUp_SameVersion() throws Exception {
- Install.single(UNCOMPRESSED_APEX_V1).setStaged().commit();
- }
-
-
- @Test
- public void testCapexToApexSwitch() throws Exception {
- // Only retrieve active apex package
- PackageInfo pi = mPm.getPackageInfo(
- COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
- assertThat(pi).isNotNull();
- assertThat(pi.isApex).isTrue();
- assertThat(pi.packageName).isEqualTo(COMPRESSED_APEX_PACKAGE_NAME);
- assertThat(pi.getLongVersionCode()).isEqualTo(1);
- boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- assertThat(isFactoryPackage).isTrue();
- assertThat(pi.applicationInfo.sourceDir).startsWith("/system/apex");
- }
-
- @Test
- public void testDecompressedApexVersionAlwaysHasSameVersionAsCapex() throws Exception {
- // Only retrieve active apex package
- PackageInfo pi = mPm.getPackageInfo(
- COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
- assertThat(pi).isNotNull();
- assertThat(pi.isApex).isTrue();
- assertThat(pi.packageName).isEqualTo(COMPRESSED_APEX_PACKAGE_NAME);
- assertThat(pi.getLongVersionCode()).isEqualTo(1);
- boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- assertThat(isFactoryPackage).isTrue();
- }
-
- @Test
- public void testCompressedApexCanBeRolledBack_Commit() throws Exception {
- // Verify before updating
- PackageInfo pi = mPm.getPackageInfo(
- COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
- assertThat(pi.getLongVersionCode()).isEqualTo(1);
- boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- assertThat(isFactoryPackage).isTrue();
- assertThat(pi.applicationInfo.sourceDir).startsWith("/data/apex/decompressed/");
-
- Install.single(UNCOMPRESSED_APEX_V2).setStaged().setEnableRollback().commit();
- }
-
- @Test
- public void testCompressedApexCanBeRolledBack_Rollback() throws Exception {
- // Verify before rollback
- PackageInfo pi = mPm.getPackageInfo(
- COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
- assertThat(pi.getLongVersionCode()).isEqualTo(2);
- boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- assertThat(isFactoryPackage).isFalse();
- assertThat(pi.applicationInfo.sourceDir).startsWith("/data/apex/active/");
-
- // 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
- public void testCompressedApexCanBeRolledBack_Verify() throws Exception {
- // Verify rollback worked
- PackageInfo pi = mPm.getPackageInfo(
- COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
- assertThat(pi.getLongVersionCode()).isEqualTo(1);
- boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- assertThat(isFactoryPackage).isFalse();
- assertThat(pi.applicationInfo.sourceDir).startsWith("/data/apex/active/");
- }
-}
diff --git a/tests/cellbroadcast-e2e-tests.xml b/tests/cellbroadcast-e2e-tests.xml
new file mode 100644
index 00000000..368a88fa
--- /dev/null
+++ b/tests/cellbroadcast-e2e-tests.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for Cellbroadcast module e2e test cases">
+ <option name="test-suite-tag" value="cellbroadcast_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="cellbroadcast_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.cellbroadcast.apex" />
+ </test>
+</configuration> \ No newline at end of file
diff --git a/tests/conscrypt-e2e-tests.xml b/tests/conscrypt-e2e-tests.xml
new file mode 100644
index 00000000..77f781a2
--- /dev/null
+++ b/tests/conscrypt-e2e-tests.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for Conscrypt module e2e test cases">
+ <option name="test-suite-tag" value="conscrypt_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="conscrypt_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.conscrypt.apex" />
+ </test>
+</configuration>
+
diff --git a/tests/extservices-e2e-tests.xml b/tests/extservices-e2e-tests.xml
new file mode 100644
index 00000000..c45392e6
--- /dev/null
+++ b/tests/extservices-e2e-tests.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for extservices apex e2e testing">
+ <option name="test-suite-tag" value="extservices_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="extservices_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.extservices.apex" />
+ </test>
+</configuration>
diff --git a/tests/ipsec-e2e-tests.xml b/tests/ipsec-e2e-tests.xml
new file mode 100644
index 00000000..0030bd34
--- /dev/null
+++ b/tests/ipsec-e2e-tests.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for ipsec module e2e testing">
+ <option name="test-suite-tag" value="ipsec_e2e_test" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="ipsec_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.ipsec.apex" />
+ </test>
+</configuration>
+
diff --git a/tests/mediaprovider-e2e-tests.xml b/tests/mediaprovider-e2e-tests.xml
new file mode 100644
index 00000000..e1212622
--- /dev/null
+++ b/tests/mediaprovider-e2e-tests.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for MediaProvider module e2e test cases">
+ <option name="test-suite-tag" value="mediaprovider_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="mediaprovider_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.mediaprovider.apex" />
+ </test>
+</configuration>
diff --git a/tests/module-test-utils-tests.xml b/tests/module-test-utils-tests.xml
new file mode 100644
index 00000000..6337ab92
--- /dev/null
+++ b/tests/module-test-utils-tests.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Unit tests for ModuleTestUtils">
+ <option name="test-suite-tag" value="module_test_utils_tests" />
+ <option name="test-suite-tag" value="apct" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="module_test_utils_tests.jar" />
+ </test>
+</configuration>
diff --git a/tests/native/.clang-format b/tests/native/.clang-format
deleted file mode 100644
index f6cb8ad9..00000000
--- a/tests/native/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-BasedOnStyle: Google
diff --git a/tests/native/Android.bp b/tests/native/Android.bp
deleted file mode 100644
index 79152223..00000000
--- a/tests/native/Android.bp
+++ /dev/null
@@ -1,55 +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"],
-}
-
-cc_test {
- name: "CtsApexSharedLibrariesTestCases",
- test_suites: [
- "cts",
- "device-tests",
- "mts",
- ],
- compile_multilib: "both",
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
-
- shared_libs: [
- "libbase",
- "liblog",
- ],
-
- static_libs: [
- "libc++fs",
- "libfs_mgr",
- ],
-
- srcs: [
- "apex_shared_libraries_test.cpp",
- ],
-
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- ],
-}
diff --git a/tests/native/AndroidTest.xml b/tests/native/AndroidTest.xml
deleted file mode 100644
index fa189d5e..00000000
--- a/tests/native/AndroidTest.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="Config for CTS apex_shared_libraries test cases">
- <option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="systems" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
- <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
- <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="cleanup" value="true" />
- <option name="push" value="CtsApexSharedLibrariesTestCases->/data/local/tmp/CtsApexSharedLibrariesTestCases" />
- <option name="append-bitness" value="true" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="CtsApexSharedLibrariesTestCases" />
- <option name="runtime-hint" value="65s" />
- </test>
-</configuration>
diff --git a/tests/native/apex_shared_libraries_test.cpp b/tests/native/apex_shared_libraries_test.cpp
deleted file mode 100644
index 9f536dc6..00000000
--- a/tests/native/apex_shared_libraries_test.cpp
+++ /dev/null
@@ -1,142 +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.
- */
-#define LOG_TAG "apex_shared_libraries_test"
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/scopeguard.h>
-#include <android-base/strings.h>
-#include <dlfcn.h>
-#include <fstab/fstab.h>
-#include <gtest/gtest.h>
-#include <link.h>
-
-#include <filesystem>
-#include <fstream>
-#include <string>
-
-using android::base::GetBoolProperty;
-using android::base::Split;
-using android::base::StartsWith;
-using android::fs_mgr::Fstab;
-using android::fs_mgr::ReadFstabFromFile;
-
-namespace fs = std::filesystem;
-
-static constexpr const char* kApexRoot = "/apex";
-static constexpr const char* kApexSharedLibsRoot = "/apex/sharedlibs";
-
-TEST(apex_shared_libraries, symlink_libraries_loadable) {
- if (!GetBoolProperty("ro.apex.updatable", false)) {
- GTEST_SKIP() << "Skipping test because device doesn't support APEX";
- }
-
- Fstab fstab;
- ASSERT_TRUE(ReadFstabFromFile("/proc/mounts", &fstab));
-
- // Traverse mount points to identify apexs.
- for (auto& entry : fstab) {
- if (fs::path(entry.mount_point).parent_path() != kApexRoot) {
- continue;
- }
-
- // Focus on "active" apexs.
- if (entry.mount_point.find('@') != std::string::npos) {
- continue;
- }
- std::string dev_file = fs::path(entry.blk_device).filename();
-
- // Filter out any mount irrelevant (e.g. tmpfs)
- if (!StartsWith(dev_file, "loop") && !StartsWith(dev_file, "dm-")) {
- continue;
- }
-
-#if !defined(__LP64__)
- auto lib = fs::path(entry.mount_point) / "lib";
-#else // !__LP64__
- auto lib = fs::path(entry.mount_point) / "lib64";
-#endif // !__LP64__
- if (!fs::is_directory(lib)) {
- continue;
- }
- for (auto& p : fs::directory_iterator(lib)) {
- std::error_code ec;
- if (!fs::is_symlink(p, ec)) {
- continue;
- }
-
- // We are only checking libraries pointing at a location inside
- // /apex/sharedlibs.
- auto target = fs::read_symlink(p.path(), ec);
- if (ec || !StartsWith(target.string(), kApexSharedLibsRoot)) {
- continue;
- }
-
- // Symlink validity check.
- auto dest = fs::canonical(p.path(), ec);
- EXPECT_FALSE(ec) << "Failed to resolve " << p.path() << " (symlink to "
- << target << "): " << ec;
- if (ec) {
- continue;
- }
-
- // Library loading validity check.
- dlerror(); // Clear any pending errors.
- void* handle = dlopen(p.path().c_str(), RTLD_NOW);
- EXPECT_TRUE(handle != nullptr) << dlerror();
- if (handle == nullptr) {
- continue;
- }
- auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
-
- // Check that library is loaded and pointing to the realpath of the
- // library.
- auto dl_callback = [](dl_phdr_info* info, size_t /* size */, void* data) {
- auto dest = *static_cast<fs::path*>(data);
- if (info->dlpi_name == nullptr) {
- // This is linker imposing as libdl.so - skip it
- return 0;
- }
- int j;
- for (j = 0; j < info->dlpi_phnum; j++) {
- void* addr = (void*)(info->dlpi_addr + info->dlpi_phdr[j].p_vaddr);
- Dl_info dl_info;
- int rc = dladdr(addr, &dl_info);
- if (rc == 0) {
- continue;
- }
- if (dl_info.dli_fname) {
- auto libpath = fs::path(dl_info.dli_fname);
- if (libpath == dest) {
- // Library found!
- return 1;
- }
- }
- }
-
- return 0;
- };
- bool found = (dl_iterate_phdr(dl_callback, &dest) == 1);
- EXPECT_TRUE(found) << "Error verifying library symlink " << p.path()
- << " which points to " << target
- << " which resolves to file " << dest;
- if (found) {
- LOG(INFO) << "Verified that " << p.path()
- << " correctly loads as library " << dest;
- }
- }
- }
-}
diff --git a/tests/neuralnetworks-e2e-tests.xml b/tests/neuralnetworks-e2e-tests.xml
new file mode 100644
index 00000000..63c38a68
--- /dev/null
+++ b/tests/neuralnetworks-e2e-tests.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for neuralnetworks module e2e test cases">
+ <option name="test-suite-tag" value="neuralnetworks_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="neuralnetworks_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.neuralnetworks.apex" />
+ </test>
+</configuration>
+
diff --git a/tests/permission-e2e-tests.xml b/tests/permission-e2e-tests.xml
new file mode 100644
index 00000000..e1605abe
--- /dev/null
+++ b/tests/permission-e2e-tests.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<configuration description="Configuration for permission module e2e test cases">
+ <option name="test-suite-tag" value="permission_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="permission_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.permission.apex" />
+ </test>
+</configuration>
diff --git a/tests/sample_prefer32_binary.cc b/tests/sample_prefer32_binary.cc
new file mode 100644
index 00000000..76e81970
--- /dev/null
+++ b/tests/sample_prefer32_binary.cc
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/shared-libs-apex-tests.xml b/tests/shared-libs-apex-tests.xml
deleted file mode 100644
index d41b8916..00000000
--- a/tests/shared-libs-apex-tests.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Runs the shared libs apex host side test cases">
- <option name="test-suite-tag" value="sharedlibs_host_tests" />
- <option name="test-suite-tag" value="apct" />
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
- <test class="com.android.tradefed.testtype.HostTest" >
- <option name="jar" value="sharedlibs_host_tests.jar" />
- </test>
-</configuration>
diff --git a/tests/testdata/sharedlibs/build/include/sharedlibstest.h b/tests/src/com/android/tests/apex/AdbdHostTest.java
index a2f0cdc9..445ca88b 100644
--- a/tests/testdata/sharedlibs/build/include/sharedlibstest.h
+++ b/tests/src/com/android/tests/apex/AdbdHostTest.java
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#ifndef SHAREDLIBSTEST_H_
-#define SHAREDLIBSTEST_H_
+package com.android.tests.apex;
-#include <string>
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-namespace sharedlibstest {
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
-std::string getSharedLibsTestFingerprint();
-
-} // namespace sharedlibstest
-
-#endif // SHAREDLIBSTEST_H_
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+@Ignore // TODO(b/148759193): remove when test is fixed
+public class AdbdHostTest extends ApexE2EBaseHostTest {
+}
diff --git a/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java b/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java
index e0871df5..0812c6ac 100644
--- a/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java
+++ b/tests/src/com/android/tests/apex/ApexE2EBaseHostTest.java
@@ -21,10 +21,9 @@ 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.tests.util.ModuleTestUtils;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.device.ITestDevice.ApexInfo;
@@ -34,7 +33,6 @@ import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import java.io.File;
@@ -54,11 +52,8 @@ public abstract class ApexE2EBaseHostTest extends BaseHostJUnit4Test {
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);
-
- @Rule
- public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this);
+ /* protected so that derived tests can have access to test utils automatically */
+ protected final ModuleTestUtils mUtils = new ModuleTestUtils(this);
@Option(name = OPTION_APEX_FILE_NAME,
description = "The file name of the apex module.",
@@ -69,13 +64,15 @@ public abstract class ApexE2EBaseHostTest extends BaseHostJUnit4Test {
@Before
public void setUp() throws Exception {
- assumeTrue("Updating APEX is not supported", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Updating APEX is not supported", mUtils.isApexUpdateSupported());
+ mUtils.abandonActiveStagedSession();
uninstallAllApexes();
}
@After
public void tearDown() throws Exception {
- assumeTrue("Updating APEX is not supported", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Updating APEX is not supported", mUtils.isApexUpdateSupported());
+ mUtils.abandonActiveStagedSession();
uninstallAllApexes();
}
@@ -108,23 +105,35 @@ public abstract class ApexE2EBaseHostTest extends BaseHostJUnit4Test {
private void uninstallAllApexes() throws Exception {
for (String filename : getAllApexFilenames()) {
- ApexInfo apex = mHostUtils.getApexInfo(mHostUtils.getTestFile(filename));
+ ApexInfo apex = mUtils.getApexInfo(mUtils.getTestFile(filename));
uninstallApex(apex.name);
}
}
protected final ApexInfo installApex(String filename) throws Exception {
- File testAppFile = mHostUtils.getTestFile(filename);
+ File testAppFile = mUtils.getTestFile(filename);
- String installResult = mHostUtils.installStagedPackage(testAppFile);
+ String installResult = getDevice().installPackage(testAppFile, false, "--wait");
assertWithMessage("failed to install test app %s. Reason: %s", filename, installResult)
.that(installResult).isNull();
- ApexInfo testApexInfo = mHostUtils.getApexInfo(testAppFile);
+ ApexInfo testApexInfo = mUtils.getApexInfo(testAppFile);
Assert.assertNotNull(testApexInfo);
return testApexInfo;
}
+ protected final void installApexes(String... filenames) throws Exception {
+ // We don't use the installApex method from the super class here, because that won't install
+ // the two apexes into the same session.
+ String[] args = new String[filenames.length + 1];
+ args[0] = "install-multi-package";
+ for (int i = 0; i < filenames.length; i++) {
+ args[i + 1] = mUtils.getTestFile(filenames[i]).getAbsolutePath();
+ }
+ String stdout = getDevice().executeAdbCommand(args);
+ assertThat(stdout).isNotNull();
+ }
+
protected final void reboot(boolean userspaceReboot) throws Exception {
if (userspaceReboot) {
assertThat(getDevice().setProperty("test.userspace_reboot.requested", "1")).isTrue();
diff --git a/tests/src/com/android/tests/apex/ApexRollbackTests.java b/tests/src/com/android/tests/apex/ApexRollbackTests.java
index 68f82ca6..6cf54e1f 100644
--- a/tests/src/com/android/tests/apex/ApexRollbackTests.java
+++ b/tests/src/com/android/tests/apex/ApexRollbackTests.java
@@ -22,18 +22,16 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import android.cts.install.lib.host.InstallUtilsHost;
-
-import com.android.tests.rollback.host.AbandonSessionsRule;
-import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tests.util.ModuleTestUtils;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.ITestDevice.ApexInfo;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,20 +44,13 @@ import java.util.Set;
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public class ApexRollbackTests extends BaseHostJUnit4Test {
- private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
- @Rule
- public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this);
-
- private boolean mWasAdbRoot = false;
+ private final ModuleTestUtils mUtils = new ModuleTestUtils(this);
@Before
public void setUp() throws Exception {
- mHostUtils.uninstallShimApexIfNecessary();
+ mUtils.abandonActiveStagedSession();
+ mUtils.uninstallShimApexIfNecessary();
resetProperties();
- mWasAdbRoot = getDevice().isAdbRoot();
- if (!mWasAdbRoot) {
- assumeTrue("Requires root", getDevice().enableAdbRoot());
- }
}
/**
@@ -68,11 +59,9 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@After
public void tearDown() throws Exception {
- mHostUtils.uninstallShimApexIfNecessary();
+ mUtils.abandonActiveStagedSession();
+ mUtils.uninstallShimApexIfNecessary();
resetProperties();
- if (!mWasAdbRoot) {
- getDevice().disableAdbRoot();
- }
}
private void resetProperties() throws Exception {
@@ -92,15 +81,9 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testAutomaticBootLoopRecovery() throws Exception {
- 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: " + crashingProcess, hasCrashingProcess);
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ assumeTrue("Device does not support updating APEX", mUtils.isApexUpdateSupported());
+
+ File apexFile = mUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
// To simulate an apex update that causes a boot loop, we install a
// trigger_watchdog.rc file that arranges for a trigger_watchdog.sh
@@ -109,9 +92,10 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
// persist.debug.trigger_watchdog.apex is installed. If so,
// trigger_watchdog.sh repeatedly kills the system server causing a
// boot loop.
+ ITestDevice device = getDevice();
assertThat(device.setProperty("persist.debug.trigger_watchdog.apex",
"com.android.apex.cts.shim@2")).isTrue();
- String error = mHostUtils.installStagedPackage(apexFile);
+ String error = device.installPackage(apexFile, false, "--wait");
assertThat(error).isNull();
String sessionIdToCheck = device.executeShellCommand("pm get-stagedsessions --only-ready "
@@ -145,10 +129,10 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testSessionNotRevertedWithCheckpointingDisabled() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeFalse("Fs checkpointing is enabled", mHostUtils.isCheckpointSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.isApexUpdateSupported());
+ assumeFalse("Fs checkpointing is enabled", supportsFsCheckpointing());
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ File apexFile = mUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
ITestDevice device = getDevice();
assertThat(device.setProperty("persist.debug.trigger_reboot_after_activation",
@@ -156,7 +140,7 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
assertThat(device.setProperty("debug.trigger_reboot_once_after_activation",
"1")).isTrue();
- String error = mHostUtils.installStagedPackage(apexFile);
+ String error = device.installPackage(apexFile, false, "--wait");
assertThat(error).isNull();
String sessionIdToCheck = device.executeShellCommand("pm get-stagedsessions --only-ready "
@@ -169,8 +153,12 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
ApexInfo ctsShimV1 = new ApexInfo("com.android.apex.cts.shim", 1L);
ApexInfo ctsShimV2 = new ApexInfo("com.android.apex.cts.shim", 2L);
- String stagedSessionInfo = getStagedSession(sessionIdToCheck);
- assertThat(stagedSessionInfo).contains("isApplied = true");
+ String stagedSessionsInfo = device.executeShellCommand("pm get-stagedsessions");
+ for (String line: stagedSessionsInfo.split("[\\r\\n]+")) {
+ if (line.contains(sessionIdToCheck)) {
+ assertThat(line).contains("isApplied = true");
+ }
+ }
Set<ApexInfo> activatedApexes = device.getActiveApexes();
assertThat(activatedApexes).contains(ctsShimV2);
@@ -183,17 +171,17 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testCheckpointingRevertsSession() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device doesn't support fs checkpointing", mHostUtils.isCheckpointSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.isApexUpdateSupported());
+ assumeTrue("Device doesn't support fs checkpointing", supportsFsCheckpointing());
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ File apexFile = mUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
ITestDevice device = getDevice();
assertThat(device.setProperty("persist.debug.trigger_reboot_after_activation",
"com.android.apex.cts.shim@2.apex")).isTrue();
assertThat(device.setProperty("persist.debug.trigger_reboot_twice_after_activation",
"1")).isTrue();
- String error = mHostUtils.installStagedPackage(apexFile);
+ String error = device.installPackage(apexFile, false, "--wait");
assertThat(error).isNull();
String sessionIdToCheck = device.executeShellCommand("pm get-stagedsessions --only-ready "
@@ -207,8 +195,12 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
ApexInfo ctsShimV1 = new ApexInfo("com.android.apex.cts.shim", 1L);
ApexInfo ctsShimV2 = new ApexInfo("com.android.apex.cts.shim", 2L);
- String stagedSessionInfo = getStagedSession(sessionIdToCheck);
- assertThat(stagedSessionInfo).contains("isFailed = true");
+ String stagedSessionsInfo = device.executeShellCommand("pm get-stagedsessions");
+ for (String line: stagedSessionsInfo.split("[\\r\\n]+")) {
+ if (line.contains(sessionIdToCheck)) {
+ assertThat(line).contains("isFailed = true");
+ }
+ }
Set<ApexInfo> activatedApexes = device.getActiveApexes();
assertThat(activatedApexes).contains(ctsShimV1);
@@ -221,17 +213,17 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testRebootingOnceDoesNotRevertSession() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device doesn't support fs checkpointing", mHostUtils.isCheckpointSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.isApexUpdateSupported());
+ assumeTrue("Device doesn't support fs checkpointing", supportsFsCheckpointing());
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ File apexFile = mUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
ITestDevice device = getDevice();
assertThat(device.setProperty("persist.debug.trigger_reboot_after_activation",
"com.android.apex.cts.shim@2.apex")).isTrue();
assertThat(device.setProperty("debug.trigger_reboot_once_after_activation",
"1")).isTrue();
- String error = mHostUtils.installStagedPackage(apexFile);
+ String error = device.installPackage(apexFile, false, "--wait");
assertThat(error).isNull();
String sessionIdToCheck = device.executeShellCommand("pm get-stagedsessions --only-ready "
@@ -245,8 +237,12 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
ApexInfo ctsShimV1 = new ApexInfo("com.android.apex.cts.shim", 1L);
ApexInfo ctsShimV2 = new ApexInfo("com.android.apex.cts.shim", 2L);
- String stagedSessionInfo = getStagedSession(sessionIdToCheck);
- assertThat(stagedSessionInfo).contains("isApplied = true");
+ String stagedSessionsInfo = device.executeShellCommand("pm get-stagedsessions");
+ for (String line: stagedSessionsInfo.split("[\\r\\n]+")) {
+ if (line.contains(sessionIdToCheck)) {
+ assertThat(line).contains("isApplied = true");
+ }
+ }
Set<ApexInfo> activatedApexes = device.getActiveApexes();
assertThat(activatedApexes).contains(ctsShimV2);
@@ -261,7 +257,7 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testApexdDoesNotBootLoopDeviceIfThereIsNothingToRevert() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.isApexUpdateSupported());
// On next boot trigger setprop sys.init.updatable_crashing 1, which will trigger a
// revert mechanism in apexd. Since there is nothing to revert, this should be a no-op
// and device will boot successfully.
@@ -280,16 +276,16 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testFailingUserspaceReboot_doesNotRevertUpdate() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.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());
+ assumeTrue("Device doesn't support fs checkpointing", supportsFsCheckpointing());
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ File apexFile = mUtils.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);
+ String error = getDevice().installPackage(apexFile, false, "--wait");
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
@@ -309,17 +305,17 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testUserspaceRebootFailedShutdownSequence_doesNotRevertUpdate() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.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());
+ assumeTrue("Device doesn't support fs checkpointing", supportsFsCheckpointing());
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ File apexFile = mUtils.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);
+ String error = getDevice().installPackage(apexFile, false, "--wait");
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
@@ -342,17 +338,17 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testUserspaceRebootFailedRemount_revertsUpdate() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.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());
+ assumeTrue("Device doesn't support fs checkpointing", supportsFsCheckpointing());
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ File apexFile = mUtils.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);
+ String error = getDevice().installPackage(apexFile, false, "--wait");
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
@@ -371,14 +367,14 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
*/
@Test
public void testBootCompletedCleanupHappensEvenWhenThereIsCrashingProcess() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mUtils.isApexUpdateSupported());
assumeTrue("Device requires root", getDevice().isAdbRoot());
try {
// On next boot trigger setprop sys.init.updatable_crashing 1, which will trigger a
// revert mechanism in apexd. Since there is nothing to revert, this should be a no-op
// and device will boot successfully.
getDevice().setProperty("persist.debug.trigger_updatable_crashing_for_testing", "1");
- assertThat(getDevice().pushFile(mHostUtils.getTestFile("apex.apexd_test_v2.apex"),
+ assertThat(getDevice().pushFile(mUtils.getTestFile("apex.apexd_test_v2.apex"),
"/data/apex/active/apexd_test_v2.apex")).isTrue();
getDevice().reboot();
assertWithMessage("Timed out waiting for device to boot").that(
@@ -390,84 +386,18 @@ public class ApexRollbackTests extends BaseHostJUnit4Test {
ITestDevice.ApexInfo testApex = new ITestDevice.ApexInfo(
"com.android.apex.cts.shim", 2L);
assertThat(activeApexes).doesNotContain(testApex);
- mHostUtils.waitForFileDeleted("/data/apex/active/apexd_test_v2.apex",
+ mUtils.waitForFileDeleted("/data/apex/active/apexd_test_v2.apex",
Duration.ofMinutes(3));
} finally {
getDevice().executeShellV2Command("rm /data/apex/active/apexd_test_v2.apex");
}
}
- /**
- * Test reason for revert is properly logged during boot loops
- */
- @Test
- public void testReasonForRevertIsLoggedDuringBootloop() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- 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: " + 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
- // trigger_watchdog.rc file that arranges for a trigger_watchdog.sh
- // script to be run at boot. The trigger_watchdog.sh script checks if
- // the apex version specified in the property
- // persist.debug.trigger_watchdog.apex is installed. If so,
- // trigger_watchdog.sh repeatedly kills the system server causing a
- // boot loop.
- assertThat(device.setProperty("persist.debug.trigger_watchdog.apex",
- "com.android.apex.cts.shim@2")).isTrue();
- final String error = mHostUtils.installStagedPackage(apexFile);
- assertThat(error).isNull();
-
- final String sessionIdToCheck = device.executeShellCommand("pm get-stagedsessions "
- + "--only-ready --only-parent --only-sessionid").trim();
- assertThat(sessionIdToCheck).isNotEmpty();
-
- // After we reboot the device, we expect the device to go into boot
- // loop from trigger_watchdog.sh. Native watchdog should detect and
- // report the boot loop, causing apexd to roll back to the previous
- // version of the apex and force reboot. When the device comes up
- // after the forced reboot, trigger_watchdog.sh will see the different
- // version of the apex and refrain from forcing a boot loop, so the
- // device will be recovered.
- device.reboot();
-
- final ApexInfo ctsShimV1 = new ApexInfo("com.android.apex.cts.shim", 1L);
- final ApexInfo ctsShimV2 = new ApexInfo("com.android.apex.cts.shim", 2L);
- final Set<ApexInfo> activatedApexes = device.getActiveApexes();
- assertThat(activatedApexes).contains(ctsShimV1);
- assertThat(activatedApexes).doesNotContain(ctsShimV2);
-
- // Assert that a session has failed with the expected reason
- final String stagedSessionString = getStagedSession(sessionIdToCheck);
- assertThat(stagedSessionString).contains("Session reverted due to crashing native process");
- }
- String getStagedSession(String sessionId) throws DeviceNotAvailableException {
- final String[] lines = getDevice().executeShellCommand(
- "pm get-stagedsessions").split("\n");
- for (int i = 0; i < lines.length; i++) {
- if (lines[i].startsWith("sessionId = " + sessionId + ";")) {
- // Join all lines realted to this session
- final StringBuilder result = new StringBuilder(lines[i]);
- for (int j = i + 1; j < lines.length; j++) {
- if (lines[j].startsWith("sessionId = ")) {
- // A new session block has started
- break;
- }
- result.append(lines[j]);
- }
- return result.toString();
- }
- }
- return "";
+ private boolean supportsFsCheckpointing() throws Exception {
+ CommandResult result = getDevice().executeShellV2Command("sm supports-checkpoint");
+ assertWithMessage("Failed to check if fs checkpointing is supported : %s",
+ result.getStderr()).that(result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
+ return "true".equals(result.getStdout().trim());
}
}
diff --git a/tests/src/com/android/tests/apex/ApexdHostTest.java b/tests/src/com/android/tests/apex/ApexdHostTest.java
index 2d72e9fd..fc1fa4be 100644
--- a/tests/src/com/android/tests/apex/ApexdHostTest.java
+++ b/tests/src/com/android/tests/apex/ApexdHostTest.java
@@ -21,27 +21,17 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assume.assumeTrue;
-import android.cts.install.lib.host.InstallUtilsHost;
-
-import com.android.apex.ApexInfo;
-import com.android.apex.XmlParser;
-import com.android.tests.rollback.host.AbandonSessionsRule;
+import com.android.tests.util.ModuleTestUtils;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
-import java.io.FileInputStream;
import java.time.Duration;
-import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
/**
* Host side integration tests for apexd.
@@ -51,36 +41,14 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
private static final String SHIM_APEX_PATH = "/system/apex/com.android.apex.cts.shim.apex";
- private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
-
- @Rule
- public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this);
-
- private boolean mWasAdbRoot = false;
-
- @Before
- public void setUp() throws Exception {
- mHostUtils.uninstallShimApexIfNecessary();
- mWasAdbRoot = getDevice().isAdbRoot();
- if (!mWasAdbRoot) {
- assumeTrue("Device requires root", getDevice().enableAdbRoot());
- }
- }
-
- @After
- public void tearDown() throws Exception {
- mHostUtils.uninstallShimApexIfNecessary();
- if (!mWasAdbRoot) {
- getDevice().disableAdbRoot();
- }
- }
+ private final ModuleTestUtils mTestUtils = new ModuleTestUtils(this);
@Test
public void testOrphanedApexIsNotActivated() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mTestUtils.isApexUpdateSupported());
assumeTrue("Device requires root", getDevice().isAdbRoot());
try {
- assertThat(getDevice().pushFile(mHostUtils.getTestFile("apex.apexd_test_v2.apex"),
+ assertThat(getDevice().pushFile(mTestUtils.getTestFile("apex.apexd_test_v2.apex"),
"/data/apex/active/apexd_test_v2.apex")).isTrue();
getDevice().reboot();
assertWithMessage("Timed out waiting for device to boot").that(
@@ -89,7 +57,7 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
ITestDevice.ApexInfo testApex = new ITestDevice.ApexInfo(
"com.android.apex.test_package", 2L);
assertThat(activeApexes).doesNotContain(testApex);
- mHostUtils.waitForFileDeleted("/data/apex/active/apexd_test_v2.apex",
+ mTestUtils.waitForFileDeleted("/data/apex/active/apexd_test_v2.apex",
Duration.ofMinutes(3));
} finally {
getDevice().executeShellV2Command("rm /data/apex/active/apexd_test_v2.apex");
@@ -97,11 +65,11 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
}
@Test
public void testApexWithoutPbIsNotActivated() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mTestUtils.isApexUpdateSupported());
assumeTrue("Device requires root", getDevice().isAdbRoot());
final String testApexFile = "com.android.apex.cts.shim.v2_no_pb.apex";
try {
- assertThat(getDevice().pushFile(mHostUtils.getTestFile(testApexFile),
+ assertThat(getDevice().pushFile(mTestUtils.getTestFile(testApexFile),
"/data/apex/active/" + testApexFile)).isTrue();
getDevice().reboot();
assertWithMessage("Timed out waiting for device to boot").that(
@@ -110,7 +78,7 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
ITestDevice.ApexInfo testApex = new ITestDevice.ApexInfo(
"com.android.apex.cts.shim", 2L);
assertThat(activeApexes).doesNotContain(testApex);
- mHostUtils.waitForFileDeleted("/data/apex/active/" + testApexFile,
+ mTestUtils.waitForFileDeleted("/data/apex/active/" + testApexFile,
Duration.ofMinutes(3));
} finally {
getDevice().executeShellV2Command("rm /data/apex/active/" + testApexFile);
@@ -119,14 +87,14 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
@Test
public void testRemountApex() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mTestUtils.isApexUpdateSupported());
assumeTrue("Device requires root", getDevice().isAdbRoot());
final File oldFile = getDevice().pullFile(SHIM_APEX_PATH);
try {
getDevice().remountSystemWritable();
// In case remount requires a reboot, wait for boot to complete.
getDevice().waitForBootComplete(Duration.ofMinutes(3).toMillis());
- final File newFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
+ final File newFile = mTestUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
// Stop framework
getDevice().executeShellV2Command("stop");
// Push new shim APEX. This simulates adb sync.
@@ -150,7 +118,7 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
@Test
public void testApexWithoutPbIsNotActivated_ProductPartitionHasOlderVersion()
throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mTestUtils.isApexUpdateSupported());
assumeTrue("Device requires root", getDevice().isAdbRoot());
try {
@@ -159,10 +127,10 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
assertWithMessage("Timed out waiting for device to boot").that(
getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
- final File v1 = mHostUtils.getTestFile("apex.apexd_test.apex");
+ final File v1 = mTestUtils.getTestFile("apex.apexd_test.apex");
getDevice().pushFile(v1, "/product/apex/apex.apexd_test.apex");
- final File v2_no_pb = mHostUtils.getTestFile("apex.apexd_test_v2_no_pb.apex");
+ final File v2_no_pb = mTestUtils.getTestFile("apex.apexd_test_v2_no_pb.apex");
getDevice().pushFile(v2_no_pb, "/data/apex/active/apex.apexd_test_v2_no_pb.apex");
getDevice().reboot();
@@ -176,7 +144,7 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
"com.android.apex.test_package", 2L));
// v2_no_pb should be deleted
- mHostUtils.waitForFileDeleted("/data/apex/active/apex.apexd_test_v2_no_pb.apex",
+ mTestUtils.waitForFileDeleted("/data/apex/active/apex.apexd_test_v2_no_pb.apex",
Duration.ofMinutes(3));
} finally {
getDevice().remountSystemWritable();
@@ -191,7 +159,7 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
@Test
public void testApexWithoutPbIsNotActivated_ProductPartitionHasNewerVersion()
throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support updating APEX", mTestUtils.isApexUpdateSupported());
assumeTrue("Device requires root", getDevice().isAdbRoot());
try {
@@ -200,10 +168,10 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
assertWithMessage("Timed out waiting for device to boot").that(
getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
- final File v3 = mHostUtils.getTestFile("apex.apexd_test_v3.apex");
+ final File v3 = mTestUtils.getTestFile("apex.apexd_test_v3.apex");
getDevice().pushFile(v3, "/product/apex/apex.apexd_test_v3.apex");
- final File v2_no_pb = mHostUtils.getTestFile("apex.apexd_test_v2_no_pb.apex");
+ final File v2_no_pb = mTestUtils.getTestFile("apex.apexd_test_v2_no_pb.apex");
getDevice().pushFile(v2_no_pb, "/data/apex/active/apex.apexd_test_v2_no_pb.apex");
getDevice().reboot();
@@ -217,7 +185,7 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
"com.android.apex.test_package", 2L));
// v2_no_pb should be deleted
- mHostUtils.waitForFileDeleted("/data/apex/active/apex.apexd_test_v2_no_pb.apex",
+ mTestUtils.waitForFileDeleted("/data/apex/active/apex.apexd_test_v2_no_pb.apex",
Duration.ofMinutes(3));
} finally {
getDevice().remountSystemWritable();
@@ -228,115 +196,4 @@ public class ApexdHostTest extends BaseHostJUnit4Test {
getDevice().executeShellV2Command("rm /data/apex/active/apex.apexd_test_v2_no_pb.apex");
}
}
-
- @Test
- public void testApexInfoListIsValid() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- try (FileInputStream fis = new FileInputStream(
- getDevice().pullFile("/apex/apex-info-list.xml"))) {
- // #1 Data got from apexd via binder
- Set<ITestDevice.ApexInfo> fromApexd = getDevice().getActiveApexes();
- // #2 Data got from the xml file (key is the path)
- Map<String, ApexInfo> fromXml = XmlParser.readApexInfoList(fis).getApexInfo().stream()
- .collect(Collectors.toMap(ApexInfo::getModulePath, ai -> ai));
-
- // Make sure that all items in #1 are also in #2 and they are identical
- for (ITestDevice.ApexInfo ai : fromApexd) {
- ApexInfo apexFromXml = fromXml.get(ai.sourceDir);
- assertWithMessage("APEX (" + ai.toString() + ") is not found in the list")
- .that(apexFromXml).isNotNull();
- assertWithMessage("Version mismatch for APEX (" + ai.toString() + ")")
- .that(ai.versionCode).isEqualTo(apexFromXml.getVersionCode());
- assertWithMessage("APEX (" + ai.toString() + ") is not active")
- .that(apexFromXml.getIsActive()).isTrue();
- }
- }
- }
-
- /**
- * Test to verify that the state of a staged session does not change if apexd is stopped and
- * restarted while a session is staged.
- */
- @Test
- public void testApexSessionStateUnchangedBeforeReboot() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- File apexFile = mHostUtils.getTestFile("com.android.apex.cts.shim.v2.apex");
- String error = mHostUtils.installStagedPackage(apexFile);
- assertThat(error).isNull();
- String sessionId = getDevice().executeShellCommand(
- "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim();
- assertThat(sessionId).isNotEmpty();
- String sessionStateCmd = "cmd -w apexservice getStagedSessionInfo " + sessionId;
- String initialState = getDevice().executeShellV2Command(sessionStateCmd).getStdout();
- assertThat(initialState).isNotEmpty();
-
- // Kill apexd. This means apexd will perform its start logic when the second install
- // is staged.
- getDevice().executeShellV2Command("kill `pidof apexd`");
-
- // Verify that the session state remains consistent after apexd has restarted.
- String updatedState = getDevice().executeShellV2Command(sessionStateCmd).getStdout();
- assertThat(updatedState).isEqualTo(initialState);
- }
-
- /**
- * Verifies that content of {@code /data/apex/sessions/} is migrated to the {@code
- * /metadata/apex/sessions}.
- */
- @Test
- public void testSessionsDirMigrationToMetadata() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- try {
- getDevice().executeShellV2Command("mkdir -p /data/apex/sessions/1543");
- File file = File.createTempFile("foo", "bar");
- getDevice().pushFile(file, "/data/apex/sessions/1543/file");
-
- // During boot sequence apexd will move /data/apex/sessions/1543/file to
- // /metadata/apex/sessions/1543/file.
- getDevice().reboot();
- assertWithMessage("Timed out waiting for device to boot").that(
- getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
-
- assertThat(getDevice().doesFileExist("/metadata/apex/sessions/1543/file")).isTrue();
- assertThat(getDevice().doesFileExist("/data/apex/sessions/1543/file")).isFalse();
- } finally {
- getDevice().executeShellV2Command("rm -R /data/apex/sessions/1543");
- getDevice().executeShellV2Command("rm -R /metadata/apex/sessions/1543");
- }
- }
-
- @Test
- public void testFailsToActivateApexOnDataFallbacksToPreInstalled() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- try {
- final File file =
- mHostUtils.getTestFile("com.android.apex.cts.shim.v2_additional_file.apex");
- getDevice().pushFile(file, "/data/apex/active/com.android.apex.cts.shim@2.apex");
-
- getDevice().reboot();
- assertWithMessage("Timed out waiting for device to boot").that(
- getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
-
- // After reboot pre-installed version of shim apex should be activated, and corrupted
- // version on /data should be deleted.
- final Set<ITestDevice.ApexInfo> activeApexes = getDevice().getActiveApexes();
- ITestDevice.ApexInfo testApex = new ITestDevice.ApexInfo(
- "com.android.apex.cts.shim", 1L);
- assertThat(activeApexes).contains(testApex);
- assertThat(
- getDevice()
- .doesFileExist("/data/apex/active/com.android.apex.cts.shim@2.apex"))
- .isFalse();
- } finally {
- getDevice().deleteFile("/data/apex/active/com.android.apex.cts.shim@2.apex");
- }
- }
}
diff --git a/tests/src/com/android/tests/apex/CellbroadcastHostTest.java b/tests/src/com/android/tests/apex/CellbroadcastHostTest.java
new file mode 100644
index 00000000..97230422
--- /dev/null
+++ b/tests/src/com/android/tests/apex/CellbroadcastHostTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.apex;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CellbroadcastHostTest extends ApexE2EBaseHostTest {
+} \ No newline at end of file
diff --git a/apexd/aidl/android/apex/CompressedApexInfo.aidl b/tests/src/com/android/tests/apex/ConscryptHostTest.java
index 48015bd0..01cb840e 100644
--- a/apexd/aidl/android/apex/CompressedApexInfo.aidl
+++ b/tests/src/com/android/tests/apex/ConscryptHostTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,10 +14,15 @@
* limitations under the License.
*/
-package android.apex;
+package com.android.tests.apex;
-parcelable CompressedApexInfo {
- @utf8InCpp String moduleName;
- long versionCode;
- long decompressedSize;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class ConscryptHostTest extends ApexE2EBaseHostTest {
}
diff --git a/tests/testdata/sharedlibs/build/sharedlibstest.cpp b/tests/src/com/android/tests/apex/ExtServicesHostTest.java
index bac580ef..ff5d6942 100644
--- a/tests/testdata/sharedlibs/build/sharedlibstest.cpp
+++ b/tests/src/com/android/tests/apex/ExtServicesHostTest.java
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-#include "sharedlibstest.h"
+package com.android.tests.apex;
-#include <string>
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-namespace sharedlibstest {
+import org.junit.runner.RunWith;
-// This parameter gets modified by the build_artifacts.sh script.
-#define FINGERPRINT "VERSION_XXX"
-
-std::string getSharedLibsTestFingerprint() {
- return std::string("SHARED_LIB_") + FINGERPRINT;
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class ExtServicesHostTest extends ApexE2EBaseHostTest {
}
-
-} // namespace sharedlibstest
diff --git a/apexd/aidl/android/apex/CompressedApexInfoList.aidl b/tests/src/com/android/tests/apex/IpSecHostTest.java
index e1620bd1..765f4355 100644
--- a/apexd/aidl/android/apex/CompressedApexInfoList.aidl
+++ b/tests/src/com/android/tests/apex/IpSecHostTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-package android.apex;
+package com.android.tests.apex;
-import android.apex.CompressedApexInfo;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-parcelable CompressedApexInfoList {
- CompressedApexInfo[] apexInfos;
+import org.junit.runner.RunWith;
+
+/** Test to check if Apex can be staged, activated and uninstalled successfully. */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class IpSecHostTest extends ApexE2EBaseHostTest {
}
diff --git a/tests/src/com/android/tests/apex/MediaProviderHostTest.java b/tests/src/com/android/tests/apex/MediaProviderHostTest.java
new file mode 100644
index 00000000..4fc72251
--- /dev/null
+++ b/tests/src/com/android/tests/apex/MediaProviderHostTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.apex;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class MediaProviderHostTest extends ApexE2EBaseHostTest {
+}
diff --git a/tests/src/com/android/tests/apex/NeuralNetworksHostTest.java b/tests/src/com/android/tests/apex/NeuralNetworksHostTest.java
new file mode 100644
index 00000000..1effbe2a
--- /dev/null
+++ b/tests/src/com/android/tests/apex/NeuralNetworksHostTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.apex;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class NeuralNetworksHostTest extends ApexE2EBaseHostTest {
+}
diff --git a/tests/src/com/android/tests/apex/PermissionHostTest.java b/tests/src/com/android/tests/apex/PermissionHostTest.java
new file mode 100644
index 00000000..c673ade9
--- /dev/null
+++ b/tests/src/com/android/tests/apex/PermissionHostTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.apex;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@Ignore("b/152717947")
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class PermissionHostTest extends ApexE2EBaseHostTest {
+}
diff --git a/tests/src/com/android/tests/apex/SharedLibsApexTest.java b/tests/src/com/android/tests/apex/SharedLibsApexTest.java
deleted file mode 100644
index fdeac2c3..00000000
--- a/tests/src/com/android/tests/apex/SharedLibsApexTest.java
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.apex;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeTrue;
-
-import android.cts.install.lib.host.InstallUtilsHost;
-
-import com.android.compatibility.common.util.CpuFeatures;
-import com.android.internal.util.test.SystemPreparer;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-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 SharedLibsApexTest extends BaseHostJUnit4Test {
-
- 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);
-
- enum ApexName {
- FOO,
- BAR,
- BAZ,
- PONY,
- SHAREDLIBS,
- SHAREDLIBS_SECONDARY
- }
-
- enum ApexVersion {
- ONE,
- TWO
- }
-
- enum ApexType {
- DEFAULT,
- STRIPPED
- }
-
- enum SharedLibsVersion {
- X,
- Y,
- Z
- }
-
- /**
- * Utility function to generate test apex names in the form e.g.:
- * "com.android.apex.test.bar.v1.libvX.apex"
- */
- private String getTestApex(ApexName apexName, ApexType apexType, ApexVersion apexVersion,
- SharedLibsVersion sharedLibsVersion) {
- StringBuilder ret = new StringBuilder();
- ret.append("com.android.apex.test.");
- switch(apexName) {
- case FOO:
- ret.append("foo");
- break;
- case BAR:
- ret.append("bar");
- break;
- case BAZ:
- ret.append("baz");
- break;
- case PONY:
- ret.append("pony");
- break;
- case SHAREDLIBS:
- ret.append("sharedlibs_generated");
- break;
- case SHAREDLIBS_SECONDARY:
- ret.append("sharedlibs_secondary_generated");
- break;
- }
-
- switch(apexType) {
- case STRIPPED:
- ret.append("_stripped");
- break;
- case DEFAULT:
- break;
- }
-
- switch(apexVersion) {
- case ONE:
- ret.append(".v1");
- break;
- case TWO:
- ret.append(".v2");
- break;
- }
-
- switch(sharedLibsVersion) {
- case X:
- ret.append(".libvX.apex");
- break;
- case Y:
- ret.append(".libvY.apex");
- break;
- case Z:
- ret.append(".libvZ.apex");
- break;
- }
-
- return ret.toString();
- }
-
- /**
- * Utility function to generate the file name of an installed package as per
- * apexd convention e.g.: "com.android.apex.test.bar@1.apex"
- */
- private String getInstalledApexFileName(ApexName apexName, ApexVersion apexVersion) {
- StringBuilder ret = new StringBuilder();
- ret.append("com.android.apex.test.");
- switch(apexName) {
- case FOO:
- ret.append("foo");
- break;
- case BAR:
- ret.append("bar");
- break;
- case BAZ:
- ret.append("baz");
- break;
- case PONY:
- ret.append("pony");
- break;
- case SHAREDLIBS:
- ret.append("sharedlibs");
- break;
- case SHAREDLIBS_SECONDARY:
- ret.append("sharedlibs_secondary");
- break;
- }
- ret.append("@");
- switch(apexVersion) {
- case ONE:
- ret.append("1");
- break;
- case TWO:
- ret.append("2");
- break;
- }
- ret.append(".apex");
- return ret.toString();
- }
-
- /**
- * Tests basic functionality of two apex packages being force-installed and the C++ binaries
- * contained in them being executed correctly.
- */
- @Test
- public void testInstallAndRunDefaultApexs() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- for (String apex : new String[]{
- getTestApex(ApexName.BAR, ApexType.DEFAULT, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.FOO, ApexType.DEFAULT, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.PONY, ApexType.DEFAULT, ApexVersion.ONE, SharedLibsVersion.Z),
- }) {
- mPreparer.pushResourceFile(apex,
- "/system/apex/" + apex);
- }
- mPreparer.reboot();
-
- getDevice().disableAdbRoot();
- String runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- }
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.pony/bin/pony_test");
- assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z");
-
- mPreparer.stageMultiplePackages(
- new String[]{
- getTestApex(ApexName.BAR, ApexType.DEFAULT, ApexVersion.TWO, SharedLibsVersion.Y),
- getTestApex(ApexName.FOO, ApexType.DEFAULT, ApexVersion.TWO, SharedLibsVersion.Y),
- },
- new String[] {
- "com.android.apex.test.bar",
- "com.android.apex.test.foo",
- }).reboot();
-
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- }
- }
-
- /**
- * Tests functionality of shared libraries apex: installs two apexs "stripped" of libc++.so and
- * one apex containing it and verifies that C++ binaries can run.
- */
- @Test
- public void testInstallAndRunOptimizedApexs() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- // Base case:
- //
- // Pre-installed on /system:
- // package bar version 1 using library version X
- // package foo version 1 using library version X
- // package sharedlibs version 1 exporting library version X
- //
- // package pony version 1 using library version Z
- // package sharedlibs_secondary version 1 exporting library version Z
-
- for (String apex : new String[]{
- getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.PONY, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.Z),
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.X),
- getTestApex(ApexName.SHAREDLIBS_SECONDARY, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.Z),
- }) {
- mPreparer.pushResourceFile(apex,
- "/system/apex/" + apex);
- }
- mPreparer.reboot();
-
- getDevice().disableAdbRoot();
- String runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- }
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.pony/bin/pony_test");
- assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z");
-
- // Edge case: sharedlibs updated with a same version apex.
- //
- // Updated packages (installed on /data/apex/active):
- // package sharedlibs version 1 exporting library version X <-- new
- // package sharedlibs_secondary version 1 exporting library version Z <-- new
- //
- // Pre-installed:
- // package bar version 1 using library version X
- // package foo version 1 using library version X
- // (inactive) package sharedlibs version 1 exporting library version X
- //
- // package pony version 1 using library version Z
- // (inactive) package sharedlibs_secondary version 1 exporting library version Z
-
- mPreparer.stageMultiplePackages(
- new String[]{
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.X),
- getTestApex(ApexName.SHAREDLIBS_SECONDARY, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.Z),
- },
- new String[]{
- "com.android.apex.test.sharedlibs",
- "com.android.apex.test.sharedlibs_secondary",
- }).reboot();
-
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- }
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.pony/bin/pony_test");
- assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z");
-
- // Updated packages (installed on /data/apex/active):
- // package bar version 2 using library version Y <-- new
- // package foo version 2 using library version Y <-- new
- // package sharedlibs version 2 exporting library version Y <-- new
- // package sharedlibs_secondary version 1 exporting library version Z
- //
- // Pre-installed:
- // (inactive) package bar version 1 using library version X
- // (inactive) package foo version 1 using library version X
- // package sharedlibs version 1 exporting library version X
- //
- // package pony version 1 using library version Z
- // (inactive) package sharedlibs_secondary version 1 exporting library version Z
-
- mPreparer.stageMultiplePackages(
- new String[]{
- getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y),
- getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y),
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.TWO,
- SharedLibsVersion.Y),
- },
- new String[]{
- "com.android.apex.test.bar",
- "com.android.apex.test.foo",
- "com.android.apex.test.sharedlibs",
- }).reboot();
-
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- }
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.pony/bin/pony_test");
- assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z");
-
- // Assume that an OTA now adds a package baz on /system needing libraries installed on
- // /system:
- //
- // Updated packages (installed on /data/apex/active):
- // package bar version 2 using library version Y
- // package foo version 2 using library version Y
- // package sharedlibs version 2 exporting library version Y
- //
- // Pre-installed:
- // (inactive) package bar version 1 using library version X
- // package baz version 1 using library version X <-- new
- // (inactive) package foo version 1 using library version X
- // package sharedlibs version 1 exporting library version X
- // package pony version 1 using library version Z
- // package sharedlibs_secondary version 1 exporting library version Z
-
- String baz_apex =
- getTestApex(ApexName.BAZ, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X);
- mPreparer.pushResourceFile(baz_apex, "/system/apex/" + baz_apex);
- mPreparer.reboot();
-
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- }
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.baz/bin/baz_test");
- assertThat(runAsResult).isEqualTo("BAZ_VERSION_1 SHARED_LIB_VERSION_X");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.pony/bin/pony_test");
- assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z");
- }
-
- /**
- * Tests that when a shared library apex is updated via OTA the previously
- * downloaded version is remoted.
- */
- @Test
- public void testHigherVersionOnSystemDeletesDataVersion() throws Exception {
- assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported());
- assumeTrue("Device requires root", getDevice().isAdbRoot());
-
- // Base case:
- //
- // Pre-installed on /system:
- // package bar version 1 using library version X
- // package foo version 1 using library version X
- // package sharedlibs version 1 exporting library version X
- for (String apex : new String[]{
- getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.X),
- }) {
- mPreparer.pushResourceFile(apex,
- "/system/apex/" + apex);
- }
- mPreparer.reboot();
- String runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- }
-
- // Same-grade case:
- //
- // Pre-installed on /system:
- // package bar version 1 using library version X
- // package foo version 1 using library version X
- // package sharedlibs version 1 exporting library version X
- // Updated packages (installed on /data/apex/active):
- // package bar version 1 using library version X
- // package foo version 1 using library version X
- // package sharedlibs version 1 exporting library version X
- mPreparer.stageMultiplePackages(
- new String[]{
- getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.X),
- },
- new String[]{
- "com.android.apex.test.bar",
- "com.android.apex.test.foo",
- "com.android.apex.test.sharedlibs",
- }).reboot();
-
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X");
- }
-
- // Simulate OTA upgrading pre-installed modules:
- //
- // Pre-installed on /system:
- // package bar version 2 using library version Y
- // package foo version 2 using library version Y
- // package sharedlibs version 2 exporting library version Y
- //
- // Updated packages (installed on /data/apex/active):
- // package bar version 1 using library version X (deleted)
- // package foo version 1 using library version X (deleted)
- // package sharedlibs version 1 exporting library version X (deleted)
- //
- for (String apex : new String[]{
- getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X),
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE,
- SharedLibsVersion.X),
- }) {
- mPreparer.deleteFile("/system/apex/" + apex);
- }
- for (String apex : new String[]{
- getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y),
- getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y),
- getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.TWO,
- SharedLibsVersion.Y),
- }) {
- mPreparer.pushResourceFile(apex,
- "/system/apex/" + apex);
- }
-
- // Check that files in /data are deleted on first boot.
- assertThat(getDevice().doesFileExist("/data/apex/active/"
- + getInstalledApexFileName(ApexName.BAR, ApexVersion.ONE))).isTrue();
- assertThat(getDevice().doesFileExist("/data/apex/active/"
- + getInstalledApexFileName(ApexName.FOO, ApexVersion.ONE))).isTrue();
- assertThat(getDevice().doesFileExist("/data/apex/active/"
- + getInstalledApexFileName(ApexName.SHAREDLIBS, ApexVersion.ONE))).isTrue();
- mPreparer.reboot();
- 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(
- "/apex/com.android.apex.test.foo/bin/foo_test");
- assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y");
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test32");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) {
- runAsResult = getDevice().executeShellCommand(
- "/apex/com.android.apex.test.bar/bin/bar_test64");
- assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y");
- }
- }
-}
diff --git a/tests/src/com/android/tests/apex/StatsdHostTest.java b/tests/src/com/android/tests/apex/StatsdHostTest.java
new file mode 100644
index 00000000..4ad3bb8d
--- /dev/null
+++ b/tests/src/com/android/tests/apex/StatsdHostTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.apex;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+@Ignore // TODO(b/150452752): unignore when test is fixed.
+public class StatsdHostTest extends ApexE2EBaseHostTest {
+}
diff --git a/tests/src/com/android/tests/apex/WifiHostTest.java b/tests/src/com/android/tests/apex/WifiHostTest.java
new file mode 100644
index 00000000..7fd85289
--- /dev/null
+++ b/tests/src/com/android/tests/apex/WifiHostTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.apex;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+
+/**
+ * Test to check if Apex can be staged, activated and uninstalled successfully.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class WifiHostTest extends ApexE2EBaseHostTest {
+ // TODO(b/146163587): Add more checks to verify apex installation.
+}
diff --git a/tests/src/com/android/tests/apex/host/ApexCompressionTests.java b/tests/src/com/android/tests/apex/host/ApexCompressionTests.java
deleted file mode 100644
index a09ca60d..00000000
--- a/tests/src/com/android/tests/apex/host/ApexCompressionTests.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.apex.host;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
-import android.cts.install.lib.host.InstallUtilsHost;
-import android.platform.test.annotations.LargeTest;
-
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.time.Duration;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-/**
- * Test for platform support for Apex Compression feature
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class ApexCompressionTests extends BaseHostJUnit4Test {
- private static final String COMPRESSED_APEX_PACKAGE_NAME = "com.android.apex.compressed";
- private static final String ORIGINAL_APEX_FILE_NAME =
- COMPRESSED_APEX_PACKAGE_NAME + ".v1_original.apex";
- private static final String DECOMPRESSED_DIR_PATH = "/data/apex/decompressed/";
- private static final String APEX_ACTIVE_DIR = "/data/apex/active/";
- private static final String OTA_RESERVED_DIR = "/data/apex/ota_reserved/";
- private static final String DECOMPRESSED_APEX_SUFFIX = ".decompressed.apex";
-
- private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
- private boolean mWasAdbRoot = false;
-
- @Before
- public void setUp() throws Exception {
- mWasAdbRoot = getDevice().isAdbRoot();
- if (!mWasAdbRoot) {
- assumeTrue("Requires root", getDevice().enableAdbRoot());
- }
- deleteFiles("/system/apex/" + COMPRESSED_APEX_PACKAGE_NAME + "*apex",
- APEX_ACTIVE_DIR + COMPRESSED_APEX_PACKAGE_NAME + "*apex",
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "*apex",
- OTA_RESERVED_DIR + "*");
- }
-
- @After
- public void tearDown() throws Exception {
- if (!mWasAdbRoot) {
- getDevice().disableAdbRoot();
- }
- deleteFiles("/system/apex/" + COMPRESSED_APEX_PACKAGE_NAME + "*apex",
- APEX_ACTIVE_DIR + COMPRESSED_APEX_PACKAGE_NAME + "*apex",
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "*apex",
- OTA_RESERVED_DIR + "*");
- }
-
- /**
- * 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 {
- assertTrue(runDeviceTests("com.android.tests.apex.app",
- "com.android.tests.apex.app.ApexCompressionTests",
- phase));
- }
-
- /**
- * Deletes files and reboots the device if necessary.
- * @param files the paths of files which might contain wildcards
- */
- private void deleteFiles(String... files) throws Exception {
- boolean found = false;
- for (String file : files) {
- CommandResult result = getDevice().executeShellV2Command("ls " + file);
- if (result.getStatus() == CommandStatus.SUCCESS) {
- found = true;
- break;
- }
- }
-
- if (found) {
- getDevice().remountSystemWritable();
- for (String file : files) {
- getDevice().executeShellCommand("rm -rf " + file);
- }
- getDevice().reboot();
- }
- }
-
- private void pushTestApex(final String fileName) throws Exception {
- final File apex = mHostUtils.getTestFile(fileName);
- getDevice().remountSystemWritable();
- assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName));
- getDevice().reboot();
- }
-
- private List<String> getFilesInDir(String baseDir) throws DeviceNotAvailableException {
- return getDevice().getFileEntry(baseDir).getChildren(false)
- .stream().map(entry -> entry.getName())
- .collect(Collectors.toList());
- }
-
- /**
- * Returns the active apex info as optional.
- */
- private Optional<ITestDevice.ApexInfo> getActiveApexInfo(String packageName)
- throws DeviceNotAvailableException {
- return getDevice().getActiveApexes().stream().filter(
- apex -> apex.name.equals(packageName)).findAny();
- }
-
- @Test
- @LargeTest
- public void testDecompressedApexIsConsideredFactory() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- runPhase("testDecompressedApexIsConsideredFactory");
- }
-
- @Test
- @LargeTest
- public void testCompressedApexIsDecompressedAndActivated() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
-
- // Ensure that compressed APEX was decompressed in DECOMPRESSED_DIR_PATH
- List<String> files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
-
- // Match the decompressed apex with original byte for byte
- final File originalApex = mHostUtils.getTestFile(ORIGINAL_APEX_FILE_NAME);
- final byte[] originalApexFileBytes = Files.readAllBytes(Paths.get(originalApex.toURI()));
- final File decompressedFile = getDevice().pullFile(
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "@1"
- + DECOMPRESSED_APEX_SUFFIX);
- final byte[] decompressedFileBytes =
- Files.readAllBytes(Paths.get(decompressedFile.toURI()));
- assertThat(decompressedFileBytes).isEqualTo(originalApexFileBytes);
-
- // The decompressed APEX should note be hard linked to APEX_ACTIVE_DIR
- files = getFilesInDir(APEX_ACTIVE_DIR);
- assertThat(files).doesNotContain(
- COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- }
-
- @Test
- @LargeTest
- public void testDecompressedApexSurvivesReboot() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
-
- // Ensure that compressed APEX was activated from DECOMPRESSED_DIR_PATH
- List<String> files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- final File decompressedFile = getDevice().pullFile(
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "@1"
- + DECOMPRESSED_APEX_SUFFIX);
- final byte[] decompressedFileBytes =
- Files.readAllBytes(Paths.get(decompressedFile.toURI()));
-
- getDevice().reboot();
-
- // Ensure it gets activated again on reboot
- files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- final File decompressedFileAfterReboot = getDevice().pullFile(
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "@1"
- + DECOMPRESSED_APEX_SUFFIX);
- final byte[] decompressedFileBytesAfterReboot =
- Files.readAllBytes(Paths.get(decompressedFileAfterReboot.toURI()));
- assertThat(decompressedFileBytes).isEqualTo(decompressedFileBytesAfterReboot);
- }
-
- @Test
- @LargeTest
- public void testDecompressionDoesNotHappenOnEveryReboot() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
-
- final String decompressedApexFilePath = DECOMPRESSED_DIR_PATH
- + COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX;
- String lastModifiedTime1 =
- getDevice().executeShellCommand("stat -c %Y " + decompressedApexFilePath);
-
- getDevice().reboot();
- getDevice().waitForDeviceAvailable();
-
- String lastModifiedTime2 =
- getDevice().executeShellCommand("stat -c %Y " + decompressedApexFilePath);
- assertThat(lastModifiedTime1).isEqualTo(lastModifiedTime2);
- }
-
- @Test
- @LargeTest
- public void testHigherVersionOnSystemTriggerDecompression() throws Exception {
- // Install v1 on /system partition
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- // On boot, /data partition will have decompressed v1 APEX in it
- List<String> files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
-
- // Now replace /system APEX with v2
- getDevice().remountSystemWritable();
- getDevice().executeShellCommand("rm -rf /system/apex/"
- + COMPRESSED_APEX_PACKAGE_NAME + "*apex");
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v2.capex");
-
- // Ensure that v2 was decompressed
- files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@2" + DECOMPRESSED_APEX_SUFFIX);
- }
-
-
- @Test
- @LargeTest
- public void testDifferentRootDigestTriggersDecompression() throws Exception {
- // Install v1 on /system partition
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- // On boot, /data partition will have decompressed v1 APEX in it
- List<String> files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- final File decompressedFile = getDevice().pullFile(
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "@1"
- + DECOMPRESSED_APEX_SUFFIX);
- final byte[] decompressedFileBytes =
- Files.readAllBytes(Paths.get(decompressedFile.toURI()));
-
- // Now replace /system APEX with same version but different root digest
- getDevice().remountSystemWritable();
- getDevice().executeShellCommand("rm -rf /system/apex/"
- + COMPRESSED_APEX_PACKAGE_NAME + "*apex");
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1_different_digest.capex");
-
- // Ensure that decompressed APEX is different than before
- files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- final File decompressedFileAfterReboot = getDevice().pullFile(
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "@1"
- + DECOMPRESSED_APEX_SUFFIX);
- final byte[] decompressedFileBytesAfterReboot =
- Files.readAllBytes(Paths.get(decompressedFileAfterReboot.toURI()));
- assertThat(decompressedFileBytes).isNotEqualTo(decompressedFileBytesAfterReboot);
- }
-
- @Test
- @LargeTest
- public void testUnusedDecompressedApexIsCleanedUp_HigherVersion() throws Exception {
- // Install v1 on /system partition
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- // Ensure that compressed APEX was decompressed in DECOMPRESSED_DIR_PATH
- List<String> files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
-
- // Now install an update for that APEX so that decompressed APEX becomes redundant
- runPhase("testUnusedDecompressedApexIsCleanedUp_HigherVersion");
- getDevice().reboot();
-
- // 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
- @LargeTest
- public void testUnusedDecompressedApexIsCleanedUp_SameVersion() throws Exception {
- // Install v1 on /system partition
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- // Ensure that compressed APEX was decompressed in DECOMPRESSED_DIR_PATH
- List<String> files = getFilesInDir(DECOMPRESSED_DIR_PATH);
- assertThat(files).contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
-
- // Now install an update for that APEX so that decompressed APEX becomes redundant
- runPhase("testUnusedDecompressedApexIsCleanedUp_SameVersion");
- getDevice().reboot();
-
- // 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
- @LargeTest
- public void testReservedSpaceIsNotCleanedOnReboot() throws Exception {
- getDevice().executeShellCommand("touch " + OTA_RESERVED_DIR + "random");
-
- getDevice().reboot();
-
- List<String> files = getFilesInDir(OTA_RESERVED_DIR);
- assertThat(files).hasSize(1);
- assertThat(files).contains("random");
- }
-
- @Test
- @LargeTest
- public void testReservedSpaceIsCleanedUpOnDecompression() throws Exception {
- getDevice().executeShellCommand("touch " + OTA_RESERVED_DIR + "random1");
- getDevice().executeShellCommand("touch " + OTA_RESERVED_DIR + "random2");
-
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
-
- assertThat(getFilesInDir(OTA_RESERVED_DIR)).isEmpty();
- }
-
- @Test
- @LargeTest
- public void testFailsToActivateApexOnDataFallbacksToPreInstalled() throws Exception {
- // Push a data apex that will fail to activate
- final File file =
- mHostUtils.getTestFile("com.android.apex.compressed.v2_manifest_mismatch.apex");
- getDevice().pushFile(file, APEX_ACTIVE_DIR + COMPRESSED_APEX_PACKAGE_NAME + "@2.apex");
- // Push a CAPEX which should act as the fallback
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v2.capex");
- assertWithMessage("Timed out waiting for device to boot").that(
- getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
-
- // After reboot pre-installed version of shim apex should be activated, and corrupted
- // version on /data should be deleted.
- final ITestDevice.ApexInfo activeApex =
- getActiveApexInfo(COMPRESSED_APEX_PACKAGE_NAME).get();
- assertThat(activeApex.versionCode).isEqualTo(2);
- assertThat(getDevice().doesFileExist(
- DECOMPRESSED_DIR_PATH + COMPRESSED_APEX_PACKAGE_NAME + "@2"
- + DECOMPRESSED_APEX_SUFFIX)).isTrue();
- assertThat(getDevice().doesFileExist(
- APEX_ACTIVE_DIR + COMPRESSED_APEX_PACKAGE_NAME + "@2"
- + DECOMPRESSED_APEX_SUFFIX)).isFalse();
- assertThat(getDevice().doesFileExist(
- APEX_ACTIVE_DIR + COMPRESSED_APEX_PACKAGE_NAME + "@2.apex")).isFalse();
- }
-
- @Test
- @LargeTest
- public void testCapexToApexSwitch() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- assertThat(getFilesInDir(DECOMPRESSED_DIR_PATH))
- .contains(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
-
- // Now replace the CAPEX with an uncompressed APEX
- getDevice().remountSystemWritable();
- getDevice().executeShellCommand("rm -rf /system/apex/"
- + COMPRESSED_APEX_PACKAGE_NAME + "*apex");
- pushTestApex(ORIGINAL_APEX_FILE_NAME);
- runPhase("testCapexToApexSwitch");
-
- // Ensure active apex is running from /system
- final ITestDevice.ApexInfo activeApex = getActiveApexInfo(COMPRESSED_APEX_PACKAGE_NAME)
- .orElseThrow(() -> new AssertionError(
- "Can't find " + COMPRESSED_APEX_PACKAGE_NAME));
- assertThat(activeApex.sourceDir).startsWith("/system");
- // Ensure previous decompressed APEX has been cleaned up
- assertThat(getFilesInDir(DECOMPRESSED_DIR_PATH))
- .doesNotContain(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- }
-
- @Test
- @LargeTest
- public void testDecompressedApexVersionAlwaysHasSameVersionAsCapex() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v2.capex");
- // Now replace /system APEX with v1
- getDevice().remountSystemWritable();
- getDevice().executeShellCommand("rm -rf /system/apex/"
- + COMPRESSED_APEX_PACKAGE_NAME + "*apex");
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
- runPhase("testDecompressedApexVersionAlwaysHasSameVersionAsCapex");
- }
-
- @Test
- @LargeTest
- public void testCompressedApexCanBeRolledBack() throws Exception {
- pushTestApex(COMPRESSED_APEX_PACKAGE_NAME + ".v1.capex");
-
- // Now install update with rollback
- runPhase("testCompressedApexCanBeRolledBack_Commit");
- getDevice().reboot();
-
- // Rollback the apex
- runPhase("testCompressedApexCanBeRolledBack_Rollback");
- getDevice().reboot();
-
- runPhase("testCompressedApexCanBeRolledBack_Verify");
- }
-
- @Test
- @LargeTest
- public void testOrphanedDecompressedApexInActiveDirIsIgnored() throws Exception {
- final File apex = mHostUtils.getTestFile(
- COMPRESSED_APEX_PACKAGE_NAME + ".v1_original.apex");
- // Prepare an APEX in active directory with .decompressed.apex suffix.
- // Place the same apex in system too. When booting, system APEX should
- // be mounted while the decomrpessed APEX in active direcotyr should
- // be ignored.
- getDevice().remountSystemWritable();
- assertTrue(getDevice().pushFile(apex,
- APEX_ACTIVE_DIR + COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX));
- assertTrue(getDevice().pushFile(apex,
- "/system/apex/" + COMPRESSED_APEX_PACKAGE_NAME + ".v1.apex"));
- getDevice().reboot();
- // Ensure active apex is running from /system
- final ITestDevice.ApexInfo activeApex = getActiveApexInfo(COMPRESSED_APEX_PACKAGE_NAME)
- .orElseThrow(() -> new AssertionError(
- "Can't find " + COMPRESSED_APEX_PACKAGE_NAME));
- assertThat(activeApex.sourceDir).startsWith("/system");
- // Ensure orphaned decompressed APEX has been cleaned up
- assertThat(getFilesInDir(APEX_ACTIVE_DIR))
- .doesNotContain(COMPRESSED_APEX_PACKAGE_NAME + "@1" + DECOMPRESSED_APEX_SUFFIX);
- }
-}
-
diff --git a/tests/src/com/android/tests/util/ModuleTestUtilsTest.java b/tests/src/com/android/tests/util/ModuleTestUtilsTest.java
new file mode 100644
index 00000000..833974f8
--- /dev/null
+++ b/tests/src/com/android/tests/util/ModuleTestUtilsTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.util;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class ModuleTestUtilsTest extends BaseHostJUnit4Test {
+ private static final String SHIM_V2 = "com.android.apex.cts.shim.v2.apex";
+ private final ModuleTestUtils mUtils = new ModuleTestUtils(this);
+
+ @Before
+ public void setUp() throws Exception {
+ mUtils.abandonActiveStagedSession();
+ mUtils.uninstallShimApexIfNecessary();
+ }
+ /**
+ * Uninstalls any version greater than 1 of shim apex and reboots the device if necessary
+ * to complete the uninstall.
+ */
+ @After
+ public void tearDown() throws Exception {
+ mUtils.abandonActiveStagedSession();
+ mUtils.uninstallShimApexIfNecessary();
+ }
+
+ /**
+ * Unit test for {@link ModuleTestUtils#abandonActiveStagedSession()}
+ */
+ @Test
+ public void testAbandonActiveStagedSession() throws Exception {
+ File apexFile = mUtils.getTestFile(SHIM_V2);
+
+ // Install apex package
+ String installResult = getDevice().installPackage(apexFile, false, "--wait");
+ assertWithMessage(String.format("failed to install apex first time %s. Reason: %s",
+ SHIM_V2, installResult)).that(installResult).isNull();
+
+ // Abandon ready session
+ mUtils.abandonActiveStagedSession();
+
+ // Install apex again
+ installResult = getDevice().installPackage(apexFile, false, "--wait");
+ assertWithMessage(String.format("failed to install apex again %s. Reason: %s",
+ SHIM_V2, installResult)).that(installResult).isNull();
+ }
+}
diff --git a/tests/statsd-e2e-tests.xml b/tests/statsd-e2e-tests.xml
new file mode 100644
index 00000000..b3a270ce
--- /dev/null
+++ b/tests/statsd-e2e-tests.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Configuration for statsd module e2e test cases">
+ <option name="test-suite-tag" value="statsd_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="statsd_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.os.statsd.apex" />
+ </test>
+</configuration>
diff --git a/tests/testdata/init.rc b/tests/testdata/init.rc
index 4e89f444..1c90c830 100644
--- a/tests/testdata/init.rc
+++ b/tests/testdata/init.rc
@@ -6,7 +6,7 @@ service surfaceflinger /apex/com.android.apex.test/bin/surfaceflinger
user system
group graphics drmrpc readproc
onrestart restart zygote
- task_profiles HighPerformance
+ writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
diff --git a/tests/testdata/sharedlibs/README.md b/tests/testdata/sharedlibs/README.md
deleted file mode 100644
index a59686da..00000000
--- a/tests/testdata/sharedlibs/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-### Test artifacts for shared libraries APEX support
-
-This directory contains APEX packages used for testing the platform support for
-moving shared libraries used by binaries within an APEX package into another
-APEX package.
-
-Due to the peculiarity of the build needs, this directory contains prebuilt
-artifacts used by tests. In order to regenerate these artifacts, run from the
-root of the tree:
-
-```shell script
-./system/apex/tests/testdata/sharedlibs/build/build_artifacts.sh
-``` \ No newline at end of file
diff --git a/tests/testdata/sharedlibs/build/Android.bp b/tests/testdata/sharedlibs/build/Android.bp
deleted file mode 100644
index 74b08a25..00000000
--- a/tests/testdata/sharedlibs/build/Android.bp
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "noop",
- srcs: ["noop.cc"],
- shared_libs: [
- "libsharedlibtest",
- ],
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
-
- compile_multilib: "both",
-
- apex_available: [
- "com.android.apex.test.sharedlibs_stub",
- "com.android.apex.test.sharedlibs_secondary_stub",
- ],
-}
-
-python_binary_host {
- name: "shared_libs_repack",
- srcs: [
- "shared_libs_repack.py",
- ],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
- libs: [
- "apex_build_info_proto",
- "apex_manifest_proto",
- ],
- required: [
- "apexer",
- "signapk",
- ],
-}
-
-cc_library_shared {
- name: "libsharedlibtest",
- srcs: [ "sharedlibstest.cpp", ],
-
- local_include_dirs: [
- "include",
- ],
-
- export_include_dirs: [
- "include",
- ],
- apex_available: [
- "com.android.apex.test.bar",
- "com.android.apex.test.baz",
- "com.android.apex.test.foo",
- "com.android.apex.test.pony",
- "com.android.apex.test.sharedlibs_stub",
- "com.android.apex.test.sharedlibs_secondary_stub",
- ],
-}
diff --git a/tests/testdata/sharedlibs/build/build_artifacts.sh b/tests/testdata/sharedlibs/build/build_artifacts.sh
deleted file mode 100755
index 8dbc64f5..00000000
--- a/tests/testdata/sharedlibs/build/build_artifacts.sh
+++ /dev/null
@@ -1,206 +0,0 @@
-#!/bin/bash -e
-
-# List of files required in output. Every other file generated will be skipped.
-OUTFILES=(
- com.android.apex.test.bar_stripped.v1.libvX.apex
- com.android.apex.test.bar_stripped.v2.libvY.apex
- com.android.apex.test.bar.v1.libvX.apex
- com.android.apex.test.bar.v2.libvY.apex
- com.android.apex.test.baz_stripped.v1.libvX.apex
- com.android.apex.test.foo_stripped.v1.libvX.apex
- com.android.apex.test.foo_stripped.v2.libvY.apex
- com.android.apex.test.foo.v1.libvX.apex
- com.android.apex.test.foo.v2.libvY.apex
- com.android.apex.test.pony_stripped.v1.libvZ.apex
- com.android.apex.test.pony.v1.libvZ.apex
- com.android.apex.test.sharedlibs_generated.v1.libvX.apex
- com.android.apex.test.sharedlibs_generated.v2.libvY.apex
- com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
-)
-
-# "apex" type build targets to build.
-APEX_TARGETS=(
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.bar:com.android.apex.test.bar
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.foo:com.android.apex.test.foo
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.pony:com.android.apex.test.pony
-)
-
-# "genrule" type build targets to build, and directory they are built from.
-GENRULE_TARGETS=(
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.bar:com.android.apex.test.bar_stripped
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.baz:com.android.apex.test.baz_stripped
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.foo:com.android.apex.test.foo_stripped
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.pony:com.android.apex.test.pony_stripped
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs:com.android.apex.test.sharedlibs_generated
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary:com.android.apex.test.sharedlibs_secondary_generated
-)
-
-if [ ! -e "build/make/core/Makefile" ]; then
- echo "$0 must be run from the top of the tree"
- exit 1
-fi
-
-OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR)
-DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR)
-TMPDIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var TMPDIR)
-
-manifestdirs=()
-
-for t in "${APEX_TARGETS[@]}" "${GENRULE_TARGETS[@]}"; do
- IFS=: read -a ar <<< "${t}"
- manifestdirs+=( ${ar[0]})
-done
-
-manifestdirs=($(printf "%s\n" "${manifestdirs[@]}" | sort -u))
-
-generated_artifacts=()
-
-archs=(
- arm
- arm64
- x86
- x86_64
-)
-
-apexversions=(
- 1
- 2
-)
-
-libversions=(
- X
- Y
- Z
-)
-
-for arch in "${archs[@]}"; do
- for apexversion in "${apexversions[@]}"; do
- apexfingerprint="VERSION_${apexversion}"
- sed -i "s/#define FINGERPRINT .*/#define FINGERPRINT \"${apexfingerprint}\"/g" \
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.bar/bar_test.cc \
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.baz/baz_test.cc \
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.foo/foo_test.cc \
- system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.pony/pony_test.cc
-
- for d in "${manifestdirs[@]}"; do
- sed -i "s/ \"version\": .*/ \"version\": ${apexversion}/g" \
- ${d}/manifest.json
- done
- for libversion in "${libversions[@]}"; do
- # Check if we need to build this combination of versions.
- found=n
- for t in "${APEX_TARGETS[@]}" "${GENRULE_TARGETS[@]}"; do
- IFS=: read -a ar <<< "${t}"
- outfile=${ar[1]}.v${apexversion}.libv${libversion}.apex
- if printf '%s\n' "${OUTFILES[@]}" | grep -q -F "${outfile}"; then
- found=y
- break
- fi
- done
- if [ "${found}" != "y" ]; then
- # Skipping this combination.
- continue
- fi
-
- echo "Building combination arch: ${arch}, apexversion: ${apexversion}, libversion: ${libversion}"
- libfingerprint="VERSION_${libversion}"
- sed -i "s/#define FINGERPRINT .*/#define FINGERPRINT \"${libfingerprint}\"/g" \
- system/apex/tests/testdata/sharedlibs/build/sharedlibstest.cpp
-
- build/soong/soong_ui.bash \
- --make-mode \
- TARGET_PRODUCT=aosp_${arch} \
- dist sharedlibs_test
-
- for t in "${APEX_TARGETS[@]}" "${GENRULE_TARGETS[@]}"; do
- IFS=: read -a ar <<< "${t}"
- outfile=${ar[1]}.v${apexversion}.libv${libversion}.apex
- if printf '%s\n' "${OUTFILES[@]}" | grep -q -P "^${outfile}\$"; then
- cp -v \
- "${DIST_DIR}"/"${ar[1]}".apex \
- system/apex/tests/testdata/sharedlibs/prebuilts/${arch}/${outfile}
- generated_artifacts+=(system/apex/tests/testdata/sharedlibs/prebuilts/${arch}/${outfile})
- fi
- done
- done
- done
-done
-
-# Generate the Android.bp file for the prebuilts.
-tmpfile=$(mktemp)
-
-cat > "${tmpfile}" << EOF
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file is auto-generated by
-// ./system/apex/tests/testdata/sharedlibs/build/build_artifacts.sh
-// Do NOT edit manually.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-EOF
-
-artifacts_filenames=()
-for artifact in "${generated_artifacts[@]}"; do
- artifacts_filenames+=($(basename ${artifact}))
-done
-
-artifacts_filenames=($(printf '%s\n' "${artifacts_filenames[@]}" | sort -u))
-
-for artifact in "${artifacts_filenames[@]}"; do
- outfile=$(basename "${artifact}")
- # remove .apex suffix
- rulename=${outfile%.apex}
-
- cat >> "${tmpfile}" << EOF
-
-prebuilt_apex {
- name: "${rulename}_prebuilt",
- arch: {
-EOF
-
- for arch in "${archs[@]}"; do
- cat >> "${tmpfile}" << EOF
- ${arch}: {
- src: "${arch}/${outfile}",
- },
-EOF
- done
-
- cat >> "${tmpfile}" << EOF
- },
- filename: "${outfile}",
- installable: false,
-}
-EOF
-done
-
-mv "${tmpfile}" system/apex/tests/testdata/sharedlibs/prebuilts/Android.bp
-
-# Restore the default version string to avoid bogus diffs.
-sed -i "s/#define FINGERPRINT .*/#define FINGERPRINT \"VERSION_XXX\"/g" \
-system/apex/tests/testdata/sharedlibs/build/sharedlibstest.cpp \
-system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.bar/bar_test.cc \
-system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.baz/baz_test.cc \
-system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.foo/foo_test.cc \
-system/apex/tests/testdata/sharedlibs/build/com.android.apex.test.pony/pony_test.cc
-
-for d in "${manifestdirs[@]}"; do
- sed -i "s/ \"version\": .*/ \"version\": 1/g" \
- ${d}/manifest.json
-done
-
-ls -l "${generated_artifacts[@]}"
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/Android.bp b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/Android.bp
deleted file mode 100644
index 0c62e645..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/Android.bp
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.test.bar.key",
- public_key: "com.android.apex.test.bar.avbpubkey",
- private_key: "com.android.apex.test.bar.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.test.bar.certificate",
- certificate: "com.android.apex.test.bar",
-}
-
-apex {
- name: "com.android.apex.test.bar",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test.bar.key",
- installable: false,
- binaries: [ "bar_test" ],
- dist: {
- targets: ["sharedlibs_test"],
- },
- updatable: false,
- compile_multilib: "both",
- multilib: {
- both: {
- binaries: [
- "bar_test",
- ],
- },
- },
-}
-
-cc_binary {
- name: "bar_test",
- srcs: ["bar_test.cc"],
- shared_libs: [
- "libsharedlibtest",
- ],
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
-
- compile_multilib: "both",
-
- apex_available: [ "com.android.apex.test.bar" ],
-}
-
-genrule {
- name: "com.android.apex.test.bar_stripped",
- out: ["com.android.apex.test.bar_stripped.apex"],
- defaults: ["apexer_test_host_tools_list"],
- dist: {
- targets: ["sharedlibs_test"],
- },
- srcs: [
- ":com.android.apex.test.bar",
- "com.android.apex.test.bar.avbpubkey",
- "com.android.apex.test.bar.pem",
- "com.android.apex.test.bar.pk8",
- "com.android.apex.test.bar.x509.pem",
- ],
- tools: [
- "shared_libs_repack",
- ],
- cmd: "$(location shared_libs_repack) " +
- " --mode strip" +
- " --key $(location com.android.apex.test.bar.pem)" +
- " --input $(location :com.android.apex.test.bar)" +
- " --output $(genDir)/com.android.apex.test.bar_stripped.apex" +
- " --pk8key $(location com.android.apex.test.bar.pk8)" +
- " --pubkey $(location com.android.apex.test.bar.avbpubkey)" +
- " --x509key $(location com.android.apex.test.bar.x509.pem)" +
- " --tmpdir $(genDir)",
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/bar_test.cc b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/bar_test.cc
deleted file mode 100644
index 9b397de2..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/bar_test.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <iostream>
-#include <string>
-
-#include "sharedlibstest.h"
-
-// This parameter gets modified by the build_artifacts.sh script.
-#define FINGERPRINT "VERSION_XXX"
-
-int main() {
- std::cout << "BAR_" << FINGERPRINT << " "
- << sharedlibstest::getSharedLibsTestFingerprint();
- return 0;
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.avbpubkey b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.avbpubkey
deleted file mode 100644
index 931a477a..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pem
deleted file mode 100644
index 9363cda9..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEAp/bgVatvywj6wEKD0ldJ+RxfFOv/67norL43z55gd/K/u1W4
-GoFHm0e5T1PV0j5zMi7EraIWy5g9eTmtU9DTwJoIKHw/agrVimxBsd5Los/zHAGJ
-JoRy5Wo7cenpp2QpNzfY3HdN88PMZ3FiRooa/GepoOI7IBs3IEmGJTC3N5CZYsh7
-b3yzZn4cuWuQZ+oD+G/z1AjK9Q1po3auz5lqSu1VD8GoswwfrC7G/MvH/5Jytu/o
-XKESeGIri8YDMqsVX7hHTGbQ8MBpy5RtFfIGND+XulZvTl87bXAhJVbJjD3GlZyM
-i/eZL4pUdxKjv/ZOT5bI1/NTJ6Qtr6yMgJuVbL7VHYFPISxdwXYY/fkr0AvZw+hL
-KopDrb3Jn+79elZqOuZ6l1muCpkXRs4QS4fRSh4Lnk2782p+y070WhdA+zgzDLhX
-4ytyhAGNi9wWNCjGDT3C8AOoRzn8PhG8sHsAHL6sFYpJx3LRyv/nO1jFGHDd3cgj
-Vql0NTyVPlj8JiSQ1aQvXMtf1M7pwp6igjKPf37tVrZ4gDpjQm26VSy8lcgKgR8w
-Ej4Ti4NbkcZuoJNjIfJZJAUDtr+aXJA2bWRO0ggTnuvC3sHCMH4o6i2FdNzsahYn
-z2QY7h7hiuCdXJdoFWBhSOQ9cUcBroymuSNWhliSxj7XObql2hK+u3Bzp3MCAwEA
-AQKCAgAdQrPYGNKT40+TmMLQLOa1IA0sXuSpkyyGk2izoZqaqs5d+1PkQitQUNFm
-kWtJghmdX2ph+T/RXgcvjC220UViYzMSonqFpbeHss5LBzfT+DgY4+eZry846iXK
-9X3/7EIF3ZPI7HvHAJAmYSlGsp565DA319GHCVa0KDrXVcJFSsp93AEs7eNu8n9c
-ifGROMJSUGaAxLter2R81psjjU1oGipcYVdbQbxuyYNe3L1Nt5yGZArtwB2wnSGK
-6wb5l7ZUg4zgMXUqy8pibcwHK6+LAJ0VGCOx2oNG0Gbl01WvOb/Tpn8RjyO/lXCb
-gcLHGUiRMupwPHJ7EG3pEb00VmZUUCd5bBv76A8WyS9hrGZbcHy26nS/9HkadT5Q
-IZVjWSbjZA13Tm0OmSKgwV3UC5yRZnRj4vNoku9bhWhZ+n7GCAYbSBiAVBrlIgM6
-yxw66Sbxq7jLEZEUDWLTGl00W07hvF44FHYIATsOMzHyLPbKAeozimP/sZVw+dFN
-KcNVKJtvxf/xoZIvM32BevrwqlfgQRr6G+sILzP60NlLMqQTsXlqsqZlyZ6ROrWp
-0q1T1NQBqiyNjk5Iq+nfQl0wVK1F8Xj/IrZ4udddKKunWtDIADcdx3HshkmiVVwp
-3lTadEEEA64Jwu9GyoYK78+xINkIm8/GK4LPgo4a5eRO5JaAqQKCAQEA1/DzERsj
-FqmrF3SVKt15ZqAV71YkVmlVTcE62Gr93kE0YEhkK9HrxcddkiPgkaKP/VUXpzwL
-zVsvdIlPaCdLQVoZt/c2weDvNO+8DKtb3v4AYgc8fltSCvPMzdc3VezL1Y0mZmMV
-sZndsw2ZpZnRrtHllqPQR8mC3mLgvhUyQw2yIcWPuI1L3VBTjd/9z6MDgDTZ3gKq
-h5odK5gu+KIT5hUsnxCb1Z7D3WAw/uprwpW4IFIFWbMeXPwVGuwKQ0/ueqSWQPoC
-mO5sVLd43auO9pAtp0BT8shdPkxuJiI7FNckdh8QJJOu2JkvN9O9/GZEDK2NuPZN
-ONo0hAkczxUkjQKCAQEAxx+BeFsY7H2ai55QR8TkEaK4jVuqiJZFjMipQWkM8vyM
-kYXUG/sV61gex5TZEdagxGdGyGsm58kq9cySY75CGPjCm9bPJ2qsKnKEkw4PK6BM
-eqHres2x7XjE64tF4AIYLPNVmMQKc/5Ke7uTsA2W4YYHSwDKODRFGKhgc4oI5G+w
-j5TtnqeOQ+WxseFEQEp9RgUIssO6m0K4lE9lrwTFsu95USrpJQXs6J/nZct/xXAO
-fRuv/nB7GMSj+Ay7TEfFbAw0D8NKEYzpF1/oUjPW8aihXh3Eq6HySBjRbAH8YCjC
-WZYSm7f7TLunIonRL+dqCHB3WFDsvta2nwdPdUb7/wKCAQAZquxZhi4/jV9m5Fau
-x7CcgD7bOhQLqW2YVnWWL/GJL5r4LuKpSsSJt87phhY1eWtAI5MyL7L/b+1OHtwv
-dyw80mboNRxvIzuLwUtK/jtnYC3PeSi5pEU2RBB+Dyzmq8T211ZPKUv01mNB20X+
-JzCDZTOzGjmxrsQ9hudL8N0Ol1wrI36X40O3RMsJvCxBOBE8dgvHle2LPMhm3CoJ
-J8rRuIabSbAcTkjd0YdBZb/1WzKNtPIp3V6oktY3YwM9SQ0ByvqJMq6IWx7JWx2k
-y7WsnSqwDLdtzl82/oLBSaRYL9KHr92NW3iXCm5QZnzYuZcxIpgL+krnjRhc8XBZ
-NRwpAoIBAQCntCU61J6dLvwmcuNyTqU3JTEB/R4Xg1h4RdgnOu6pB4LsXSZTmpjP
-aZwiw34+w+ELCWBYE8bkmE0ST4VLdEX++iQNVFGMBQ+TgHef0st8FrnS3uSQvQUJ
-2BkhuF7VV249DYQd8Z5MKvNYWpb8Q7W7o0IpLTUjOQKozcbOCIeMvXSauPeYE86B
-6MZL5kmxTAtOGZdF2AsmEH+ciXI+gWpwVbh7YASUJfVtxp8A4O9vvfy16cfEJ7/F
-EHh4xWBJ0ni3k1+Vlwie12rJQQFNmlOBnGCr/65QT0ja5+wZZ2LDKhDlmrt5Yu7H
-pZQSRrhj/CcVjIM3YpDB+dw8+880GuDJAoIBAD/3oFK1uG++uU/Mo+3YtZj5YWuE
-Z5FNE7tJGeyKUvKXTLUO1NTG+HEmSGkOyeiXrQNJssFOjgVzNx1kke5Pi4qv4+QL
-087gFnhDnrMHBSwcWIpkEe5zQEYrS/yRJlD63WM72ivLDNTXe/BQfuCIdX9qBHbG
-qQQzjaLdj0xtKQsidL2Cy/PlqfqGzp90I6uXbRiOrC4rsNjr9mX82atNswua0tcD
-mMGi0eJXtKOS2aaJPU9yofd4sBW+n94Ff5ue1cwfjdW/lKaAPDBGNRCgvvcyM39Q
-DWK6NSHzz7pVO5+tb54vMZK4TySPrS1qlin4AALo4tHIBuIDkaIHTmDsF8c=
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pk8 b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pk8
deleted file mode 100644
index 6119c7f2..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.x509.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.x509.pem
deleted file mode 100644
index e687fc56..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/com.android.apex.test.bar.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1zCCA78CFEnLOBRbjwndwo8AjZVTyorFhju2MA0GCSqGSIb3DQEBCwUAMIGm
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEiMCAGA1UEAwwZY29t
-LmFuZHJvaWQuYXBleC50ZXN0LmJhcjAgFw0yMDEwMDUxNjMzMDVaGA80NzU4MDkw
-MTE2MzMwNVowgaYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw
-FAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQL
-DAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMSIw
-IAYDVQQDDBljb20uYW5kcm9pZC5hcGV4LnRlc3QuYmFyMIICIjANBgkqhkiG9w0B
-AQEFAAOCAg8AMIICCgKCAgEA42Gi4Y3vNA1zQh+IDY/mQbRfvy5ikmWFTP4PwKcO
-XSg21BiTx7o7k+cKbuHjCWp3eh2O1fRXB9WXLQ3//8BNLZLUuaGWM7+fcsN5V+aK
-yPxzt/6fYBOzb4BkYnMgJjmOHBo9TL1g35IPM6O5Y3oSvCBhQuMdvZYbBDBAZ4Zn
-+0PoP7fWPPUne4PGL5KF48ttpKbXeFhUjWcVnh440Amfs4+dHrblf4/f1iKUIrT8
-hNWgOBhUrHAKyKAyE/FYydVm6smLZN39m/5ac7LDwYzRBP5IDVKbLxfmwSOfj0n9
-1YvEyl/BSwY0V29AbCbsl9eVQkE2Jy1UqS7we8rK+V+Z3b/dTOh7skdAwMHGDi6v
-qIxjNr9tAX1Pxhj1PbqYM7nIa7hLmNfJk6N/k72VjJdiWyp2WcQFIJQduSbtgMS3
-CA+LzCJqEbqz5SyaFHh89KsqHPGOxcsVHI5mIRWhBioCKlCbsqvcZg+ChzdY7Hbk
-ViBhqmZr7cAXyZEqUXApSmX3E1yKCXry1WF9hl8homsG0rO1C+seS+R3OiWRNdrK
-o9Aik1gtwpoxbJH+Hxc0usS4yW3b3YyFN2tPUN2NoTFrkKNSRfDwqlWCJH8wd1Og
-4dTxyYesVLCKW0/YfPKBCPFlAqx+yDBOe7lxP/1kuWdKeIHxdhlGpjqUoaeqi+46
-+xMCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAlGQyBIzKvdstBN/6uASKOHcWuqfD
-COyBXnUmMHEWawtS0C4aL0rJmvILQaVrFp3dPkjI3RpN8TZqVnQfawOewOBe/2Vk
-cpzGxsIJQpjmFmMJr730LX/RDELnTnz3VKwIbCoZBZ3qktiAI5+rGmmP4FrU8MVl
-m+VnShyxFSmLakhcyezOos3+ibJDgFsoNFDQ9b8aTUFKy4Xsa5OMSYeAJc4L2IWY
-dowDHu5wnRTfy0uCXn095GdgSiYAAvSp58M/bXuVaHXm/Qg0upWdEaouSMecAYwz
-PTF2sEpmoAUVIHOusm1Chqopa4kQtQCcVB3b/1YDZTeodjKHI7w9WLqjEeq7+fYl
-msvxlYtyL3r6JpQXyYhy1643zmI8/P1TYTi1AbsVNwz/87xmHyrldLKH+jmWMspx
-hiynKOTZahtO48WhkRGLa+iJk14ztUdD3MxAJwZiMUMFhLth/zYLGSyBwqR1smrs
-J5k7BL67b07JApjoPL1OHn9ypBrV5L2CKwSfEGEzp65BtfGIGDYyoNxEv8zky8KY
-XHxZaSWor6RQRp1QX6VRcXYk7XQHWuIevlW5W2APRXCAC05+rlVvi98swJQUcR3/
-oZCgxdr9mSV01fRZMkXv5exkhu/KR8c1ZstqRcSswRv4vrFFTFRahrTWGk0DQXU3
-EH5MwrfZ9sUq7Iw=
------END CERTIFICATE-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/manifest.json b/tests/testdata/sharedlibs/build/com.android.apex.test.bar/manifest.json
deleted file mode 100644
index da13d6d8..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.bar/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.test.bar",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/Android.bp b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/Android.bp
deleted file mode 100644
index 6076d71d..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.test.baz.key",
- public_key: "com.android.apex.test.baz.avbpubkey",
- private_key: "com.android.apex.test.baz.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.test.baz.certificate",
- certificate: "com.android.apex.test.baz",
-}
-
-apex {
- name: "com.android.apex.test.baz",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test.baz.key",
- installable: false,
- binaries: [ "baz_test" ],
- dist: {
- targets: ["sharedlibs_test"],
- },
- updatable: false,
-}
-
-cc_binary {
- name: "baz_test",
- srcs: ["baz_test.cc"],
- shared_libs: [
- "libsharedlibtest",
- ],
- apex_available: [ "com.android.apex.test.baz" ],
-}
-
-genrule {
- name: "com.android.apex.test.baz_stripped",
- out: ["com.android.apex.test.baz_stripped.apex"],
- defaults: ["apexer_test_host_tools_list"],
- dist: {
- targets: ["sharedlibs_test"],
- },
- srcs: [
- ":com.android.apex.test.baz",
- "com.android.apex.test.baz.avbpubkey",
- "com.android.apex.test.baz.pem",
- "com.android.apex.test.baz.pk8",
- "com.android.apex.test.baz.x509.pem",
- ],
- tools: [
- "shared_libs_repack",
- ],
- cmd: "$(location shared_libs_repack) " +
- " --mode strip" +
- " --key $(location com.android.apex.test.baz.pem)" +
- " --input $(location :com.android.apex.test.baz)" +
- " --output $(genDir)/com.android.apex.test.baz_stripped.apex" +
- " --pk8key $(location com.android.apex.test.baz.pk8)" +
- " --pubkey $(location com.android.apex.test.baz.avbpubkey)" +
- " --x509key $(location com.android.apex.test.baz.x509.pem)" +
- " --tmpdir $(genDir)",
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/baz_test.cc b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/baz_test.cc
deleted file mode 100644
index ea5b341a..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/baz_test.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <iostream>
-#include <string>
-
-#include "sharedlibstest.h"
-
-// This parameter gets modified by the build_artifacts.sh script.
-#define FINGERPRINT "VERSION_XXX"
-
-int main() {
- std::cout << "BAZ_" << FINGERPRINT << " "
- << sharedlibstest::getSharedLibsTestFingerprint();
- return 0;
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.avbpubkey b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.avbpubkey
deleted file mode 100644
index ef865d7a..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pem
deleted file mode 100644
index ee8b8a66..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAu48tcVfIiZ9syLm4CqkRE5/MOhfzro4epTGV0VrkOc8JYQic
-YjRAN02/7QfGk/aei3xRuVKqAqDxnZ5IE5ii6/HT9TOInMK08/vr7jc6N7dfQCSW
-nyvG3WBC2HWEmuVCGJrY1j/lmIzKuUcMgpF0ZaqB1Qm/viI/ppXZiEm234SFAg0y
-RZbiiGRy5K388xkTA0nbIAi3iRq8RSfDN4kFzIH/Y7AsNF/tzI2K+4PziGmReH/e
-ekgPhC7XUUySNrjctl7naDgvuihu18QwsC+WNCop7aHLe/ByOrOFq5R/mGsPCP6q
-JyUJ0P9YotI28y+h7rd88W6IsTQMz9jw1JENx2YGJHkjRYIy97vDDbeeyBm5qI3I
-Suy8IgzG/JW0w4pvUB6pWzfDuw+Hr4sqU7Bjb/CFeFUfzSGTg7efDN8W3L/O/wtH
-+hR1t0B0BZBtW9TOFCo4z30C1u2OltT5Vr8GgsODMdR6tQCNpu4WmWfImriETuKQ
-OzPYo2eKCbsoLEQxda+EUu4h5FDH703JYWvrxCCmHeW624iXy1LavEc9YYOe0oRT
-DslIvYSHimH9jvgXRU7HLz0obljwwYRM+7aHWmTClrIC+aSEq1x0COHt8fWtbJ3f
-gBCdNSBcd0GEX55V6Ez1lytGWLzwPqedYbQnoKdIJPu5Ge7GMm75de0lgR8CAwEA
-AQKCAgBoV2e1dVt3zHwtUrxjGdkJLM3lx6tmAWRlDCfHlyP+UQJru+mb7GuJGLTb
-/YZojDt5Z8jjK2yvF7AyunpohHKmhhsffvLSGrOmRBDlrk2x706LFY/Brw3r3AB0
-ATSrIz1ZCNP2pQdqjXC+EBuSi67QXEHsLYdBFDaKyzSAUFnvEP8ZvBOqiR0vOYp9
-U5mz99AO9Uh1EsRf/sKcSlmdDJpwQiW85KZC4NcfA+M8txSFYA1wltpC9tHC/HgG
-n218Ce2nezaLUS6kBphbaqaXbXHHRWmb7HWSVpqFs5d6c5tkRLLRkzM/oahLX7KE
-qiOtuGMCtYtJmO9sfYNfIdYguy2JOylBQU1HLT2eTp/be29aUfblGpvG+4WM49+e
-da33R65viP6uvwcTuiQIZdfouJLgADutfmLAX4XGk110k/AOzSFCeIvX0oeoc/Nv
-IZDgGQjELBuyKdCEnheo3UkngXZg2hbVSoI+EQE900wm8s3vi8GoKq32VuZAiNGi
-mW6ebs1A3fOLCPrK9GdbLu6A2uXyeeQH7NMiyK9o5jWPIU7NJ3KUgGQmbNz0/aqi
-jN93DdRjeoYXUdD2oYC8S9XMqtdiUubVEMqDeGg2jhLxYDk9EfKD9KZnmFSBM7a0
-WlZlixTXi77ktJS7+1YlRWluPIhD0MXdEkHeRmgGZoc0w9ayoQKCAQEA6IrCf8U6
-SUG2QaLrIjAVcR76UETGR4gE5s5E1qvZB3/yGzou9QeBOGFz5lRQbrGD9nrNFuqq
-Z/VJmsL2aia4dPDjjJLPW3budcq8GjR/ZdGCkE+VWc3D/CUf8ja4Lx3MxDjym0cw
-i+pMysym/6QNo/sAltzQYehtQlGNUisII+p1FbHKQAZwLgczvglZObgynegSUyKT
-xrXcUyqOozU933YPkPE1X3cKyF2JFoK/YzxMCfDlYIs4SfwlFnFELbz5ug4Zx2WU
-Ouc9JWhAELYzHnbHP0OkP6mUTjSJC52XCdHg8b2Qtrof/PEuJ3Xoyz8PFBQIeRjD
-HzTJ4i0Pzwd/rwKCAQEAznrE11R6IbsAznmE5d2nmrph8n0qnpXi9Ryd5c4W6VNm
-+hnelTnhAkGtNHJCloL24zPlAlb9CAGKJM7U1I21PqgZpIJ7hHTU1FLiwc83dkal
-IQ5yVbAPoa4O/qn0Omo+MQ+tYCygDHiAJFQFah+pX1Jj+6djn7kKNCzpVeN6aVFu
-hblHAOgwhDlt+l461wjYsI39osPfgInO/z/oY0WuIFEYCA5kWXEuNImqZi7GTcs3
-EQVR+OxTxwt9IUJVeTAusv8V5DFqlojF9jZVBB60VcfMAEyjsAF0/ZsweuBU3jnD
-mAln3pIS4AON0zGM/eZFKKkHZT+ZVqIUOVCFoyGBkQKCAQEAwmX10SCM6F7hwR80
-WCFAW4/dDCtiYrwn9NctHxUMWsOwHujWBosekIaPgFat4svNmMjyGJ1WlY+t143y
-t6zk+QXEBGlapYjYMmqoM3P9qJ2r+348SZXFqE1U1oS+Fs1fuA4vanXp9J2LUuIh
-HYcEzDfyNywjnCXU6OMKNE27AWNoPBmkDUAUmbX1oIFqMOF2lyFB6HP4e97ecDwc
-f/3rWpr0ymOLDeKThgsDpmjpHEl0+76B0uKvzNHYI1nO+DmJvus4y8N0VoWnTVVI
-cXAPbgE38gBXF81pKLOseaRldpUY6p5hkxAn26m3vs9ILFjr/wn8R1fXDohv2P94
-vsbzCwKCAQAkXsu9gkvhFSeXNyCJvPmA78PBCvsu5AgOVPQbPqoaf25sL5Jdhsxz
-sU3pJxdDm94RN1rnhpsbhenngedLaYq7drDNoY5QTqQOomr+6JlEZD1CDWFmZpTa
-TeamRRmYEI7T5YcMoc+vYqpvu70YbGtRNxoVge6ye82oUyDm2CL/2jA1reUr67pg
-EB2nNGH47r38m4ZJ3WbJJX0oyQEOO3/ogWBSSvayKpWQ+47gYOzdVyZkASPnTPmU
-3hk0epLDvhD7xqL8hxfXXFBChl+DUkVBtufgRZ+vqRIKegOYIVvRqSsi5MU/F0vr
-2bRptxi2wJD+EIgU9Zb1A6e8UMq5aXWBAoIBAQDS8w0TG4R8SLHXOs9JagC53zAx
-qVV8mrL9BEYzeuM6vNpyZIO75O94q2ifGvzsISxLf2xom99BxpcWo9UAyHFgubL3
-+P0spdJSeP0OWJgldEqwWGMrzQbYZomzi/QUlFpXNZfHgHZLaCK7qKu9RDQLVtug
-5i+yVjSKl6RcaCCG9E2u68yxKlI246RNK1HZXQgxsnz6BnP/cqAn9G+yzT9p6nmK
-tt2d2s35MS1zV9YzACi2idsZBeio7bghC1maj/TJvq9gRwIRN4UpbPRsflpdejFY
-nEEW+tEbNzFrepkw08+9dRGnPU1G1NYvyQqMhc98lVBiMoDiH8X18gVWafhR
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pk8 b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pk8
deleted file mode 100644
index 37948c1a..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.x509.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.x509.pem
deleted file mode 100644
index d41d86c7..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/com.android.apex.test.baz.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1zCCA78CFAgqiNJewYXPYz+41LOIDLe9lXnzMA0GCSqGSIb3DQEBCwUAMIGm
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEiMCAGA1UEAwwZY29t
-LmFuZHJvaWQuYXBleC50ZXN0LmJhejAgFw0yMDExMTAwOTIzNTJaGA80NzU4MTAw
-NzA5MjM1MlowgaYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw
-FAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQL
-DAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMSIw
-IAYDVQQDDBljb20uYW5kcm9pZC5hcGV4LnRlc3QuYmF6MIICIjANBgkqhkiG9w0B
-AQEFAAOCAg8AMIICCgKCAgEAtm4cczWBEzR+kzRPHsBh61ihAQNtWN2mKLhZZKRS
-YrNZ59+M53menjsc1Bs5fYvKTMGj2u2a/yvq0QiSAlgVMY+1aZ40FN22tBTmy4yr
-6iTMi9Q+uUbQJlHLWSy8n3oFuxEHAP96ZPDJyqPHSJpKeSPKIgwyw3I+nXb/fmB4
-HvBmjHbFnwvKqHFyoEm5p/wGZn2vMtxZqlignNtUZr2zYTJW9YCuL80L/o1jdAFk
-5sHH1tBEcp1ZTXRgKm2XFfp7fqfOWkS9XL3VUF0LVWMgyv0u2fr7n8TPZb8iz5PA
-naCUN9hCoPrj4vg29eVYy2IoeSrLOAUiK986mZDToKbhxuLSHVV+IRNnqIQV0+mu
-rR8OCqDlWbD+fU29cacAjGFt72unLAIEE49GHZFS2pTZ0cDXX1bBUrBVTMlcnCjn
-YiU7XtPaJGelBkJEu/ErjHE9TrsQGKkzMwd2ySTOsk3K4OtWl+E9i50TW8Vu7gR+
-Qr4lZvY90OmXw+k02pkCo5g1GU8uXoTPjd0JQsmiEk01dMIPyWxXBYiuiRUxu3mc
-vYJJGKZSMX3VKKYmtFN9lTuf/OyjztHjRQPit9sWVcYgKuy0kw1LQSJxtyNQIeFm
-ipZVzh8Wo2TMm8argWMPHxyIfjEiVbNhXirC4My0Z02agyyB4Edxg2jkiKQBss3y
-/IECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEArOMz9Hn03yy2ano628v0wXMFixVA
-/XzSpb8GWi4GzJxV96c9t6QQPVdo/XS0uBuEa2Uc0/W5icU9+iKzBvQHM3MI1jI6
-/oj8/mGAzvyvIA0pdKP1XOvugsgi2UDNr5QNgZ1UPIpVkzeBQpLgTiWL70Pl/znE
-b7Q1nKEFeNWxBaMk6u6n6gNh6sMLv1doSCi0FM1cnWHv/0qxPizGjTHKmGs4TbMZ
-zWnBoH8XSMxruAEbucl1E7vYXgYthOW0I+SCFpyP53e9VdoNNYWMeNKCm3EoIY86
-XWLArBBQcCCrsLas45670ouQ/H9Yn498MwFinuWcsfROghXQwhn7fPaDQ2oVlftj
-4LQS2vD20mJV15wa/1n/VDzRAxIZwPdtbJX6JZO8E7Oc0+WSehwhaU+x7k9GYyBv
-tiEGS297qZC0/WvoE3VtRHZjOzphxt6PLelCEoqhdZy+q0uGxj8TmPRXo9xtmBLH
-6GPgZe3dR2SJ4uMqBjt6/6/Rki3du3btAn2O4b0Zf6h3wftqK6INbsJ7fRpIgLaU
-GvCZiCUZaxkNcCO94RnZJrTTVO1rJ1ZBkcqyMHvrSRhPCAyH2zVtHcNDCiR06GNA
-+7P5SuyntvmnZKteKc2HdTnm42ewIXyDIwTs1crc8/luevw81s+SJqWumSGTxpfU
-IAM423xlNZfBXZA=
------END CERTIFICATE-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/manifest.json b/tests/testdata/sharedlibs/build/com.android.apex.test.baz/manifest.json
deleted file mode 100644
index 1c57f3af..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.baz/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.test.baz",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/Android.bp b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/Android.bp
deleted file mode 100644
index 451f8a01..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.test.foo.key",
- public_key: "com.android.apex.test.foo.avbpubkey",
- private_key: "com.android.apex.test.foo.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.test.foo.certificate",
- certificate: "com.android.apex.test.foo",
-}
-
-apex {
- name: "com.android.apex.test.foo",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test.foo.key",
- installable: false,
- binaries: [ "foo_test" ],
- dist: {
- targets: ["sharedlibs_test"],
- },
- updatable: false,
-}
-
-cc_binary {
- name: "foo_test",
- srcs: ["foo_test.cc"],
- shared_libs: [
- "libsharedlibtest",
- ],
- apex_available: [ "com.android.apex.test.foo" ],
-}
-
-genrule {
- name: "com.android.apex.test.foo_stripped",
- out: ["com.android.apex.test.foo_stripped.apex"],
- defaults: ["apexer_test_host_tools_list"],
- dist: {
- targets: ["sharedlibs_test"],
- },
- srcs: [
- ":com.android.apex.test.foo",
- "com.android.apex.test.foo.avbpubkey",
- "com.android.apex.test.foo.pem",
- "com.android.apex.test.foo.pk8",
- "com.android.apex.test.foo.x509.pem",
- ],
- tools: [
- "shared_libs_repack",
- ],
- cmd: "$(location shared_libs_repack) " +
- " --mode strip" +
- " --key $(location com.android.apex.test.foo.pem)" +
- " --input $(location :com.android.apex.test.foo)" +
- " --output $(genDir)/com.android.apex.test.foo_stripped.apex" +
- " --pk8key $(location com.android.apex.test.foo.pk8)" +
- " --pubkey $(location com.android.apex.test.foo.avbpubkey)" +
- " --x509key $(location com.android.apex.test.foo.x509.pem)" +
- " --tmpdir $(genDir)",
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.avbpubkey b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.avbpubkey
deleted file mode 100644
index 575ba511..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pem
deleted file mode 100644
index 1d651b58..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEAz2ykMX5GHx1z+1BpFcNwnZv/8AladKxjG962kBuZrxSpu3pb
-8JKTqajY1TNmM7Hs0P8RjDY0M2ryNWodNu7GZKSOz7L+LztHeJFuZByCHjh4em79
-sYivhJKqlX0EVCnxW+IPQPQqxJKDoFBGWo/HfbhXiZJR5OT/XrNhl9KfpFL1NHfU
-dmZHIqFJHCrcQ4jQNxAh9XIvw0bwEwWe/q3Hdxs7UC4mH4m0Hz3cmKe73H0al3FW
-2L3xgy5vmc93SgzO0Csrmcrsp84B3qtNd6B0Xna52AEmBMuhWMRiFlIpV/Pf9utS
-PYoxU3IRjUJ0FacMbhgQOZdtXZGW+G3FLnH2XHX9rUNnrlMmgTmoCGH/JD4ZwXvF
-KoEUZ8wlGVZksNz8i79yPMxR/QyEppf56YSD72FrfCBMVdBDi0vYk7/nhqJU97ws
-VFwhFDTxp0//rca8UOnn0pP9HKylxT6sff/w2U+zzzn1MLsu/Tx6JEbDj+464RnK
-zxBL0wyzUUkwOodgctW8UFPSrttbQD5+7G+kQUl3q1854bX1EdW5jGF3l/OxE9P6
-mbsZlHPOjd4nFOtju7cgKpDbFtVwyDZRBtoPBIbBqS9bf7Y3oaesVeFkDfeC5SkC
-bUIDlri8Sysuse9uoNtaGzvYu5Wnuv3FE1V4X9Ak92S8VyUT2a2miW6Hj9sCAwEA
-AQKCAgAefqdpC1p9ypO5l+nLJE+TLFMlVAqzaoCroUOPzi76+Xu2r1eC99mzsLoo
-JgVZhkf9tfI7feCQyqFPTwl6gQIz26mPSY5rHTj1tdPX7gUHMmAsB9NOXX0IbZOc
-pKOVSBFO495AO2VqPuwRDpw5Rjga+JYOCK/3id8tagvoCTQlMXkRPKjEu2ar5bBc
-7sQxPZT28206q43wFKbI9SOZ56ySizNeJ1q9ej479ZlP7CEHWnElYKlW9h3inloT
-79dm0Jk7K42eb6H5TaUiumaKNtHE7YmHAyw2ukU/SqftBilD3/vGTnRpzb5QuU1x
-ShrM8CE4slr4TJXskrHyVhkOKf0A+RNKcZ6YICrEK1GGOTItNMcAGbHSTQBqVr5I
-MApXfiEQfZetgSv0e9s+DGecB016QG/uJis6OyABV0hYBcnrNPNgpUhmDfy+IN6A
-dpdjeSD/7iOXTEnCe9jrY5+0ot4rKZbl00GoZpb+3pYoBcpDiIVJvPxrWUZeC6lc
-aZjgmjkg2IDXE7swevsStLqSRY3cusMTnRS1Ay37/gobE+f2rJZArY4GAobckT3R
-im6q8cfzTH46wAZBuO6wHlmNfbDVZlvXx6zFhkqpefxRQ1V6Fa9LvkICcGmuhn1O
-9p3DBphflcbHtMGwJpmmr0A3T/aakw2aMT9Qzda91SItlqxy+QKCAQEA8pE4vt3R
-a9PEABO3rF5oWT8UaHfGBTDhoZnG1KDofDvoKrw2R09mz5nhROIDnVaQMtkWChhi
-YhChOHZANp1K2xaCXqDRzbFVq1e/HB9Ag6mTZkT5R9Z088/vOWRIA9H3rk74GB+y
-9iaCusk8NiIqlubvc7XaoTO4ChQ9X+p9QDAmvZVaDfsJGSXYvqfVfMy179mIlzCN
-DSTePQsn1qEiPKltRNBysuluDJqa/PhcsGd7Oeo8SJuLFVOHk9rTuemvIbkxI8v8
-PZ6LD4ORCDsEKst5giqvVBl3yZ2ntuLlouxQGAg0F+VGxSvDYz81zwUHUmsSXDFo
-gw22tWGCQpeFvQKCAQEA2uk2jzEnMvhklfh+3mAUNpPRUyAC7KHIB0vSgvkRTK1w
-aqWF5jCx0onz9sW7lGYcM6RRXBJNi7z8NxouY2Bdw7ijGd7ZuL2ybpbsIetfMV16
-xGZCEL1JEHOnglEochGzspwKmADqWpV/suXKcOlrAZeH1y28TNOgaprTG8zr02DJ
-CQrV8uJnE3HArEHtQdtjsPv/OhDEjEA3Gl2k3hRuhsf0rfeMby0QvvqyVb0Y4SEM
-iIq8MP/dZPgNrDi4r3s0aps10ciAHyHtyuLv2PRkc5ddsBh5V2uEc+S0TTFRRW5N
-uuM6E7uiuCbNrdd/1dfl55ojIYgI4TgR6lH5kmPJdwKCAQBPAK9rstE/fkRLBiD/
-WexAjQP3lnL/Q9FpEa2pmRK/S7+tE4nWJe1FVkgBaF9nAkeK2BuOhCye5e2sdw8o
-+ofj3WvuqBBNHyHY4YZUAXXArB1e5L4QALAsrJ+soJW38M3rjrrNGJ3v/9D6Rwp+
-Uxht958rn6IqeK7LUZY/xB6xJj2n55niDc4Dy8jRJ9anhAEJsl8DZwO5sTVUympa
-RDbjbQcyr3V8Af0ey8gI9lcx+TIwRbMGrupYstDofhARcCPjJu7zSr/HzfhawC4f
-cSFFUuorU/2wtW7HUrrKHRJPwwm/GgTld35aP4uuqmq7F1cwJ8FeF5WDgZbtcmm7
-iKA9AoIBAHaOWSsBns4e8jK6atM6S5gnQ/V137+R+ofhC3g9NZ5GTByl2jeJZbS1
-W7fo7Kb5Cgr50cpAa1jjl+CrwDW3yfAmvcZUB6viqJD2EZppI5vTmZpmGx9/s+NC
-D5UnKPVmGuD/W0lpLYKzdn5HrvSppXcuPrZNoa4l6rnxcaWbvJg00YuhH6+z58kD
-ESr5ZWoGTB5cy6QB0sB2QqF318MiY52BC0VwTNElIe2cThrbF29Ne8EzCaqr15ZI
-NPdxnKwE2KVnu6UKpkC2GleHwgfIi+KCNo4ZIxYyN4CgevlXXUFx9IzjZN+s/fon
-obqlfCkvDOb6dk5BozV+LU2u6a/bdQ8CggEBAK/n4ELmvMRbkB4lr9BEN5GyWwvq
-Zkd3e1EcefMpR/dXv+2YD95BlUa2kOhvGVNb2TtnTGcodtYgmWgkSCNwYGO15YX+
-f1OdqWJdJs/FEgMWyAElLHcrwFUJIDuBBLCZrYYKSgNoUM/Ddk/CaAGWT4lsq1U7
-X+GC8SVGkxyqV4GzI4uQ9/vxgbxP9zIbHQqa4BUUM4kzaWxTtJuaF+fHsafgTsDb
-BDmOR/vVAhbM02Bw6xCqWNB337dIC2LJNmvmbTz/4lxe9mZIvN56UzcXAHSB8Xkj
-fbn4ipVY7l/NC4LBLzRvEItTdNr7zAC4QpsU2/upw5PPhv5R4Q2FKV96zM8=
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pk8 b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pk8
deleted file mode 100644
index fa38e322..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.x509.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.x509.pem
deleted file mode 100644
index 145a6560..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/com.android.apex.test.foo.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1zCCA78CFGuWfjBtDvTQFqx0afFbqDDoozbTMA0GCSqGSIb3DQEBCwUAMIGm
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEiMCAGA1UEAwwZY29t
-LmFuZHJvaWQuYXBleC50ZXN0LmZvbzAgFw0yMDEwMDUxNDU2NTJaGA80NzU4MDkw
-MTE0NTY1MlowgaYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw
-FAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQL
-DAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMSIw
-IAYDVQQDDBljb20uYW5kcm9pZC5hcGV4LnRlc3QuZm9vMIICIjANBgkqhkiG9w0B
-AQEFAAOCAg8AMIICCgKCAgEAuB+RzoO8K96g3xYQng3cToQGYfCFVA47S3qUBlpj
-Qr4IIw/R/Mo/0/LoK3OMBbjrpwYm0mBRrBttoX0jqlANDOrsk0T6jrWsIiz0iDar
-5PEJjZpnfQILN76shJ/YgW4GQdLvjrZMtksBxKXLbID1uxBBD7KZzIpb7euiV06w
-gaNJZyZg+2J0Isj8qI4H34x2GtjQxd2rN8KTLYOgatekkQCauHH/LLCxVA0K62v5
-+NPmrhBTQNO8TSMLmqci13jYcvs9Oj2qkwQKD9i4SMn1VoHrswjulXMibWEyu5xB
-72vjwd9+xpLDcLxHDCQW8uFS7z/omhIE/DTC4QnmGmfz3gyi8O3sekLAdrP5YMz6
-+GrrNN8dwKr470g02oMtdpvTIC+4CcIMUuNBPvzsLUnCAxYTWo2QM8hcHx7Bs3XA
-gRaeC2pEIcz9oWoTr/G/5ipdmLSDUVtBQAiNa3KouY9OAO7RtqmweLiXaBfPQSBM
-lBWnyNhfEnhp++4Ef3LFDRpFfyo12XUysdmdreVjlZJ8MykJD5AU0EZ3gQbjcmWX
-vnIWJTc3045dMCDn/1pOss8//q8doIhwVoTCRK0UAofZEajbtfDQTtggWyjMTPtR
-pDtAJA1kmBLnCpjcrnj995pkz6rbMU76zDE7SzoVHE0zRnjDIiLCvNNScJ6oxY/R
-/wcCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAp5kVSkIcuFWMl2X7yTyC3AuOfsOS
-nqnEGs5ns1ij1SjSsogwt4apnjfgXdc3sye2eX3s1SWnxkIBwBQVOIrvSWgN1Wda
-9UQ5uKcrbiz2yT1QMBD1VYsv/zzRPWNP7rzcR7szfaNQOje3BoCaQOkWutgDKi3O
-kN8mz7VtfQniKvw/bbrSQMyVkQpy40XQTyJckfizomTVXlI79AoOVayER/Osgjp9
-8qwjtKVp/o3f3Nd5g2yS9GwsGBbXST0KhSB7bmsLHxPGyF1Zw8i6kKMuS9PX0E8r
-lBGGMZceKDp0eGDXeEUdVIn7labsS2UpMKRuDurpsvol8s3lVBFhAD8yT3yLRNhM
-c573H1ttrE/tlDOj6pdE/uz24WG+M11iKNuqW+/XnUiUjZpK+2Bt6ev4Yg9cDknn
-ih9dr+/YEvCopBCgwaURhTOxDKNNDQCQbu10NnT+apnomWVgWIAmu9SJRE0dFHj/
-46TIUnmmnjg1tTq90yJYoZyXLib6r9PUIXtUEGtBbbjg0axhUqP1jr6FKYnnK3TP
-NkxrkUVDUuI76qDhPIfqECymJz8fx97AJcPGT4qwOJKcCgft86RHOJIFr1AGVGSw
-b+Vw2IWKNwyAqixjN/hhmNH2nlUdhuPPDk1GuTwlODuAvC/GTfOms7yacSeEO0wk
-Sw6cwZWCm3nMiiE=
------END CERTIFICATE-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/foo_test.cc b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/foo_test.cc
deleted file mode 100644
index 34d44d4f..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/foo_test.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <iostream>
-#include <string>
-
-#include "sharedlibstest.h"
-
-// This parameter gets modified by the build_artifacts.sh script.
-#define FINGERPRINT "VERSION_XXX"
-
-int main() {
- std::cout << "FOO_" << FINGERPRINT << " "
- << sharedlibstest::getSharedLibsTestFingerprint();
- return 0;
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/manifest.json b/tests/testdata/sharedlibs/build/com.android.apex.test.foo/manifest.json
deleted file mode 100644
index c986f711..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.foo/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.test.foo",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/Android.bp b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/Android.bp
deleted file mode 100644
index 3dd0349e..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.test.pony.key",
- public_key: "com.android.apex.test.pony.avbpubkey",
- private_key: "com.android.apex.test.pony.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.test.pony.certificate",
- certificate: "com.android.apex.test.pony",
-}
-
-apex {
- name: "com.android.apex.test.pony",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test.pony.key",
- installable: false,
- binaries: [ "pony_test" ],
- dist: {
- targets: ["sharedlibs_test"],
- },
- updatable: false,
-}
-
-cc_binary {
- name: "pony_test",
- srcs: ["pony_test.cc"],
- shared_libs: [
- "libsharedlibtest",
- ],
- apex_available: [ "com.android.apex.test.pony" ],
-}
-
-genrule {
- name: "com.android.apex.test.pony_stripped",
- out: ["com.android.apex.test.pony_stripped.apex"],
- defaults: ["apexer_test_host_tools_list"],
- dist: {
- targets: ["sharedlibs_test"],
- },
- srcs: [
- ":com.android.apex.test.pony",
- "com.android.apex.test.pony.avbpubkey",
- "com.android.apex.test.pony.pem",
- "com.android.apex.test.pony.pk8",
- "com.android.apex.test.pony.x509.pem",
- ],
- tools: [
- "shared_libs_repack",
- ],
- cmd: "$(location shared_libs_repack) " +
- " --mode strip" +
- " --key $(location com.android.apex.test.pony.pem)" +
- " --input $(location :com.android.apex.test.pony)" +
- " --output $(genDir)/com.android.apex.test.pony_stripped.apex" +
- " --pk8key $(location com.android.apex.test.pony.pk8)" +
- " --pubkey $(location com.android.apex.test.pony.avbpubkey)" +
- " --x509key $(location com.android.apex.test.pony.x509.pem)" +
- " --tmpdir $(genDir)",
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.avbpubkey b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.avbpubkey
deleted file mode 100644
index f7af6e90..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pem
deleted file mode 100644
index c0e2965d..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAu5za6xUAaREb/RXJGh0QOi+tPLjtmDkYL3COBcZ6dTsBYZuE
-TkBwNgsvfk713Ddk6iOirjcakRLdj1K9lJdyBHMocNz8TjizO/3uRhLA34Fgog6Y
-h0xwpDfb5gPyb18OvCVFuRLIremGa68zPnXl+p0kxzqafKICGjAp3x3ugNcSMXlN
-0nKm4MSDiqZbTlAYutW+jTFr+e2VABbbCY6ijgQJMFDHNkA4QgW2rwEK63OaTImT
-OKT44JnQ5VJpl8VN7HRaAyg5MUjVfuo/HSIkFpYZ5rxgWOZioqvJw+lFV6/TSrxk
-P2JWQuu9mBDmuAoaEHE/yyLPLDKtQUquc6IwGBFG2/dn1WKoTB1X0TsCaIwTBGVV
-n23foz/+uE2FJuh0mNaGWMHN4cOekbYhti1xIvOnHFlOIWdpmRRkIvUwjZYVkCu9
-UnPDHmhbA+3cr8scqc66JTESc1A/uoIGBtK10aY5jUyg4Tvdjc+PlwapeIAseYzK
-x4eW1ujaTP+DEMBaamQLOwhvewxXubTyhjIN4epQma11pVfLwfuM7GAGqlyzTMXE
-BQLkm17TIPEkb+wpU9zP4Xn5FshE8mb6k71fVXwWeBaHtF+tx4Ml5Jv2XUe23EDJ
-5pnIB0sXyJcEjDlqbNCzfZn/LMJQHSd5h+wfwLoeL3U5TigpFSQp9MypSX0CAwEA
-AQKCAgB7LdhaYrabRT2AJI6eE5j06xqt9KkiudHUS+0jg5YhZDVa9bWffxVtllh/
-cK5iAQjD5dPI2Ksbtyw7DtMkPW8B1u4ldCI/5WBgsi+AWI3D8XkVzcl9g8WtPHOn
-iM3jK6FMDJjDk76o2NuF1kkp6FSv//8Gw8ZssB37PcYwFMHkW9E5JHDhDJ/ekYfg
-P6tRNquV+AKdR2aieMfMgDUeCEVYQvQZgd/aEb4eMwwnyOJ3hrY3LFi55y70oGkU
-N9DWchfgeOAklINAhZaPNpNruF/DaJfm86W6mMEIFwxpEb6SfQGYXyrept0GISuh
-LO+exBsq0oBVCizF0xwH81Wo3EMAWnjAGMNxzKOdtJhP0VCL5asgMb6/QbKecko3
-2kZNAeW0aC8wFajCOarQQ5JgMcPdC2gGqjUakqHj+1QlbvG/KI1Xav0ET/OIFOuY
-RAneqIaWVkU76tldm3mnp6b4vS6lsT/v/56sHtCUWGDmVF8zNkZ94LF6XcbEt6ZJ
-p0Ssq0e35Z60ikAPuxNXNA0kgJBpq/V6j0Iqf9otGuEFLCy9AEtCKSYHVQvwRmMC
-wLGr0L47p7RSKyMqWwJFZmMPfbAUz+IlYtxqzQ316L2NSCRnTHPV+thh9W/HIXvu
-pciYkbjk2m4cpjiYEZRS6wLadfPGqMosNJX42G1INM2wEzfeQQKCAQEA35iBH9P+
-hWGYl1rmZBQfv2uYJPo6TDyM7kOrIctmPek8XPWNI9jnayE0Mmpf/eA1sTZpOzg2
-hVVc2QK8Baqxaq6JwNz/WVIvvD8kuCnsBLVYfAxEXgS5aF6NYbSg2oZf0CaMAFtM
-xf0SIyhol9Xl9d48CrmumNZnkvpa7AzOvb9PRn8TXFJFkmkyDmDWvQVaBZbbkKMC
-Ak3UA2nB8ypXfujLc2aBAeoSSw2d/EdoZW4TI/v5sFI+FM9Eg8KG3MP7rhaemptl
-6DNh5PpFYl6smqE87Cb+0jmR3ek9jkjxXJxE4VrkBrDT4BYogb4TnNP7wdux5GJ7
-NqBAGQ8Mjj4ezQKCAQEA1s1dt/VxbOBPCRWlmIlWnmiY4pf3dkl1HOClNOwtviG7
-gCRmeIwtt4O2uwZOMd/JyYLBg4yieT8cCDbXSPXVop765bftBz/Ce5xU9sadLzI5
-sUdHRJkBtHsC12vXZrlrcnVauKAoArDcz5AgndqZ6i7lw5wsB2fQhITGJ1fYMW0L
-RRugKU+wuAgur5GOoTPmryrf8WAbKYh9eeyoBHvK2u8JxsiUXUuJIPvOPjArmHLe
-fxsoN8G3o4Rud9ugPEjsfT3RU8oA+9+LUMVbNl6q8RF9qherxKqmXwukh4C4iuVn
-MyJ3FBAq4Z4BSbyirl4APC4Q41z//ZTYrAuFx9J1cQKCAQBY99ihLnw+3GeYCe5U
-cgFz7D78r6hUv18gS0Kjzsge6FhBcN85HUxvvyWCzfrmDLmwisLyclqXUTEBlGn2
-I0Y2+b4MRKNCCka+M63Lrbqg4PuVWFg3xM91bPH6p6G9cexb6YqZdbqlqR33aVO8
-3rqCy2u+pMWJQP6zZ/SXqjz1GVNU7Klqeb3/FOZ6/CNV0PRR9wXklkftXMR4mzM2
-K2nnMIALqgS5G0cuH/v17v/mJBdvoQpoE0FqjFJpzxRUcZMKYSu4vw6chx1zu/Wx
-v5QUbwXLvXR1d7zHvM/mdrW7MN7jgIPs+Z1Es+xoO5aYN20cZOtywZDfWoJGtks7
-qhIdAoIBAQCqntwXmH2tRwtgovIzlLvZ/imaq61kJvtAoex4ejXndfHy2ncOwAI8
-aAJI0rxf/2vQhe1iqd4QwyFoIO+mw6cbkn6m5A8CGBJKj6YpkyAd8h5Dg+PHSGZD
-Twa1yLKDpTsE4tTaHFVLteLfeJN/77kcfH4Df9S1WTAXY0Pm0m8m63/tOAFjbypn
-NBCpYsxRneFaOItDttw8hG9u3p2jWhWLDB7O6Fp5NNvK+FkdqrOmV3AGtLKgf154
-I2SADlNcL2yyGt1gWe+oIiwOT4WhTVcpP4R7DGxjPk4C50OcYpGzun7b7j96D1GQ
-fyp0wMLUEFTNeKXvg9rPOWFWX5y3WaPxAoIBAQCiWoixjIhHK0f2yMvcYAzqb3A3
-AZs8IjU7phUxAa8LB4R2V5NOYsUl8xIZqZgoPjyJvlI0S82IjEuLqnsmh8GgtJxa
-vOL8JLUX27kr/eOTkz6EnzYVtViFM+D2re7QvakGSh+D43sC29S+dUSMrB6XvFdP
-pBbD6paLmefvgRyP8kxMTujsqVS9TSAqZLirxGSC28wgrRx9CRTy93MxUfw9spCO
-V4/TO384iLZBlj6bDJc4g7YL1KYvZ6ZCCLWoq2TXyBHAOjfThttOoGFj1B4KqdZP
-rO7xAyJCS3t++Nm1AWqmnA7wmNEhMruEZchqGOP7A5f/xcxdsjY0m5LTth50
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pk8 b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pk8
deleted file mode 100644
index 104a5830..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.x509.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.x509.pem
deleted file mode 100644
index 2f96a293..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/com.android.apex.test.pony.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF2TCCA8ECFBuIrFu5kQxwNJM09/WyY4JaskQLMA0GCSqGSIb3DQEBCwUAMIGn
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEjMCEGA1UEAwwaY29t
-LmFuZHJvaWQuYXBleC50ZXN0LnBvbnkwIBcNMjAxMTI3MTA1MTI1WhgPNDc1ODEw
-MjQxMDUxMjVaMIGnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
-MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE
-CwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEj
-MCEGA1UEAwwaY29tLmFuZHJvaWQuYXBleC50ZXN0LnBvbnkwggIiMA0GCSqGSIb3
-DQEBAQUAA4ICDwAwggIKAoICAQCrNP9VtH73dqoDIKN9GQ/XTizM2y79KgiUah8J
-4w2FLn3Q/TKxH/NRJVhunAbNLbu8bqfOhETFFWWr8FD2CNq7j5ZSN/xZHHgo40F+
-U1+SisPErTVa9oma4fn62qrzwOZ/uDqwCwzv2Qx7SAYE52M4JAwMI16sV7KZGXBI
-3MZApfRWcuk9FcH0SPCQReY+P4nRqpNqSdsDw0u6BFnPmc2oymkUy7VV7KLjpNo1
-si5M43U3QyLhx6abVdeeIdcC1ycNYEyYKWigBqWOWHIxj2FWUA/vF1OLJm6AR5Z/
-VYh9/7EPvPW+QsMwaM/YRgoCXAnbWA1T7XDJx6aksy6CHt53FjufNwqKC9npthYl
-rdy7rv8XBfrp6/ZXzRhsEWXMHliGrDQF0vyHPgs9CsfdPQtR3H+7tV5nXfa4vj2S
-WbkmZyOyDLTQku7luh2dDcn4Jw9yOoAc2cD7ql6H/Hd4MKrPX/SKahpK7ypZebgY
-RRovxgwxrgFkP9J8/xW1GCY767a9E/sjVaFdQb1rAUWkNG2NBUDtFKdu7mg1KFyE
-c1dTY4cpLiahWLyD845bLnunWaYqutRm3ufu10lBstqF1RkBHcqvoxfoa2IeNB23
-MPqKGaovQuFj+cRHsetC5W3VmROcvAvIJzhcvy3CK5JhvXdvGTkFaoA+6hifY2WU
-Chli5wIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCKEncgnGCwsHkC9UGg/HDwU97Q
-ZH2kqNXdFRYURp8BmQbtNYuYSs9CYDpGugOjW7RILmr954KO+KNCo1OX6c4RWwQ0
-5LAh5+/FmBHiTJlWHRFGhL9WR8Mn1iwEsrANMyhoeoLwlKDVORM2/rS7APBM1pQl
-gQfQHLt0cWoFpoL+pHElyuoVVKGB8sf06atcB/U8HND/xSY8fa7YjBOPYIMoUEvQ
-aeN4JbxYNStqGDEz7+FoguXudQAvq8JFECsFwjWZd0/I5AjqcHiAG9ZaOrUiVRl2
-MdZSf2fjeSHXV3TH7i9f5vmcPUNERZxo/dutOTTVxlS42qrUaVwuSJzDG/MfXZWB
-A6IB3P2qe5lzGl8mmvGKbX3ZXakf0OJaGb/Wn7GpsTynS3P6Zqa02oz89kquERey
-PoHrR3tzNbUbDnjc/px2h2esG7E7E4bRc1PE6ndpvhs2vKypTpYO2v0cXWSk+xiR
-eUZGPIXS7yMHSu4yHxoWUnWoEfzhKJ87gpk87wkSieL73zC/uMkjjyksmngN59VU
-ODkUALrflWdHHynYiaA09zsDCjDuWDBXl17DNPV9lb4L0wLjJSklhuGsHo+wtW9k
-HJx+H972Qk79C4/ZuNiRx83xt8hruqlky2wkZKB9cxYTiizoD9CXwpBl+KGo5oFX
-ZjsDT4tnAHMa69yUoA==
------END CERTIFICATE-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/manifest.json b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/manifest.json
deleted file mode 100644
index d1b5a60d..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.test.pony",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/pony_test.cc b/tests/testdata/sharedlibs/build/com.android.apex.test.pony/pony_test.cc
deleted file mode 100644
index 761d2410..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.pony/pony_test.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <iostream>
-#include <string>
-
-#include "sharedlibstest.h"
-
-// This parameter gets modified by the build_artifacts.sh script.
-#define FINGERPRINT "VERSION_XXX"
-
-int main() {
- std::cout << "PONY_" << FINGERPRINT << " "
- << sharedlibstest::getSharedLibsTestFingerprint();
- return 0;
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/Android.bp b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/Android.bp
deleted file mode 100644
index 78816364..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/Android.bp
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.test.sharedlibs.key",
- public_key: "com.android.apex.test.sharedlibs.avbpubkey",
- private_key: "com.android.apex.test.sharedlibs.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.test.sharedlibs.certificate",
- certificate: "com.android.apex.test.sharedlibs",
-}
-
-apex {
- name: "com.android.apex.test.sharedlibs_stub",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test.sharedlibs.key",
- installable: false,
- // We want to force libc++.so to be available in this stub APEX, so put an empty binary.
- binaries: [ "noop" ],
- updatable: false,
- compile_multilib: "both",
- multilib: {
- both: {
- binaries: [
- "noop",
- ],
- },
- },
-}
-
-genrule {
- name: "com.android.apex.test.sharedlibs_generated",
- out: ["com.android.apex.test.sharedlibs_generated.apex"],
- defaults: ["apexer_test_host_tools_list"],
- dist: {
- targets: ["sharedlibs_test"],
- },
- srcs: [
- ":com.android.apex.test.sharedlibs_stub",
- "com.android.apex.test.sharedlibs.avbpubkey",
- "com.android.apex.test.sharedlibs.pem",
- "com.android.apex.test.sharedlibs.pk8",
- "com.android.apex.test.sharedlibs.x509.pem",
- ],
- tools: [
- "shared_libs_repack",
- ],
- cmd: "$(location shared_libs_repack) " +
- " --mode sharedlibs" +
- " --key $(location com.android.apex.test.sharedlibs.pem)" +
- " --input $(location :com.android.apex.test.sharedlibs_stub)" +
- " --output $(genDir)/com.android.apex.test.sharedlibs_generated.apex" +
- " --pk8key $(location com.android.apex.test.sharedlibs.pk8)" +
- " --pubkey $(location com.android.apex.test.sharedlibs.avbpubkey)" +
- " --x509key $(location com.android.apex.test.sharedlibs.x509.pem)" +
- " --tmpdir $(genDir)",
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.avbpubkey b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.avbpubkey
deleted file mode 100644
index b9a268d9..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pem
deleted file mode 100644
index ce939dcc..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEA2EG+ZcurX/nUUNhpbARwgQGgLTQkXU3yNYRk6t5WoXI6t3D2
-/bePE27RRzUhplvs5SZthRl3pgkzhZtajObm31VaUX5cXGveux1bQdtfTeMmEfPl
-TZ5bjM2aWV8QOpPQxUbL3tjCr2NB6sRX864nxl6RvFSgbVACBDVDBbdiHfq4UTGM
-oL0APyO9PCfPueFXwOJyW+gtMc50m+s46E/7Je0hmCfx5xlTjnue0CzF9oDPvat6
-72hX5JFOxefHPIVW2/IFnjzMsyCwjF4WyB2eZjmH3Mtx44Xn5hH/a+1wMvvcJmjx
-W4rexJVdDSr+RZTQC0Wr2eObk/6ib4gjXcjCr8cAdTB5g9IbKmGdOlHM3VavlkL9
-CMzNy+/w5UnqWrLJanC9nJba6PmwxG7n5doFODwB1ZypX3crrxjyT5saKN0KnSF3
-Ux3yt8SPnAr5QZ01ta4H26I65YwQi+Bqf/MOy+DgEDv3GEUTGLvK5YK2sDSWdIr4
-s3NRpkkUpAo/RZsqlxYCkYXtrdngP5r1ej0+uuzXt8cqXytcTqMpJzwDtNvlJiRG
-iqYzQZE+p3JrLgUTnT+clezOU4SbbaK17z+gLFoy9rs15ChF+VM0GFeuWh0pTOv8
-UfpsOZrI4Cwgr1q8oUGhcXwj6cgqdxzlrRFqb7no6L0rajk2dQLBoCFIV4ECAwEA
-AQKCAgAgHQMtEqWMRwkkSD6/b5lVTux+SfPsdxq0n8hsqD+tEc1uWDQVUSDJ/fbN
-4DHzBkuTa7VvwmxmF4+zE3LK4a7/EymqWF1WzB3zI1Td3rm0UzrgB5vRfuaRbiax
-htBeIn0qDm1P1lhyuwaa2jVFVmNJrdluYhLAqNTj0xT00FqdoRGl3PnJFMfomGIN
-gMv0CmaBmh7pTv0HHGVske2NcfMVmrUWZzgg3T3vNqRKvZtYE6DFxaUn0BLdOka8
-VMLdVd+kIbh72wN6xivxbDdt2BghjgGC5CMxaj0ZiSqo2EWFDKmQepz8vw59msCK
-qAvCQWrzgZEXdhkwTOvKLCk0UA+4zJoZ1hF3tZWStftqHB+zl1nsz3H8vBHzUaGJ
-1ufJqBZrmKqJvMEMlxoV+A8ftV/SZTmdXrEb/CNLGAfNdf8mhjc5hU58HLQPHQxA
-3IAj1Jyllc5hZHYXKAvu89ift0ZxZel8Nim+STmzpXiTvhia8+NEJlbOIp7JJf9L
-OOhj33PUiIR9e2iPOrhPOkV4o3HVW/Dpwu2P1DSqOIoGxB0zFE+eZGGf9HVNOyy9
-xUUGRpzdD8M09gnI3Yszabo2HjKdKYQdmoSc7jzMMwvQGd9Zt08KvpsWj8mry7l9
-VVy8h4rWlxmJtC8aXOHI5thV/4jmwfRYbDEzh4Qt2XxVQCyvUQKCAQEA9uviNj0Q
-FWtpeYULYMksz63JryaPeI3wAJtz6efYTcJ025qobTiHhoIER3TInsBBUQ3/YRYy
-ZBtCeKpLxYA81IabIX9lO757RMslEb5KeD3Da2HqNnrh3hyRXgXXcUMbed8JunlC
-5FRCRafikkj5ABvLHB9AYgAhS/vnTGQ7+XgpFsYi1kUGbJw+t4ly/ydWLjs5XoY7
-JdAuwnI/T8z31yYGG8T3oMSQV+BXT1doGNalKGupGMrUyvvqJQvScvxsVSWS8cRS
-A1Xu91R0oMYhwnUkMZc7qYEVdGqcXFagSbnXufT4J7Bw+H7wbY17fYOC3cGkh3AK
-FCa1d74Zd/3aswKCAQEA4DU7vukSOSDAf1hChkYXPzUJdrk31AVfeISYZmKqYah6
-65I2kzOnaszDQRg11wHXHSRhU0oVQxA77VTQBNQzOy+F7oB3o0cuQ+n6X5U8QQy4
-2dmgiYp3rkrqoH9KVn5VsYdwyYQHmE1IVMazo2YByv2N7aq4KN0MEgYUzizF38jX
-hf7ubQA7mGr9I0Wm1keQJ1m9VZ06mPKLfG70LViJAAvCYzSLY/31FBGVNq4JlreP
-EI4hgrYv7tzU6BqzrIdAmFOYOOsdRnUUW9+OhVzreU2EBAAmjK1jWa6FFAXGJEhi
-/qyO2suvNdWsIGxfqt5yhPMevMqjyEPmvwpLF+5u+wKCAQEAj9ShZVS2bLOvsdB0
-60DkMGkcBUGh6uhK+B+VKpgZYFo4Nb9mApEeKJTNp034mriEk5FixAvo+HUEiEMy
-de4YAPgTnzSVJHL1XQI0Kpy8xkO79G4JvwhfT0E20Bz4/QnJFHl+Mjf2ZghKvkZn
-7SxClvSZoFz35N4MhzVJ6y6r3MpIrPJnUobMkjGFOuX+rXAdfDqVVWE9TO5yfmOM
-S5CqgZGtlzlpwSUeq4GLejUA9w75D41+52knAMIzBrdXNBGjjQmhCeGAoF7LHxj8
-ArbG7X3MwnJEl50QgUqkoAj5v1hYuAJhFsVpWOagaEA0wcz8Su5ER3xU8p4FsKV0
-MngVjwKCAQEAqVuMpcioWz7CKW8h0Qtgw/3sCCIgaaclVoPSGoSs7te1AfyP/OEn
-tSS22JTRFnftZbX1TlTHesDog31tJDil+i8Lm/yuYkeCSwqSdWDlAr35Y5VgDoTp
-ol40nMeJ/4uub0s/hviURBcca+0sBGEpOYwNiVlLgpJ2a6bsUFDBpyiupCjNMMjc
-O2WVkO8r9vBXk2HWArWhbabIdlXZW+dklQRM8WLfZ8iNN3uQmp0b4R0GlBrIdVPp
-ISTuLeT9k3UW9fkvIs92baJCnqNfpJ1rwVUsQ1lZxSmzwipxm45A/WcwX+84eU0i
-LCgavOMf4JHnL0X2EeV/kea4hdXgo1MXwQKCAQEApKpBnJ2DPxN/I0cHbOFLH1rS
-A3lZvx0iOz7AFVK9laJ/794s5RdugXQ0MO4D0u+QrYN/Q3GnMpuNmHM8FRRNRIte
-jdpPmFLyPOrqOCaeISmMnwZl1GZtOjZwOWRWP/7pK8cv6bI4H8tDyYq9T3b0K+TK
-mqhqoHyN4aNrLCxggmhFS8wlK5UmuwJRfbAx4KGbfYk7fy4THkGjn5ZL3q9PO9Fa
-1jWsiBFdnmRQvD4svnTswPEts/rJ9o1P5+AnWtVKK7Npq9eOFhPRJ3R3hruHJath
-Cw999aol+hd093kcd7RzRmRjxUZ6oKxs1yRF7o9QQxnsmHRUT79Yy9LBOprvVA==
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pk8 b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pk8
deleted file mode 100644
index 933eb474..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.x509.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.x509.pem
deleted file mode 100644
index 95f96af8..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/com.android.apex.test.sharedlibs.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF5TCCA80CFBhOpuxTEQRD+MtXkeI8yP5rnPrwMA0GCSqGSIb3DQEBCwUAMIGt
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEpMCcGA1UEAwwgY29t
-LmFuZHJvaWQuYXBleC50ZXN0LnNoYXJlZGxpYnMwIBcNMjAxMDA1MTYzMzIwWhgP
-NDc1ODA5MDExNjMzMjBaMIGtMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv
-cm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQ
-MA4GA1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lk
-LmNvbTEpMCcGA1UEAwwgY29tLmFuZHJvaWQuYXBleC50ZXN0LnNoYXJlZGxpYnMw
-ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDjKxHP9SI0nMgAqYsSueNU
-042arnj7pjdzhqHhRWr8Ub0mwMXx0ulkgZcnhCbdg52670T2wPhl/xi4/HL7PybU
-sjt1QsjOaYcDdSrdxnsPe4RXZG4aE/+z06pm7TJ2jMGjJzS9x4AXbFNBxLsLp+gk
-fuxhpGQklgymRUojtUFMWhnXURQz5wyYJGUrV32FpOo5JKtO4A42pNhcHNBzeQp0
-LVAwcQalmxra1maf0PXTg6L4yukyNzfLYcukjkQilzrkWGPqGexCzLF+WXiuznNj
-BqPguKXvdsmSUIqAKGw6QHnuD6cAm3d2CuMzd4fjdOwzxFtfDEXS8f8ai/K+UEvx
-eqf8eXV0cpKROrbf0CafcUli/3CKIc3UXoQr5kx4LSp0eJHOyaoGEF3Dex/k0dgJ
-O80nNGTydhwvfMoZ4MOm+4yzDTqKu/Hw2ebM9po3vsfF3oy/hjEX0CaS4DnKDugg
-WUwAbTHG5k/lbzy6mkjRDxwSzn6sDrhHM1rs45thiQF9hfZuDwUbaGmxFAq8+Gtu
-xcr6bhryxaiO10MdMHI5KP1ZfZT49c+K8oVlTOsHxxxSK3eiQOs4k8A0jef7gfTP
-rnDKbdq7JHr73bHXv495UtgZMCKtS3p4kvHs5PYblWvJmYImMrLjqdtuckYOeEIO
-2N+79Rm8YAItX+SigohnZwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQAiJdApc590
-zoYl2w6NOj1xMljzta5Ld92lbJ3O4r1IoFQ6p+bSuV5RlPEC/kzR1G2WrZf66IrW
-UOSxtDjY6Bt1GKO949BKTp4/gdrnanst7ai5VnPeGWstUIEJ5SmF7C9QBhWnGnFT
-9zGdtbKnkcreZ81yabbNwAAwZWgX5hfkLSuMu7SzgLnzVDQOvbg96esWCbbBNPAl
-KhZb5Bzc42TDlUxWfqIC0Of3GjcLu1Ukn4fwFphMD4wGoHIgpGD6975BVWESpmnV
-tPDwiI+02Nha1aySZr/TiTId0AUucb6fqySqjCbOowv3DimKt+anwZjk1k/12TLb
-Uro5nOPbWwQkQws7tnfNb8VBWoGNc+SJbh260rhv7gpwsvXOdbKbyR7mSqXylreh
-DBUd/UL2eR1IrMuixK4bvmfVd7y+lxYKutEk+ifwSEuAubcbZ/dKH4PzjRnu1evv
-4M/1sLH4LRd+qHoR4ylopX8dWn3xh2Xq9KFrnTXRk1nd1YeGqcyTz+H7bBhYZKLO
-vPYTUb8ZYc/h0VGaABVywnb8wWZH4Op7ytKDybV2PGjhdLWaA3Y758ySkEab80ye
-XSuSPevgTDc7ZV3/Ijs7cW6+XVKnWWl4H7DQxG4B9vWrKl0YejNJBUNaXoE5t1hN
-TG2GM5D9sA/8HiW1JygwH0CBXMT5drYYjA==
------END CERTIFICATE-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/manifest.json b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/manifest.json
deleted file mode 100644
index abdb7c42..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.test.sharedlibs",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/Android.bp b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/Android.bp
deleted file mode 100644
index 9e803e32..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/Android.bp
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.android.apex.test.sharedlibs_secondary.key",
- public_key: "com.android.apex.test.sharedlibs_secondary.avbpubkey",
- private_key: "com.android.apex.test.sharedlibs_secondary.pem",
-}
-
-android_app_certificate {
- name: "com.android.apex.test.sharedlibs_secondary.certificate",
- certificate: "com.android.apex.test.sharedlibs_secondary",
-}
-
-apex {
- name: "com.android.apex.test.sharedlibs_secondary_stub",
- manifest: "manifest.json",
- file_contexts: ":apex.test-file_contexts",
- key: "com.android.apex.test.sharedlibs_secondary.key",
- installable: false,
- // We want to force libc++.so to be available in this stub APEX, so put an empty binary.
- binaries: [ "noop" ],
- updatable: false,
-}
-
-genrule {
- name: "com.android.apex.test.sharedlibs_secondary_generated",
- out: ["com.android.apex.test.sharedlibs_secondary_generated.apex"],
- defaults: ["apexer_test_host_tools_list"],
- dist: {
- targets: ["sharedlibs_test"],
- },
- srcs: [
- ":com.android.apex.test.sharedlibs_secondary_stub",
- "com.android.apex.test.sharedlibs_secondary.avbpubkey",
- "com.android.apex.test.sharedlibs_secondary.pem",
- "com.android.apex.test.sharedlibs_secondary.pk8",
- "com.android.apex.test.sharedlibs_secondary.x509.pem",
- ],
- tools: [
- "shared_libs_repack",
- ],
- cmd: "$(location shared_libs_repack) " +
- " --mode sharedlibs" +
- " --key $(location com.android.apex.test.sharedlibs_secondary.pem)" +
- " --input $(location :com.android.apex.test.sharedlibs_secondary_stub)" +
- " --output $(genDir)/com.android.apex.test.sharedlibs_secondary_generated.apex" +
- " --pk8key $(location com.android.apex.test.sharedlibs_secondary.pk8)" +
- " --pubkey $(location com.android.apex.test.sharedlibs_secondary.avbpubkey)" +
- " --x509key $(location com.android.apex.test.sharedlibs_secondary.x509.pem)" +
- " --tmpdir $(genDir)",
-}
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.avbpubkey b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.avbpubkey
deleted file mode 100644
index 3ccad0fa..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pem
deleted file mode 100644
index 5d4e1e1d..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEA2U7XN6RmrgLci4ZK2Osai9MqNIfx0gBX43DeIt6/1mQ5T590
-016wrGN6Oux0+LcdPU4PmpcyHw8+JVgdZjxG5c4icfWEuuc3Y+Pb6/FhvNwNrN5U
-wx7/DFGyEWaRZEe3pk6oDETSYvY5CzQjrFz+mDDwNnho0zxsRD74GWumQOkdAg0W
-7ihUq4/gCnjx+SeijTJAZcN0+oSldRa8+yN5zYdtO9gt9PGZLr87pvIFbcKp8QIT
-sReN9eFoLHYYktq5y4YXIhhV7W0imsPzAq6gtzHC6+qgDPCvwD6/GTvGHgF+DEUl
-/NuQgqgeVrFOEnHZ5qsawRwVeVq6sRd2ZQUdj+ix5KTS9/iKpg/cyLHCaXzEWWcZ
-DtKnZKxdFTyXa4w+UshQkKDHPYOKfOXLaTTywz9oAZNDBQsLjUUIDZhyxRq7a5Zk
-gUi5zG+Wx6r46pdSmMb76Qa2vasMQUYFoRINRfrsU6EJp55fjWCDzFXMIdm8nSkz
-4DY6T+XLu76zAMrZZPHrQle2D5zi/mu2yvbHi0sbujUCFBFrPpLkaD8TE1gqxqfh
-p5+xXD8tal6Mj7exLvRCadNaQ1R8CtcZhVxtUPmGVwlUZ6aF1QpARQtfZuVBEiut
-kyfTb9ns8r3xmxsUOSwJA6SgRuN0gvXIfDnNumDaP9dkuGE98uQpTu8kZbsCAwEA
-AQKCAgEAg0oR1yk5bAqIirdxAwtP94h16FT18eWJM/2eB71Cc9oLkiKJp6Z+4Tgc
-wfrYVOf0/3PpE4IjowZHirJo2Lq0LuVShD1MmstU+MHSvgMRBNSCYp3U4ioY961o
-AwFP+CEoQI8nEnqGDYorPqyanOl2XCa9CnvHAVBxLO5KYLlcMb1lbDbSUsMFHL4J
-IuqdbuXWXK4uoAzt4OlBObOqK6TsUxNuGIjsgx9waADbnmp8gyroF5ckpIrRlus/
-UBVtlVQWinMSCORhDdgw3wZiDI3KxcOHu5b+abMEzAZc2Hb3pGtMZ0djwxg4f+fo
-pIHs5FHqz2Uy/dbk1nPNdW7ydegYShuQmsvbOT6R8Qi25c9SiirXKOtdCM50JTW7
-SRaReqhiy828m9DOrwSXXiHrmyNevpwGQtRELGi14rgPqnpuUNaOmMEGAstQ+xcU
-Hl0DVuxWXN37iEKa4zv/LKwRzBVxlrSC1M3ufiOi2tVl5btMrdz5jZwDLYQxI7TX
-Nu0l/tEWD98/sJyOk4bmGUFrD5+oBpPGw/MrK6k7DmJjp8W1NRiiIACI/flzRWcA
-la7lPk23kG0/lmrWY87NQhEaPR9RMqmizlnF3VzWyDxXgZcn4ucjRmH7qhQLsZCC
-VIEI3oPoQSd7w+pHghLTA4R0KqW2ur/d05mkOmLfGnL27wPqaJECggEBAPX2tgHr
-DLIapja0HtxYNx0I5H/lHi3bzBI426h7317oIQpASKsqaIu/jOSDt5gLC0g+qSJi
-gT/l454bkdN4lTAMvY+3vJg3cN4U8J9GAejZi2X23Hed1QVuBSckz3CrHanqVBMN
-Nj9FsfQpqLJpewVqqdKR9rK+1ZNyMWfEO9M3pxlpZyWhPHg7KtbqBo0hS5Stlqpy
-xOo4nF4WC+OGNUo02R12ETJM4AmMs28Z5oNYZZ6K4cqKReNcDqt891ryXrow6aq9
-JBYz8sCeBQSTnPNnhbLJH/YOVMlhdAJhBcxEDbNKM6vmFQOuBEp12tjQoXsiv54C
-uBou7aRft8uGeHMCggEBAOIszCN1ZvD+xbaLDtKgPrAuDVRaZuZ9vb2TVB7Gcpto
-hCXU5GoapqQgjGplsXOQ1FMRozeRL4lQWfPfiueLAV3AeIHm0qjD2aanhJPvPrnb
-UCOdWRID99q9/s6bP98XiDseZiTHNlWitwpbWPAvmW2/08otmf4TgeLrA8p75CtK
-qJXU7o7fWTBFHF238rusK3N9t0Vikb0Cx1xDui6b5PeWtqAREV1/swP0J0av1fwK
-OuvZ8VdUjb5KMUMtGgMEWA277kYuryalu+oQH+bfe3XXUJS7fAI7GlokVqhJ8CLZ
-eSSZDtdqHib968cA4wr55nt1rEiDWzG7f2GeZra6s5kCggEAN53QrABdP4ydFvOF
-oudjlvIi0PSa7V2s+FXY/XD9IjW0+t9sTx/owejPUACkrAGbTHu2vOqvNSajYGX1
-hG7YtSO8XVn7kCPBJsZvXmRzHBbM2YKHeZi7yV2GVsKREXXv4DL3TdOH96inw4ED
-/0uwoJnsyots0CAspQmGOGN775e+9hUKWMzrongmiLAkSRdFQto5nlMTSa8BVJkB
-mTIIrL3kdi/zVX9ijWY+UJn3sK11VPMseSLpCK8RNh+swujZGJrky1G3bjnS41EX
-62ABdlxrM/EchAPbkimyFLOhnv2oZ2kY4/7Ds7BOkhOyJ6KNUQ2bbHxK6si/vZJT
-OfcvFwKCAQEA0nnVzvmmPocY/vMRbDjrnZB9nw4xzDUfqZe9JJaQeMcekwY3OfZr
-NTmE8k6IgH8618MGHOPjVOmNjEFvRmI5d0Fx45EmYR9BILGr0u9FdDf/r+Txyq4e
-rVU6FpKrMbT4deuoKnmourCdnem8LmhdY6CsOu2M7MDCkqUZ9gitIQxtLmHlTtfS
-a/UknKJeJP/nv6YyM0OzVC2N0PLGBDHXNgDvGq5HdrcrpHZFRqbDf7UVd/5tdVOe
-RINOrLEAD+au+rj02CMBo/l/kiZHSdaXUeZ5eq+ui3Ts5Q4EBsAn1IaFEeXNxfFe
-9fI+xAazQrekISg0l5aF+xX9SJ7b/xhnoQKCAQEA7vvi5zUalTNRreeExX0wiKRj
-sCvUhQoykimKpWzSUg6DpdF+DhK59/ERVSkA4C2WwHEYqZdrgEKnmqOZQkqgtq1B
-O5xxioRtn6VsZRYjaRw5Cq/Ej1AeDgQr+SH29kBtym81mMBbkPnFoBxKCjuuVn9u
-4Kjg910wxErzipjDB2alfkuFCqNz9IZd2XSmpmGhpE/hBlZP4slJXTX77nIxRTHB
-Vq5gehJoEhLNsFAu34BgrXRIhzSBALdalbepNrHh2br87rJpjxeRASbuyyNdgZyl
-wk+aJxHo6RpMD7xHxsxv5kmRcLITPICk+ysLZ5ZHMaEuGIVFxDdOoFGylRV4wQ==
------END RSA PRIVATE KEY-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pk8 b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pk8
deleted file mode 100644
index 2eee60f0..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.x509.pem b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.x509.pem
deleted file mode 100644
index 74dd144f..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/com.android.apex.test.sharedlibs_secondary.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF+TCCA+ECFGnrAltwoToH4tPw7aN36oFBb8zxMA0GCSqGSIb3DQEBCwUAMIG3
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEzMDEGA1UEAwwqY29t
-LmFuZHJvaWQuYXBleC50ZXN0LnNoYXJlZGxpYnNfc2Vjb25kYXJ5MCAXDTIwMTEy
-NzEwNTE0N1oYDzQ3NTgxMDI0MTA1MTQ3WjCBtzELMAkGA1UEBhMCVVMxEzARBgNV
-BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoM
-B0FuZHJvaWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJv
-aWRAYW5kcm9pZC5jb20xMzAxBgNVBAMMKmNvbS5hbmRyb2lkLmFwZXgudGVzdC5z
-aGFyZWRsaWJzX3NlY29uZGFyeTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
-ggIBANLZWZWEtzYdHL+yio1j16r4aDCtRMdTFT8dWhXi/khEodZ9PZHV73eAWl7o
-5AHO2h/4To6hqxKlzl5lbNWT/Xu7OFvhaqy1gD2XiOyZxqNITba3SV4qDnWYAMHc
-JdcYKv/F5UMeiXQueBJ2HaWcWoZPOmHwfJbMxSvr+LOwtI1vvR38G68uIFyR0Rlb
-jQggv/WsudLlB++0c+jOtPLmD65h7dXXXlqGvu+7Rt5GWYxtN/sIZ0KPqtLk1JQD
-nIa5E05UDcqfGnyo5mz7t9Tj+4dyH/B+fY9JMXJMNMcy47CfdhR4NfnsUTmLqXRc
-fOwSRfuodMbCd4WAgA6e6KHjlBO89NOA3QamQDyhT3XURrMCMeRQvb155dEoHCs5
-FDBu138hku5aylLfiHkEHfwEDu9wsWAd3CWsBfqOMAEQG7AB+4lCaGVhYKMxKWjM
-Pdqzfy47ODHrMEprfrYlOkdJ+9Fu9HJZvEMQXh7tleoOSIuvqmL1ksRSUXsE2JHJ
-KC/hoBCcVsMsujxn7tQilB0e+TLDml08dIrrGLV1UiqU/80q0MC2Bwinne21KAtY
-UMJd2pImZr3H4z7J6wQmuevvcZksaEwWXtQzIoXenmaSW9bwqVy6k+DushOghGy/
-CAeeJAc35sUFsa8ysp0aPARZIqCYiesGdiO/wW+UVibo2JyLAgMBAAEwDQYJKoZI
-hvcNAQELBQADggIBAFE7g7ZTGqSDpJ/PyLKLp+oItJ+JNJVd5UbLvLMiA4t7QTtE
-0aPCxMGybJGeYbs16OB3ZqWZlVyjirEXAmSH2HZxO1uIeDcCjndSCfz+oxmBs27j
-C8t5BzExaelpP/J9nyKObzaZ1EJ+KdTqPVmrhgN8uUU82mRt5oJZuxGbHNdbzxGh
-zXHi+q5oecWaiBFDSF9pvKFp7nvbW4MIaGcm9Flx9JdYhgzRfXeJV7EsKE2Kxflj
-nojgyUzjvkNTa/wRASgwr/hgpPL0mpD9gSejxOA5wRGLknDlIfsfEh5cJTFiBO5b
-MZiSHe7Ds+8GWyKk8y8G2YtB0Z5HxD91rzPA2W/JEDHhoI8jT47I3JuOyJMjC9DV
-kAu4nhReBilOmU+oS1Iv+TheslPGLEZ7JOHsmyQh5X5H0D+YH7H9L8BOWEBlNBhy
-zPlMKNWsvMZmem/fhuXK1xUUWZuqoj2tF2fMmiYf6fSNRb7dQI10uBslxX7myNyj
-pqZNSk/E9V650UC5JixpOtPxrSsPXifOLwB7OEkT5v7v/MoBqlSfqve9/62Ktnuc
-NC9Rt3fqU+VOs6tVUPGnSJRDc2uhvU8rJZN86e1xX8d7lhHZwO8sJtaxZ2KYduM1
-ncEODTAxK7wQ041CS7H/kULG6CEPnIg0a1ZjASWhQRbQ1Rj/Y40CmHxThnyx
------END CERTIFICATE-----
diff --git a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/manifest.json b/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/manifest.json
deleted file mode 100644
index 80da6f14..00000000
--- a/tests/testdata/sharedlibs/build/com.android.apex.test.sharedlibs_secondary/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.apex.test.sharedlibs_secondary",
- "version": 1
-}
diff --git a/tests/testdata/sharedlibs/build/noop.cc b/tests/testdata/sharedlibs/build/noop.cc
deleted file mode 100644
index cfd2ef57..00000000
--- a/tests/testdata/sharedlibs/build/noop.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <iostream>
-
-#include "sharedlibstest.h"
-
-int main() {
- std::cout << "This binary should never be executed";
- std::cout << sharedlibstest::getSharedLibsTestFingerprint();
- return 1;
-} \ No newline at end of file
diff --git a/tests/testdata/sharedlibs/build/shared_libs_repack.py b/tests/testdata/sharedlibs/build/shared_libs_repack.py
deleted file mode 100644
index 31b9a6bc..00000000
--- a/tests/testdata/sharedlibs/build/shared_libs_repack.py
+++ /dev/null
@@ -1,421 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Repacking tool for Shared Libs APEX testing."""
-
-import argparse
-import hashlib
-import logging
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-from zipfile import ZipFile
-
-import apex_build_info_pb2
-import apex_manifest_pb2
-
-logger = logging.getLogger(__name__)
-
-def comma_separated_list(arg):
- return arg.split(',')
-
-
-def parse_args(argv):
- parser = argparse.ArgumentParser(
- description='Repacking tool for Shared Libs APEX testing')
-
- parser.add_argument('--input', required=True, help='Input file')
- parser.add_argument('--output', required=True, help='Output file')
- parser.add_argument(
- '--key', required=True, help='Path to the private avb key file')
- parser.add_argument(
- '--pk8key',
- required=True,
- help='Path to the private apk key file in pk8 format')
- parser.add_argument(
- '--pubkey', required=True, help='Path to the public avb key file')
- parser.add_argument(
- '--tmpdir', required=True, help='Temporary directory to use')
- parser.add_argument(
- '--x509key',
- required=True,
- help='Path to the public apk key file in x509 format')
- parser.add_argument(
- '--mode', default='strip', choices=['strip', 'sharedlibs'])
- parser.add_argument(
- '--libs',
- default='libc++.so,libsharedlibtest.so',
- type=comma_separated_list,
- help='Libraries to strip/repack. Expects comma separated values.')
- return parser.parse_args(argv)
-
-
-def run(args, verbose=None, **kwargs):
- """Creates and returns a subprocess.Popen object.
-
- Args:
- args: The command represented as a list of strings.
- verbose: Whether the commands should be shown. Default to the global
- verbosity if unspecified.
- kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
- stdin, etc. stdout and stderr will default to subprocess.PIPE and
- subprocess.STDOUT respectively unless caller specifies any of them.
- universal_newlines will default to True, as most of the users in
- releasetools expect string output.
-
- Returns:
- A subprocess.Popen object.
- """
- if 'stdout' not in kwargs and 'stderr' not in kwargs:
- kwargs['stdout'] = subprocess.PIPE
- kwargs['stderr'] = subprocess.STDOUT
- if 'universal_newlines' not in kwargs:
- kwargs['universal_newlines'] = True
- if verbose:
- logger.info(' Running: \"%s\"', ' '.join(args))
- return subprocess.Popen(args, **kwargs)
-
-
-def run_and_check_output(args, verbose=None, **kwargs):
- """Runs the given command and returns the output.
-
- Args:
- args: The command represented as a list of strings.
- verbose: Whether the commands should be shown. Default to the global
- verbosity if unspecified.
- kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
- stdin, etc. stdout and stderr will default to subprocess.PIPE and
- subprocess.STDOUT respectively unless caller specifies any of them.
-
- Returns:
- The output string.
-
- Raises:
- ExternalError: On non-zero exit from the command.
- """
- proc = run(args, verbose=verbose, **kwargs)
- output, _ = proc.communicate()
- if output is None:
- output = ''
- # Don't log any if caller explicitly says so.
- if verbose:
- logger.info('%s', output.rstrip())
- if proc.returncode != 0:
- raise RuntimeError(
- 'Failed to run command \'{}\' (exit code {}):\n{}'.format(
- args, proc.returncode, output))
- return output
-
-
-def get_container_files(apex_file_path, tmpdir):
- dir_name = tempfile.mkdtemp(prefix='container_files_', dir=tmpdir)
- with ZipFile(apex_file_path, 'r') as zip_obj:
- zip_obj.extractall(path=dir_name)
- files = {}
- for i in [
- 'apex_manifest.json', 'apex_manifest.pb', 'apex_build_info.pb', 'assets',
- 'apex_payload.img', 'apex_payload.zip'
- ]:
- file_path = os.path.join(dir_name, i)
- if os.path.exists(file_path):
- files[i] = file_path
-
- image_file = files.get('apex_payload.img')
- if image_file is None:
- image_file = files.get('apex_payload.zip')
-
- files['apex_payload'] = image_file
-
- return files
-
-
-def extract_payload_from_img(img_file_path, tmpdir):
- dir_name = tempfile.mkdtemp(prefix='extracted_payload_', dir=tmpdir)
- cmd = [
- _get_host_tools_path('debugfs_static'), '-R',
- 'rdump ./ %s' % dir_name, img_file_path
- ]
- run_and_check_output(cmd)
-
- # Remove payload files added by apexer and e2fs tools.
- for i in ['apex_manifest.json', 'apex_manifest.pb']:
- if os.path.exists(os.path.join(dir_name, i)):
- os.remove(os.path.join(dir_name, i))
- if os.path.isdir(os.path.join(dir_name, 'lost+found')):
- shutil.rmtree(os.path.join(dir_name, 'lost+found'))
- return dir_name
-
-
-def run_apexer(container_files, payload_dir, key_path, pubkey_path, tmpdir):
- apexer_cmd = _get_host_tools_path('apexer')
- cmd = [
- apexer_cmd, '--force', '--include_build_info', '--do_not_check_keyname'
- ]
- cmd.extend([
- '--apexer_tool_path',
- os.path.dirname(apexer_cmd) + ':prebuilts/sdk/tools/linux/bin'
- ])
- cmd.extend(['--manifest', container_files['apex_manifest.pb']])
- if 'apex_manifest.json' in container_files:
- cmd.extend(['--manifest_json', container_files['apex_manifest.json']])
- cmd.extend(['--build_info', container_files['apex_build_info.pb']])
- if 'assets' in container_files:
- cmd.extend(['--assets_dir', container_files['assets']])
- cmd.extend(['--key', key_path])
- cmd.extend(['--pubkey', pubkey_path])
-
- # Decide on output file name
- apex_suffix = '.apex.unsigned'
- fd, fn = tempfile.mkstemp(prefix='repacked_', suffix=apex_suffix, dir=tmpdir)
- os.close(fd)
- cmd.extend([payload_dir, fn])
-
- run_and_check_output(cmd)
- return fn
-
-
-def _get_java_toolchain():
- java_toolchain = 'java'
- if os.path.isfile('prebuilts/jdk/jdk11/linux-x86/bin/java'):
- java_toolchain = 'prebuilts/jdk/jdk11/linux-x86/bin/java'
-
- java_dep_lib = (
- os.path.join(os.path.dirname(_get_host_tools_path()), 'lib64') + ':' +
- os.path.join(os.path.dirname(_get_host_tools_path()), 'lib'))
-
- return [java_toolchain, java_dep_lib]
-
-
-def _get_host_tools_path(tool_name=None):
- # This script is located at e.g.
- # 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:
- return os.path.join(dirname, tool_name)
- return dirname
-
-
-def sign_apk_container(unsigned_apex, x509key_path, pk8key_path, tmpdir):
- fd, fn = tempfile.mkstemp(prefix='repacked_', suffix='.apex', dir=tmpdir)
- os.close(fd)
- java_toolchain, java_dep_lib = _get_java_toolchain()
-
- cmd = [
- java_toolchain, '-Djava.library.path=' + java_dep_lib, '-jar',
- os.path.join(
- os.path.dirname(_get_host_tools_path()), 'framework', 'signapk.jar'),
- '-a', '4096', x509key_path, pk8key_path, unsigned_apex, fn
- ]
- run_and_check_output(cmd)
- return fn
-
-
-def compute_sha512(file_path):
- block_size = 65536
- hashbuf = hashlib.sha512()
- with open(file_path, 'rb') as f:
- fb = f.read(block_size)
- while len(fb) > 0:
- hashbuf.update(fb)
- fb = f.read(block_size)
- return hashbuf.hexdigest()
-
-
-def parse_fs_config(fs_config):
- configs = fs_config.splitlines()
- # Result is set of configurations.
- # Each configuration is set of items as [file path, uid, gid, mode].
- # All items are stored as string.
- result = []
- for config in configs:
- result.append(config.split())
- return result
-
-
-def config_to_str(configs):
- result = ''
- for config in configs:
- result += ' '.join(config) + '\n'
- return result
-
-
-def _extract_lib_or_lib64(payload_dir, lib_full_path):
- # Figure out if this is lib or lib64:
- # Strip out the payload_dir and split by /
- libpath = lib_full_path[len(payload_dir):].lstrip('/').split('/')
- return libpath[0]
-
-
-def main(argv):
- args = parse_args(argv)
- apex_file_path = args.input
-
- container_files = get_container_files(apex_file_path, args.tmpdir)
- payload_dir = extract_payload_from_img(container_files['apex_payload.img'],
- args.tmpdir)
- libs = args.libs
- assert len(libs)> 0
-
- lib_paths = [os.path.join(payload_dir, lib_dir, lib)
- for lib_dir in ['lib', 'lib64']
- for lib in libs
- if os.path.exists(os.path.join(payload_dir, lib_dir, lib))]
-
- assert len(lib_paths) > 0
-
- lib_paths_hashes = [(lib, compute_sha512(lib)) for lib in lib_paths]
-
- if args.mode == 'strip':
- # Stripping mode. Add a reference to the version of libc++.so to the
- # requireSharedApexLibs entry in the manifest, and remove lib64/libc++.so
- # from the payload.
- pb = apex_manifest_pb2.ApexManifest()
- with open(container_files['apex_manifest.pb'], 'rb') as f:
- pb.ParseFromString(f.read())
- for lib_path_hash in lib_paths_hashes:
- basename = os.path.basename(lib_path_hash[0])
- libpath = _extract_lib_or_lib64(payload_dir, lib_path_hash[0])
- assert libpath in ('lib', 'lib64')
- pb.requireSharedApexLibs.append(os.path.join(libpath, basename) + ':'
- + lib_path_hash[1])
- # Replace existing library with symlink
- symlink_dst = os.path.join('/', 'apex', 'sharedlibs',
- libpath, basename, lib_path_hash[1],
- basename)
- os.remove(lib_path_hash[0])
- os.system('ln -s {0} {1}'.format(symlink_dst, lib_path_hash[0]))
- #
- # Example of resulting manifest:
- # ---
- # name: "com.android.apex.test.foo"
- # version: 1
- # requireNativeLibs: "libc.so"
- # requireNativeLibs: "libdl.so"
- # requireNativeLibs: "libm.so"
- # requireSharedApexLibs: "lib/libc++.so:23c5dd..."
- # requireSharedApexLibs: "lib/libsharedlibtest.so:870f38..."
- # requireSharedApexLibs: "lib64/libc++.so:72a584..."
- # requireSharedApexLibs: "lib64/libsharedlibtest.so:109015..."
- # --
- # To print uncomment the following:
- # from google.protobuf import text_format
- # print(text_format.MessageToString(pb))
- with open(container_files['apex_manifest.pb'], 'wb') as f:
- f.write(pb.SerializeToString())
-
- if args.mode == 'sharedlibs':
- # Sharedlibs mode. Mark in the APEX manifest that this package contains
- # shared libraries.
- pb = apex_manifest_pb2.ApexManifest()
- with open(container_files['apex_manifest.pb'], 'rb') as f:
- pb.ParseFromString(f.read())
- del pb.requireNativeLibs[:]
- pb.provideSharedApexLibs = True
- with open(container_files['apex_manifest.pb'], 'wb') as f:
- f.write(pb.SerializeToString())
-
- pb = apex_build_info_pb2.ApexBuildInfo()
- with open(container_files['apex_build_info.pb'], 'rb') as f:
- pb.ParseFromString(f.read())
-
- canned_fs_config = parse_fs_config(pb.canned_fs_config.decode('utf-8'))
-
- # Remove the bin directory from payload dir and from the canned_fs_config.
- shutil.rmtree(os.path.join(payload_dir, 'bin'))
- canned_fs_config = [config for config in canned_fs_config
- if not config[0].startswith('/bin')]
-
- # Remove from the canned_fs_config the entries we are about to relocate in
- # different dirs.
- source_lib_paths = [os.path.join('/', libpath, lib)
- for libpath in ['lib', 'lib64']
- for lib in libs]
- # We backup the fs config lines for the libraries we are going to relocate,
- # so we can set the same permissions later.
- canned_fs_config_original_lib = {config[0] : config
- for config in canned_fs_config
- if config[0] in source_lib_paths}
-
- canned_fs_config = [config for config in canned_fs_config
- if config[0] not in source_lib_paths]
-
- # We move any targeted library in lib64/ or lib/ to a directory named
- # /lib64/libNAME.so/${SHA512_OF_LIBCPP}/ or
- # /lib/libNAME.so/${SHA512_OF_LIBCPP}/
- #
- for lib_path_hash in lib_paths_hashes:
- basename = os.path.basename(lib_path_hash[0])
- libpath = _extract_lib_or_lib64(payload_dir, lib_path_hash[0])
- tmp_lib = os.path.join(payload_dir, libpath, basename + '.bak')
- shutil.move(lib_path_hash[0], tmp_lib)
- destdir = os.path.join(payload_dir, libpath, basename, lib_path_hash[1])
- os.makedirs(destdir)
- shutil.move(tmp_lib, os.path.join(destdir, basename))
-
- canned_fs_config.append(
- ['/' + libpath + '/' + basename, '0', '2000', '0755'])
- canned_fs_config.append(
- ['/' + libpath + '/' + basename + '/' + lib_path_hash[1],
- '0', '2000', '0755'])
-
- if os.path.join('/', libpath, basename) in canned_fs_config_original_lib:
- config = canned_fs_config_original_lib[os.path.join(
- '/',
- libpath,
- basename)]
- canned_fs_config.append([os.path.join('/', libpath, basename,
- lib_path_hash[1], basename),
- config[1], config[2], config[3]])
- else:
- canned_fs_config.append([os.path.join('/', libpath, basename,
- lib_path_hash[1], basename),
- '1000', '1000', '0644'])
-
- pb.canned_fs_config = config_to_str(canned_fs_config).encode('utf-8')
- with open(container_files['apex_build_info.pb'], 'wb') as f:
- f.write(pb.SerializeToString())
-
- try:
- for lib in lib_paths:
- os.rmdir(os.path.dirname(lib))
- except OSError:
- # Directory not empty, that's OK.
- pass
-
- repack_apex_file_path = run_apexer(container_files, payload_dir, args.key,
- args.pubkey, args.tmpdir)
-
- resigned_apex_file_path = sign_apk_container(repack_apex_file_path,
- args.x509key, args.pk8key,
- args.tmpdir)
-
- shutil.copyfile(resigned_apex_file_path, args.output)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/tests/testdata/sharedlibs/prebuilts/Android.bp b/tests/testdata/sharedlibs/prebuilts/Android.bp
deleted file mode 100644
index 1ef2977e..00000000
--- a/tests/testdata/sharedlibs/prebuilts/Android.bp
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file is auto-generated by
-// ./system/apex/tests/testdata/sharedlibs/build/build_artifacts.sh
-// Do NOT edit manually.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.bar_stripped.v1.libvX_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.bar_stripped.v1.libvX.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.bar_stripped.v1.libvX.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.bar_stripped.v1.libvX.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.bar_stripped.v1.libvX.apex",
- },
- },
- filename: "com.android.apex.test.bar_stripped.v1.libvX.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.bar_stripped.v2.libvY_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.bar_stripped.v2.libvY.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.bar_stripped.v2.libvY.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.bar_stripped.v2.libvY.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.bar_stripped.v2.libvY.apex",
- },
- },
- filename: "com.android.apex.test.bar_stripped.v2.libvY.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.bar.v1.libvX_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.bar.v1.libvX.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.bar.v1.libvX.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.bar.v1.libvX.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.bar.v1.libvX.apex",
- },
- },
- filename: "com.android.apex.test.bar.v1.libvX.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.bar.v2.libvY_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.bar.v2.libvY.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.bar.v2.libvY.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.bar.v2.libvY.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.bar.v2.libvY.apex",
- },
- },
- filename: "com.android.apex.test.bar.v2.libvY.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.baz_stripped.v1.libvX_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.baz_stripped.v1.libvX.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.baz_stripped.v1.libvX.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.baz_stripped.v1.libvX.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.baz_stripped.v1.libvX.apex",
- },
- },
- filename: "com.android.apex.test.baz_stripped.v1.libvX.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.foo_stripped.v1.libvX_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.foo_stripped.v1.libvX.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.foo_stripped.v1.libvX.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.foo_stripped.v1.libvX.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.foo_stripped.v1.libvX.apex",
- },
- },
- filename: "com.android.apex.test.foo_stripped.v1.libvX.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.foo_stripped.v2.libvY_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.foo_stripped.v2.libvY.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.foo_stripped.v2.libvY.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.foo_stripped.v2.libvY.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.foo_stripped.v2.libvY.apex",
- },
- },
- filename: "com.android.apex.test.foo_stripped.v2.libvY.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.foo.v1.libvX_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.foo.v1.libvX.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.foo.v1.libvX.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.foo.v1.libvX.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.foo.v1.libvX.apex",
- },
- },
- filename: "com.android.apex.test.foo.v1.libvX.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.foo.v2.libvY_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.foo.v2.libvY.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.foo.v2.libvY.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.foo.v2.libvY.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.foo.v2.libvY.apex",
- },
- },
- filename: "com.android.apex.test.foo.v2.libvY.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.pony_stripped.v1.libvZ_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.pony_stripped.v1.libvZ.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.pony_stripped.v1.libvZ.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.pony_stripped.v1.libvZ.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.pony_stripped.v1.libvZ.apex",
- },
- },
- filename: "com.android.apex.test.pony_stripped.v1.libvZ.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.pony.v1.libvZ_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.pony.v1.libvZ.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.pony.v1.libvZ.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.pony.v1.libvZ.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.pony.v1.libvZ.apex",
- },
- },
- filename: "com.android.apex.test.pony.v1.libvZ.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.sharedlibs_generated.v1.libvX_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
- },
- },
- filename: "com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.sharedlibs_generated.v2.libvY_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.sharedlibs_generated.v2.libvY.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.sharedlibs_generated.v2.libvY.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex",
- },
- },
- filename: "com.android.apex.test.sharedlibs_generated.v2.libvY.apex",
- installable: false,
-}
-
-prebuilt_apex {
- name: "com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ_prebuilt",
- arch: {
- arm: {
- src: "arm/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex",
- },
- arm64: {
- src: "arm64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex",
- },
- x86: {
- src: "x86/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex",
- },
- x86_64: {
- src: "x86_64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex",
- },
- },
- filename: "com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex",
- installable: false,
-}
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v1.libvX.apex
deleted file mode 100644
index 07fcff94..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v2.libvY.apex
deleted file mode 100644
index 2361fd60..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v1.libvX.apex
deleted file mode 100644
index 20bdd345..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v2.libvY.apex
deleted file mode 100644
index 67915351..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.bar_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.baz_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.baz_stripped.v1.libvX.apex
deleted file mode 100644
index e6405b42..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.baz_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v1.libvX.apex
deleted file mode 100644
index 799890ab..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v2.libvY.apex
deleted file mode 100644
index 906ec226..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v1.libvX.apex
deleted file mode 100644
index 5ee73835..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v2.libvY.apex
deleted file mode 100644
index c2f9f687..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.foo_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony.v1.libvZ.apex
deleted file mode 100644
index 323b81ff..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony_stripped.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony_stripped.v1.libvZ.apex
deleted file mode 100644
index 8a578ba0..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.pony_stripped.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
deleted file mode 100644
index 58e7f956..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
deleted file mode 100644
index b0385526..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
deleted file mode 100644
index 3ab73afa..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v1.libvX.apex
deleted file mode 100644
index c04a1691..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v2.libvY.apex
deleted file mode 100644
index 9bedfa25..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v1.libvX.apex
deleted file mode 100644
index a8459790..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v2.libvY.apex
deleted file mode 100644
index c8f89611..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.bar_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.baz_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.baz_stripped.v1.libvX.apex
deleted file mode 100644
index e2e5b708..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.baz_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v1.libvX.apex
deleted file mode 100644
index d6795a59..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v2.libvY.apex
deleted file mode 100644
index 65dcd649..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v1.libvX.apex
deleted file mode 100644
index 894afa22..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v2.libvY.apex
deleted file mode 100644
index c1ce6fad..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.foo_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony.v1.libvZ.apex
deleted file mode 100644
index 80c64239..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony_stripped.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony_stripped.v1.libvZ.apex
deleted file mode 100644
index 4d380da7..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.pony_stripped.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
deleted file mode 100644
index e0cf9e7c..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
deleted file mode 100644
index 93f24f25..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
deleted file mode 100644
index 21a6dc3c..00000000
--- a/tests/testdata/sharedlibs/prebuilts/arm64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v1.libvX.apex
deleted file mode 100644
index 4767f4a3..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v2.libvY.apex
deleted file mode 100644
index cff076ac..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v1.libvX.apex
deleted file mode 100644
index bca5c496..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v2.libvY.apex
deleted file mode 100644
index 01f822e9..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.bar_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.baz_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.baz_stripped.v1.libvX.apex
deleted file mode 100644
index 96248526..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.baz_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v1.libvX.apex
deleted file mode 100644
index 8b352bd0..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v2.libvY.apex
deleted file mode 100644
index 71cdc202..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v1.libvX.apex
deleted file mode 100644
index eccb3d4e..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v2.libvY.apex
deleted file mode 100644
index 0265ac95..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.foo_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony.v1.libvZ.apex
deleted file mode 100644
index ef1d1d90..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony_stripped.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony_stripped.v1.libvZ.apex
deleted file mode 100644
index 8439fe3c..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.pony_stripped.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
deleted file mode 100644
index 8ba0e5b4..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
deleted file mode 100644
index 2928193e..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
deleted file mode 100644
index e849bcd0..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v1.libvX.apex
deleted file mode 100644
index e733e1d2..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v2.libvY.apex
deleted file mode 100644
index 522b9c8e..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v1.libvX.apex
deleted file mode 100644
index eec0184b..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v2.libvY.apex
deleted file mode 100644
index cbd96978..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.bar_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.baz_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.baz_stripped.v1.libvX.apex
deleted file mode 100644
index b2ca4130..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.baz_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v1.libvX.apex
deleted file mode 100644
index 2f5a2c27..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v2.libvY.apex
deleted file mode 100644
index 1bc4774e..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v1.libvX.apex
deleted file mode 100644
index 77db6dff..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v2.libvY.apex
deleted file mode 100644
index 042d4bc4..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.foo_stripped.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony.v1.libvZ.apex
deleted file mode 100644
index 5a7c5fb3..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony_stripped.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony_stripped.v1.libvZ.apex
deleted file mode 100644
index bb99f7ef..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.pony_stripped.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
deleted file mode 100644
index 2ff31ca4..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v1.libvX.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
deleted file mode 100644
index 013f2754..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_generated.v2.libvY.apex
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex b/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
deleted file mode 100644
index 3c6cf339..00000000
--- a/tests/testdata/sharedlibs/prebuilts/x86_64/com.android.apex.test.sharedlibs_secondary_generated.v1.libvZ.apex
+++ /dev/null
Binary files differ
diff --git a/tests/util/com/android/tests/util/ModuleTestUtils.java b/tests/util/com/android/tests/util/ModuleTestUtils.java
new file mode 100644
index 00000000..8f62bc33
--- /dev/null
+++ b/tests/util/com/android/tests/util/ModuleTestUtils.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.tradefed.build.BuildInfoKey.BuildInfoFileKey;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.ITestDevice.ApexInfo;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.IRunUtil;
+import com.android.tradefed.util.RunUtil;
+import com.android.tradefed.util.SystemUtil.EnvVariable;
+
+import com.google.common.base.Stopwatch;
+
+import org.junit.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+public class ModuleTestUtils {
+ private static final String SHIM = "com.android.apex.cts.shim";
+ private static final String APEX_INFO_EXTRACT_REGEX =
+ ".*package:\\sname='(\\S+)\\'\\sversionCode='(\\d+)'\\s.*";
+
+ private static final Duration WAIT_FOR_SESSION_READY_TTL = Duration.ofSeconds(10);
+ private static final Duration SLEEP_FOR = Duration.ofMillis(200);
+
+ protected final Pattern mIsSessionReadyPattern =
+ Pattern.compile("(isReady = true)|(isStagedSessionReady = true)");
+ protected final Pattern mIsSessionAppliedPattern =
+ Pattern.compile("(isApplied = true)|(isStagedSessionApplied = true)");
+
+ private IRunUtil mRunUtil = new RunUtil();
+ private BaseHostJUnit4Test mTest;
+
+ private IBuildInfo getBuild() {
+ return mTest.getBuild();
+ }
+
+ public ModuleTestUtils(BaseHostJUnit4Test test) {
+ mTest = test;
+ }
+
+ /**
+ * Retrieve package name and version code from test apex file.
+ *
+ * @param apex input apex file to retrieve the info from
+ */
+ public ApexInfo getApexInfo(File apex) {
+ String aaptOutput = runCmd(String.format(
+ "aapt dump badging %s", apex.getAbsolutePath()));
+ String[] lines = aaptOutput.split("\n");
+ Pattern p = Pattern.compile(APEX_INFO_EXTRACT_REGEX);
+ for (String l : lines) {
+ Matcher m = p.matcher(l);
+ if (m.matches()) {
+ ApexInfo apexInfo = new ApexInfo(m.group(1), Long.parseLong(m.group(2)));
+ return apexInfo;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the test file.
+ *
+ * @param testFileName name of the file
+ */
+ public File getTestFile(String testFileName) throws IOException {
+ File testFile = null;
+
+ String testcasesPath = System.getenv(EnvVariable.ANDROID_HOST_OUT_TESTCASES.toString());
+ if (testcasesPath != null) {
+ testFile = searchTestFile(new File(testcasesPath), testFileName);
+ }
+ if (testFile != null) {
+ return testFile;
+ }
+
+ File hostLinkedDir = getBuild().getFile(BuildInfoFileKey.HOST_LINKED_DIR);
+ if (hostLinkedDir != null) {
+ testFile = searchTestFile(hostLinkedDir, testFileName);
+ }
+ if (testFile != null) {
+ return testFile;
+ }
+
+ // Find the file in the buildinfo.
+ File buildInfoFile = getBuild().getFile(testFileName);
+ if (buildInfoFile != null) {
+ return buildInfoFile;
+ }
+
+ throw new IOException("Cannot find " + testFileName);
+ }
+
+ private String runCmd(String cmd) {
+ CLog.d("About to run command: %s", cmd);
+ CommandResult result = mRunUtil.runTimedCmd(1000 * 60 * 5, cmd.split("\\s+"));
+ Assert.assertNotNull(result);
+ Assert.assertTrue(
+ String.format("Command %s failed", cmd),
+ result.getStatus().equals(CommandStatus.SUCCESS));
+ CLog.v("output:\n%s", result.getStdout());
+ return result.getStdout();
+ }
+
+ /**
+ * Searches the file with the given name under the given directory, returns null if not found.
+ */
+ private File searchTestFile(File baseSearchFile, String testFileName) {
+ if (baseSearchFile != null && baseSearchFile.isDirectory()) {
+ File testFile = FileUtil.findFile(baseSearchFile, testFileName);
+ if (testFile != null && testFile.isFile()) {
+ return testFile;
+ }
+ }
+ return null;
+ }
+
+ public void waitForStagedSessionReady() throws DeviceNotAvailableException {
+ // TODO: implement wait for session ready logic inside PackageManagerShellCommand instead.
+ boolean sessionReady = false;
+ Duration spentWaiting = Duration.ZERO;
+ while (spentWaiting.compareTo(WAIT_FOR_SESSION_READY_TTL) < 0) {
+ CommandResult res = mTest.getDevice().executeShellV2Command("pm get-stagedsessions");
+ Assert.assertEquals("", res.getStderr());
+ sessionReady = Stream.of(res.getStdout().split("\n")).anyMatch(this::isReadyNotApplied);
+ if (sessionReady) {
+ CLog.i("Done waiting after " + spentWaiting);
+ break;
+ }
+ try {
+ Thread.sleep(SLEEP_FOR.toMillis());
+ spentWaiting = spentWaiting.plus(SLEEP_FOR);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(e);
+ }
+ }
+ Assert.assertTrue("Staged session wasn't ready in " + WAIT_FOR_SESSION_READY_TTL,
+ sessionReady);
+ }
+
+ /**
+ * Abandons any staged session that is marked {@code ready}
+ */
+ public void abandonActiveStagedSession() throws DeviceNotAvailableException {
+ CommandResult res = mTest.getDevice().executeShellV2Command("pm list staged-sessions "
+ + "--only-ready --only-parent --only-sessionid");
+ assertThat(res.getStderr()).isEqualTo("");
+ String activeSessionId = res.getStdout();
+ if (activeSessionId != null && !activeSessionId.equals("")) {
+ res = mTest.getDevice().executeShellV2Command("pm install-abandon "
+ + activeSessionId);
+ if (!res.getStderr().equals("") || res.getStatus() != CommandStatus.SUCCESS) {
+ CLog.d("Failed to abandon session " + activeSessionId
+ + " Error: " + res.getStderr());
+ }
+ }
+ }
+
+ /**
+ * Uninstalls a shim apex only if its latest version is installed on /data partition
+ *
+ * <p>This is purely to optimize tests run time, since uninstalling an apex requires a reboot.
+ */
+ public void uninstallShimApexIfNecessary() throws Exception {
+ if (!isApexUpdateSupported()) {
+ return;
+ }
+
+ final String errorMessage = mTest.getDevice().uninstallPackage(SHIM);
+ if (errorMessage == null) {
+ CLog.i("Uninstalling shim apex");
+ mTest.getDevice().reboot();
+ } else {
+ // Most likely we tried to uninstall system version and failed. It should be fine to
+ // continue tests.
+ // TODO(b/140813980): use ApexInfo.sourceDir to decide whenever to issue an uninstall.
+ CLog.w("Failed to uninstall shim APEX: " + errorMessage);
+ }
+ assertThat(getShimApex().versionCode).isEqualTo(1L);
+ }
+
+ private ITestDevice.ApexInfo getShimApex() throws DeviceNotAvailableException {
+ return mTest.getDevice().getActiveApexes().stream().filter(
+ apex -> apex.name.equals(SHIM)).findAny().orElseThrow(
+ () -> new AssertionError("Can't find " + SHIM));
+ }
+
+ /**
+ * Return {@code true} if and only if device supports updating apex.
+ */
+ public boolean isApexUpdateSupported() throws Exception {
+ return mTest.getDevice().getBooleanProperty("ro.apex.updatable", false);
+ }
+
+ private boolean isReadyNotApplied(String sessionInfo) {
+ boolean isReady = mIsSessionReadyPattern.matcher(sessionInfo).find();
+ boolean isApplied = mIsSessionAppliedPattern.matcher(sessionInfo).find();
+ return isReady && !isApplied;
+ }
+
+ /**
+ * Waits for given {@code timeout} for {@code filePath} to be deleted.
+ */
+ public void waitForFileDeleted(String filePath, Duration timeout) throws Exception {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ while (true) {
+ if (!mTest.getDevice().doesFileExist(filePath)) {
+ return;
+ }
+ if (stopwatch.elapsed().compareTo(timeout) > 0) {
+ break;
+ }
+ Thread.sleep(500);
+ }
+ throw new AssertionError("Timed out waiting for " + filePath + " to be deleted");
+ }
+}
diff --git a/tests/wifi-e2e-tests.xml b/tests/wifi-e2e-tests.xml
new file mode 100644
index 00000000..1a130962
--- /dev/null
+++ b/tests/wifi-e2e-tests.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for wifi apex e2e testing">
+ <option name="test-suite-tag" value="wifi_e2e_tests" />
+ <option name="test-suite-tag" value="apct" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="wifi_e2e_tests.jar" />
+ <option name="set-option" value="apex_file_name:test_com.android.wifi.apex" />
+ </test>
+</configuration>
+
diff --git a/tools/Android.bp b/tools/Android.bp
index 6b4427b1..1f119e52 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
python_binary_host {
name: "deapexer",
srcs: [
@@ -38,56 +34,3 @@ python_binary_host {
],
}
-python_binary_host {
- name: "apex_compression_tool",
- srcs: [
- "apex_compression_tool.py",
- ],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
- libs: [
- "apex_manifest_proto",
- ],
- required: [
- "avbtool",
- "conv_apex_manifest",
- ],
-}
-
-python_test_host {
- name: "apex_compression_test",
- main: "apex_compression_test.py",
- srcs: [
- "apex_compression_test.py",
- ],
- data: [
- ":avbtool",
- ":com.android.example.apex",
- ":conv_apex_manifest",
- ":apex_compression_tool",
- ":deapexer",
- ":soong_zip",
- ],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
- libs: [
- "apex_manifest_proto",
- ],
- test_suites: ["general-tests"],
- test_options: {
- unit_test: true,
- },
-}
diff --git a/tools/apex_compression_test.py b/tools/apex_compression_test.py
deleted file mode 100644
index 018fc563..00000000
--- a/tools/apex_compression_test.py
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-"""Unit tests for apex_compression_tool."""
-import hashlib
-import logging
-import os
-import shutil
-import subprocess
-import tempfile
-import unittest
-from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED
-
-import apex_manifest_pb2
-
-logger = logging.getLogger(__name__)
-
-TEST_APEX = 'com.android.example.apex'
-
-# In order to debug test failures, set DEBUG_TEST to True and run the test from
-# local workstation bypassing atest, e.g.:
-# $ m apex_compression_tool_test && \
-# out/host/linux-x86/nativetest64/apex_compression_tool_test/\
-# apex_compression_tool_test
-#
-# the test will print out the command used, and the temporary files used by the
-# test.
-DEBUG_TEST = False
-
-
-def run(args, verbose=None, **kwargs):
- """Creates and returns a subprocess.Popen object.
-
- Args:
- args: The command represented as a list of strings.
- verbose: Whether the commands should be shown. Default to the global
- verbosity if unspecified.
- kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
- stdin, etc. stdout and stderr will default to subprocess.PIPE and
- subprocess.STDOUT respectively unless caller specifies any of them.
- universal_newlines will default to True, as most of the users in
- releasetools expect string output.
-
- Returns:
- A subprocess.Popen object.
- """
- if 'stdout' not in kwargs and 'stderr' not in kwargs:
- kwargs['stdout'] = subprocess.PIPE
- kwargs['stderr'] = subprocess.STDOUT
- if 'universal_newlines' not in kwargs:
- kwargs['universal_newlines'] = True
- if DEBUG_TEST:
- print('\nRunning: \n%s\n' % ' '.join(args))
- # Don't log any if caller explicitly says so.
- if verbose:
- logger.info(' Running: \'%s\'', ' '.join(args))
- return subprocess.Popen(args, **kwargs)
-
-
-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/soong/host/linux-x86/bin')
- args[0] = os.path.join(host_command_dir, args[0])
- return run_and_check_output(args, verbose, **kwargs)
-
-
-def run_and_check_output(args, verbose=None, **kwargs):
- """Runs the given command and returns the output.
-
- Args:
- args: The command represented as a list of strings.
- verbose: Whether the commands should be shown. Default to the global
- verbosity if unspecified.
- kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
- stdin, etc. stdout and stderr will default to subprocess.PIPE and
- subprocess.STDOUT respectively unless caller specifies any of them.
-
- Returns:
- The output string.
-
- Raises:
- ExternalError: On non-zero exit from the command.
- """
-
- proc = run(args, verbose=verbose, **kwargs)
- output, _ = proc.communicate()
- if output is None:
- output = ''
- # Don't log any if caller explicitly says so.
- if verbose:
- logger.info('%s', output.rstrip())
- if proc.returncode != 0:
- raise RuntimeError(
- "Failed to run command '{}' (exit code {}):\n{}".format(
- args, proc.returncode, output))
- return output
-
-
-def get_current_dir():
- """Returns the current dir, relative to the script dir."""
- # The script dir is the one we want, which could be different from pwd.
- current_dir = os.path.dirname(os.path.realpath(__file__))
- return current_dir
-
-
-def get_sha1sum(file_path):
- h = hashlib.sha256()
-
- with open(file_path, 'rb') as file:
- while True:
- # Reading is buffered, so we can read smaller chunks.
- chunk = file.read(h.block_size)
- if not chunk:
- break
- h.update(chunk)
-
- return h.hexdigest()
-
-
-class ApexCompressionTest(unittest.TestCase):
- def setUp(self):
- self._to_cleanup = []
-
- def tearDown(self):
- if not DEBUG_TEST:
- for i in self._to_cleanup:
- if os.path.isdir(i):
- shutil.rmtree(i, ignore_errors=True)
- else:
- os.remove(i)
- del self._to_cleanup[:]
- else:
- print('Cleanup: ' + str(self._to_cleanup))
-
- def _run_apex_compression_tool(self, args):
- cmd = ['apex_compression_tool']
- 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/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(
- shutil.which('apex_compression_tool'))
- cmd.extend(args)
- run_host_command(cmd, True)
-
- def _get_container_files(self, apex_file_path):
- dir_name = tempfile.mkdtemp(
- prefix=self._testMethodName + '_container_files_')
- self._to_cleanup.append(dir_name)
- with ZipFile(apex_file_path, 'r') as zip_obj:
- zip_obj.extractall(path=dir_name)
- files = {}
- for i in ['apex_manifest.json', 'apex_manifest.pb', 'apex_pubkey',
- 'apex_build_info.pb', 'apex_payload.img', 'apex_payload.zip',
- 'AndroidManifest.xml', 'original_apex']:
- file_path = os.path.join(dir_name, i)
- if os.path.exists(file_path):
- files[i] = file_path
-
- image_file = files.get('apex_payload.img', None)
- if image_file is None:
- image_file = files.get('apex_payload.zip', None)
- else:
- files['apex_payload'] = image_file
- # Also retrieve the root digest of the image
- avbtool_cmd = ['avbtool',
- 'print_partition_digests', '--image', files['apex_payload']]
- # avbtool_cmd output has format "<name>: <value>"
- files['digest'] = run_host_command(
- avbtool_cmd, True).split(': ')[1].strip()
-
- return files
-
- def _get_manifest_string(self, manifest_path):
- cmd = ['conv_apex_manifest']
- cmd.extend([
- 'print',
- manifest_path
- ])
- return run_host_command(cmd, 'True')
-
- # Mutates the manifest located at |manifest_path|
- def _unset_original_apex_digest(self, manifest_path):
- # Open the protobuf
- with open(manifest_path, 'rb') as f:
- pb = apex_manifest_pb2.ApexManifest()
- pb.ParseFromString(f.read())
- pb.ClearField('capexMetadata')
- with open(manifest_path, 'wb') as f:
- f.write(pb.SerializeToString())
-
- def _compress_apex(self, uncompressed_apex_fp):
- """Returns file path to compressed APEX"""
- fd, compressed_apex_fp = tempfile.mkstemp(
- prefix=self._testMethodName + '_compressed_',
- suffix='.capex')
- os.close(fd)
- self._to_cleanup.append(compressed_apex_fp)
- self._run_apex_compression_tool([
- 'compress',
- '--input', uncompressed_apex_fp,
- '--output', compressed_apex_fp
- ])
- return compressed_apex_fp
-
- def _decompress_apex(self, compressed_apex_fp):
- """Returns file path to decompressed APEX"""
- decompressed_apex_fp = tempfile. \
- NamedTemporaryFile(prefix=self._testMethodName + '_decompressed_',
- suffix='.apex').name
- # Use deapexer to decompress
- cmd = ['deapexer']
- cmd.extend([
- 'decompress',
- '--input', compressed_apex_fp,
- '--output', decompressed_apex_fp
- ])
- run_host_command(cmd, True)
-
- self.assertTrue(os.path.exists(decompressed_apex_fp),
- 'Decompressed APEX does not exist')
- self._to_cleanup.append(decompressed_apex_fp)
- return decompressed_apex_fp
-
- def _get_type(self, apex_file_path):
- cmd = ['deapexer', 'info', '--print-type', apex_file_path]
- return run_host_command(cmd, True).strip()
-
- def test_compression(self):
- uncompressed_apex_fp = os.path.join(get_current_dir(), TEST_APEX + '.apex')
- # TODO(samiul): try compressing a compressed APEX
- compressed_apex_fp = self._compress_apex(uncompressed_apex_fp)
-
- # Verify output file has been created and is smaller than input file
- uncompressed_file_size = os.path.getsize(uncompressed_apex_fp)
- compressed_file_size = os.path.getsize(compressed_apex_fp)
- self.assertGreater(compressed_file_size, 0, 'Compressed APEX is empty')
- self.assertLess(compressed_file_size, uncompressed_file_size,
- 'Compressed APEX is not smaller than uncompressed APEX')
-
- # Verify type of the apex is 'COMPRESSED'
- self.assertEqual(self._get_type(compressed_apex_fp), 'COMPRESSED')
-
- # Verify the contents of the compressed apex files
- content_in_compressed_apex = self._get_container_files(compressed_apex_fp)
- self.assertIsNotNone(content_in_compressed_apex['original_apex'])
- content_in_uncompressed_apex = self._get_container_files(
- uncompressed_apex_fp)
- self.assertIsNotNone(content_in_uncompressed_apex['apex_payload'])
- self.assertIsNotNone(content_in_uncompressed_apex['digest'])
-
- # Verify that CAPEX manifest contains digest of original_apex
- manifest_string = self._get_manifest_string(
- content_in_compressed_apex['apex_manifest.pb'])
- self.assertIn('originalApexDigest: "'
- + content_in_uncompressed_apex['digest'] + '"', manifest_string)
-
- for i in ['apex_manifest.json', 'apex_manifest.pb', 'apex_pubkey',
- 'apex_build_info.pb', 'AndroidManifest.xml']:
- if i in content_in_uncompressed_apex:
- if i == 'apex_manifest.pb':
- # Get rid of originalApexDigest field, which should be the
- # only difference
- self._unset_original_apex_digest(content_in_compressed_apex[i])
- self.assertEqual(get_sha1sum(content_in_compressed_apex[i]),
- get_sha1sum(content_in_uncompressed_apex[i]))
-
- def test_decompression(self):
- # setup: create compressed APEX
- uncompressed_apex_fp = os.path.join(get_current_dir(), TEST_APEX + '.apex')
- compressed_apex_fp = self._compress_apex(uncompressed_apex_fp)
-
- # Decompress it
- decompressed_apex_fp = self._decompress_apex(compressed_apex_fp)
-
- # Verify type of the apex is 'UNCOMPRESSED'
- self.assertEqual(self._get_type(decompressed_apex_fp), 'UNCOMPRESSED')
-
- # Verify decompressed APEX is same as uncompressed APEX
- self.assertEqual(get_sha1sum(uncompressed_apex_fp),
- get_sha1sum(decompressed_apex_fp),
- 'Decompressed APEX is not same as uncompressed APEX')
-
- # Try decompressing uncompressed APEX. It should not work.
- with self.assertRaises(RuntimeError) as error:
- self._decompress_apex(uncompressed_apex_fp)
-
- self.assertIn(uncompressed_apex_fp
- + ' is not a compressed APEX', str(error.exception))
-
- def test_only_original_apex_is_compressed(self):
- uncompressed_apex_fp = os.path.join(get_current_dir(), TEST_APEX + '.apex')
- compressed_apex_fp = self._compress_apex(uncompressed_apex_fp)
-
- with ZipFile(compressed_apex_fp, 'r') as zip_obj:
- self.assertEqual(zip_obj.getinfo('original_apex').compress_type,
- ZIP_DEFLATED)
- content_in_uncompressed_apex = self._get_container_files(
- uncompressed_apex_fp)
- for i in ['apex_manifest.json', 'apex_manifest.pb', 'apex_pubkey',
- 'apex_build_info.pb', 'AndroidManifest.xml']:
- if i in content_in_uncompressed_apex:
- self.assertEqual(zip_obj.getinfo(i).compress_type, ZIP_STORED)
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/tools/apex_compression_tool.py b/tools/apex_compression_tool.py
deleted file mode 100644
index 3c0f16d8..00000000
--- a/tools/apex_compression_tool.py
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""apex_compression_tool is a tool that can compress/decompress APEX.
-
-Example:
- apex_compression_tool compress --input /apex/to/compress --output output/path
- apex_compression_tool decompress --input /apex/to/decompress --output dir/
- apex_compression_tool verify-compressed --input /file/to/check
-"""
-from __future__ import print_function
-
-import argparse
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-from zipfile import ZipFile
-
-import apex_manifest_pb2
-
-tool_path_list = None
-
-
-def FindBinaryPath(binary):
- for path in tool_path_list:
- binary_path = os.path.join(path, binary)
- if os.path.exists(binary_path):
- return binary_path
- raise Exception('Failed to find binary ' + binary + ' in path ' +
- ':'.join(tool_path_list))
-
-
-def RunCommand(cmd, verbose=False, env=None, expected_return_values=None):
- expected_return_values = expected_return_values or {0}
- env = env or {}
- env.update(os.environ.copy())
-
- cmd[0] = FindBinaryPath(cmd[0])
-
- if verbose:
- print('Running: ' + ' '.join(cmd))
- p = subprocess.Popen(
- cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
- output, _ = p.communicate()
-
- if verbose or p.returncode not in expected_return_values:
- print(output.rstrip())
-
- assert p.returncode in expected_return_values, 'Failed to execute: ' \
- + ' '.join(cmd)
-
- return output, p.returncode
-
-
-def RunCompress(args, work_dir):
- """RunCompress takes an uncompressed APEX and compresses into compressed APEX
-
- Compressed apex will contain the following items:
- - original_apex: The original uncompressed APEX
- - Duplicates of various meta files inside the input APEX, e.g
- AndroidManifest.xml, public_key
-
- Args:
- args.input: file path to uncompressed APEX
- args.output: file path to where compressed APEX will be placed
- work_dir: file path to a temporary folder
- Returns:
- True if compression was executed successfully, otherwise False
- """
- global tool_path_list
- tool_path_list = args.apex_compression_tool_path
-
- cmd = ['soong_zip']
- cmd.extend(['-o', args.output])
-
- # We want to put the input apex inside the compressed APEX with name
- # "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')
- os.link(args.input, original_apex)
- cmd.extend(['-C', work_dir])
- cmd.extend(['-f', original_apex])
-
- # We also need to extract some files from inside of original_apex and zip
- # together with compressed apex
- with ZipFile(original_apex, 'r') as zip_obj:
- extract_dir = os.path.join(work_dir, 'extract')
- for meta_file in ['apex_manifest.json', 'apex_manifest.pb',
- 'apex_pubkey', 'apex_build_info.pb',
- 'AndroidManifest.xml']:
- if meta_file in zip_obj.namelist():
- zip_obj.extract(meta_file, path=extract_dir)
- file_path = os.path.join(extract_dir, meta_file)
- cmd.extend(['-C', extract_dir])
- cmd.extend(['-f', file_path])
- cmd.extend(['-s', meta_file])
- # Extract the image for retrieving root digest
- zip_obj.extract('apex_payload.img', path= work_dir)
- image_path = os.path.join(work_dir, 'apex_payload.img')
-
- # 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)
-
- # Don't forget to compress
- cmd.extend(['-L', '9'])
-
- RunCommand(cmd, verbose=True)
-
- return True
-
-
-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, True)[0].decode().split(': ')[1].strip()
- # Update the manifest proto file
- with open(capex_manifest_path, 'rb') as f:
- pb = apex_manifest_pb2.ApexManifest()
- pb.ParseFromString(f.read())
- # Populate CompressedApexMetadata
- capex_metadata = apex_manifest_pb2.ApexManifest().CompressedApexMetadata()
- capex_metadata.originalApexDigest = root_digest
- # Set updated value to protobuf
- pb.capexMetadata.CopyFrom(capex_metadata)
- with open(capex_manifest_path, 'wb') as f:
- f.write(pb.SerializeToString())
- return True
-
-
-def ParseArgs(argv):
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers(required=True, dest='cmd')
-
- # Handle sub-command "compress"
- parser_compress = subparsers.add_parser('compress',
- help='compresses an APEX')
- parser_compress.add_argument('--input', type=str, required=True,
- help='path to input APEX file that will be '
- 'compressed')
- parser_compress.add_argument('--output', type=str, required=True,
- help='output path to compressed APEX file')
- apex_compression_tool_path_in_environ = \
- 'APEX_COMPRESSION_TOOL_PATH' in os.environ
- parser_compress.add_argument(
- '--apex_compression_tool_path',
- required=not apex_compression_tool_path_in_environ,
- default=os.environ['APEX_COMPRESSION_TOOL_PATH'].split(':')
- if apex_compression_tool_path_in_environ else None,
- type=lambda s: s.split(':'),
- help="""A list of directories containing all the tools used by
- apex_compression_tool (e.g. soong_zip etc.) separated by ':'. Can also
- be set using the APEX_COMPRESSION_TOOL_PATH environment variable""")
- parser_compress.set_defaults(func=RunCompress)
-
- return parser.parse_args(argv)
-
-
-class TempDirectory(object):
-
- def __enter__(self):
- self.name = tempfile.mkdtemp()
- return self.name
-
- def __exit__(self, *unused):
- shutil.rmtree(self.name)
-
-
-def main(argv):
- args = ParseArgs(argv)
-
- with TempDirectory() as work_dir:
- success = args.func(args, work_dir)
-
- if not success:
- sys.exit(1)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/tools/create_apex_skeleton.sh b/tools/create_apex_skeleton.sh
deleted file mode 100644
index 818e119a..00000000
--- a/tools/create_apex_skeleton.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-
-# Creates an apex stub in a subdirectory named after the package name. Edit the APEX_NAME variable
-# before running.
-
-APEX_NAME=com.android.yourpackagenamehere
-
-mkdir ${APEX_NAME}
-cd ${APEX_NAME}
-
-cat > Android.bp <<EOF
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-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
-
-openssl genrsa -out ${APEX_NAME}.pem 4096
-avbtool extract_public_key --key ${APEX_NAME}.pem --output ${APEX_NAME}.avbpubkey
-
-cat > csr.conf <<EOF
-[req]
-default_bits = 4096
-distinguished_name = dn
-prompt = no
-
-[dn]
-C="US"
-ST="California"
-L="Mountain View"
-O="Android"
-OU="Android"
-emailAddress="android@android.com"
-CN="${APEX_NAME}"
-EOF
-
-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_NAME}.pk8 -nocrypt
-rm key.pem
-
-cat > manifest.json << EOF
-{
- "name": "${APEX_NAME}",
- "version": 1
-}
-EOF
diff --git a/tools/deapexer.py b/tools/deapexer.py
index 92001c9d..b170d90f 100644
--- a/tools/deapexer.py
+++ b/tools/deapexer.py
@@ -24,29 +24,23 @@ To extract content of an APEX to the given directory:
from __future__ import print_function
import argparse
-import apex_manifest
-import enum
import os
import shutil
import sys
import subprocess
import tempfile
import zipfile
-
-BLOCK_SIZE = 4096
+import apex_manifest
class ApexImageEntry(object):
- def __init__(self, name, base_dir, permissions, size, ino, extents, is_directory=False,
- is_symlink=False):
+ def __init__(self, name, base_dir, permissions, size, is_directory=False, is_symlink=False):
self._name = name
self._base_dir = base_dir
self._permissions = permissions
self._size = size
self._is_directory = is_directory
self._is_symlink = is_symlink
- self._ino = ino
- self._extents = extents
@property
def name(self):
@@ -76,14 +70,6 @@ class ApexImageEntry(object):
def size(self):
return self._size
- @property
- def ino(self):
- return self._ino
-
- @property
- def extents(self):
- return self._extents
-
def __str__(self):
ret = ''
if self._is_directory:
@@ -166,43 +152,10 @@ class Apex(object):
name = parts[5]
if not name:
continue
- ino = parts[1]
bits = parts[2]
size = parts[6]
- extents = []
- is_symlink = bits[1]=='2'
- is_directory=bits[1]=='4'
-
- if not is_symlink and not is_directory:
- process = subprocess.Popen([self._debugfs, '-R', 'dump_extents <%s>' % ino,
- self._payload], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True)
- stdout, _ = process.communicate()
- # Output of dump_extents for an inode fragmented in 3 blocks (length and addresses represent
- # block-sized sections):
- # Level Entries Logical Physical Length Flags
- # 0/ 0 1/ 3 0 - 0 18 - 18 1
- # 0/ 0 2/ 3 1 - 15 20 - 34 15
- # 0/ 0 3/ 3 16 - 1863 37 - 1884 1848
- res = str(stdout).splitlines()
- res.pop(0) # the first line contains only columns names
- left_length = int(size)
- try: # dump_extents sometimes has an unexpected output
- for line in res:
- tokens = line.split()
- offset = int(tokens[7]) * BLOCK_SIZE
- length = min(int(tokens[-1]) * BLOCK_SIZE, left_length)
- left_length -= length
- extents.append((offset, length))
- if (left_length != 0): # dump_extents sometimes fails to display "hole" blocks
- raise ValueError
- except:
- extents = [] # [] means that we failed to retrieve the file location successfully
-
entries.append(ApexImageEntry(name, base_dir=path, permissions=int(bits[3:], 8), size=size,
- is_directory=is_directory, is_symlink=is_symlink, ino=ino,
- extents=extents))
-
+ is_directory=bits[1]=='4', is_symlink=bits[1]=='2'))
return ApexImageDirectory(path, entries, self)
def _extract(self, path, dest):
@@ -215,38 +168,17 @@ class Apex(object):
def RunList(args):
- if GetType(args.apex) == ApexType.COMPRESSED:
- with tempfile.TemporaryDirectory() as temp:
- decompressed_apex = os.path.join(temp, 'temp.apex')
- decompress(args.apex, decompressed_apex)
- args.apex = decompressed_apex
-
- RunList(args)
- return
-
with Apex(args) as apex:
for e in apex.list(is_recursive=True):
if e.is_directory:
continue
- res = ''
if args.size:
- res += e.size + ' '
- res += e.full_path
- if args.extents:
- res += ' [' + '-'.join(str(x) for x in e.extents) + ']'
- print(res)
+ print(e.size, e.full_path)
+ else:
+ print(e.full_path)
def RunExtract(args):
- if GetType(args.apex) == ApexType.COMPRESSED:
- with tempfile.TemporaryDirectory() as temp:
- decompressed_apex = os.path.join(temp, "temp.apex")
- decompress(args.apex, decompressed_apex)
- args.apex = decompressed_apex
-
- RunExtract(args)
- return
-
with Apex(args) as apex:
if not os.path.exists(args.dest):
os.makedirs(args.dest, mode=0o755)
@@ -254,75 +186,15 @@ def RunExtract(args):
shutil.rmtree(os.path.join(args.dest, "lost+found"))
-class ApexType(enum.Enum):
- INVALID = 0
- UNCOMPRESSED = 1
- COMPRESSED = 2
-
-
-def GetType(apex_path):
- with zipfile.ZipFile(apex_path, 'r') as zip_file:
- names = zip_file.namelist()
- has_payload = 'apex_payload.img' in names
- has_original_apex = 'original_apex' in names
- if has_payload and has_original_apex:
- return ApexType.INVALID
- if has_payload:
- return ApexType.UNCOMPRESSED
- if has_original_apex:
- return ApexType.COMPRESSED
- return ApexType.INVALID
-
-
def RunInfo(args):
- if args.print_type:
- res = GetType(args.apex)
- if res == ApexType.INVALID:
- print(args.apex + ' is not a valid apex')
- sys.exit(1)
- print(res.name)
- else:
- manifest = apex_manifest.fromApex(args.apex)
- print(apex_manifest.toJsonString(manifest))
-
-
-def RunDecompress(args):
- """RunDecompress takes path to compressed APEX and decompresses it to
- produce the original uncompressed APEX at give output path
-
- See apex_compression_tool.py#RunCompress for details on compressed APEX
- structure.
-
- Args:
- args.input: file path to compressed APEX
- args.output: file path to where decompressed APEX will be placed
- """
- compressed_apex_fp = args.input
- decompressed_apex_fp = args.output
- return decompress(compressed_apex_fp, decompressed_apex_fp)
-
-def decompress(compressed_apex_fp, decompressed_apex_fp):
- if os.path.exists(decompressed_apex_fp):
- print("Output path '" + decompressed_apex_fp + "' already exists")
- sys.exit(1)
-
- with zipfile.ZipFile(compressed_apex_fp, 'r') as zip_obj:
- if 'original_apex' not in zip_obj.namelist():
- print(compressed_apex_fp + ' is not a compressed APEX. Missing '
- "'original_apex' file inside it.")
- sys.exit(1)
- # Rename original_apex file to what user provided as output filename
- original_apex_info = zip_obj.getinfo('original_apex')
- original_apex_info.filename = os.path.basename(decompressed_apex_fp)
- # Extract the original_apex as desired name
- zip_obj.extract(original_apex_info,
- path=os.path.dirname(decompressed_apex_fp))
+ manifest = apex_manifest.fromApex(args.apex)
+ print(apex_manifest.toJsonString(manifest))
def main(argv):
parser = argparse.ArgumentParser()
- debugfs_default = None
+ debugfs_default = 'debugfs' # assume in PATH by default
if 'ANDROID_HOST_OUT' in os.environ:
debugfs_default = '%s/bin/debugfs_static' % os.environ['ANDROID_HOST_OUT']
parser.add_argument('--debugfs_path', help='The path to debugfs binary', default=debugfs_default)
@@ -332,7 +204,6 @@ def main(argv):
parser_list = subparsers.add_parser('list', help='prints content of an APEX to stdout')
parser_list.add_argument('apex', type=str, help='APEX file')
parser_list.add_argument('--size', help='also show the size of the files', action="store_true")
- parser_list.add_argument('--extents', help='also show the location of the files', action="store_true")
parser_list.set_defaults(func=RunList)
parser_extract = subparsers.add_parser('extract', help='extracts content of an APEX to the given '
@@ -343,31 +214,10 @@ def main(argv):
parser_info = subparsers.add_parser('info', help='prints APEX manifest')
parser_info.add_argument('apex', type=str, help='APEX file')
- parser_info.add_argument('--print-type',
- help='Prints type of the apex (COMPRESSED or UNCOMPRESSED)',
- action='store_true')
parser_info.set_defaults(func=RunInfo)
- # Handle sub-command "decompress"
- parser_decompress = subparsers.add_parser('decompress',
- help='decompresses a compressed '
- 'APEX')
- parser_decompress.add_argument('--input', type=str, required=True,
- help='path to compressed APEX file that '
- 'will be decompressed')
- parser_decompress.add_argument('--output', type=str, required=True,
- help='output directory path where '
- 'decompressed APEX will be extracted')
- parser_decompress.set_defaults(func=RunDecompress)
-
args = parser.parse_args(argv)
- debugfs_required_for_cmd = ['list', 'extract']
- if args.cmd in debugfs_required_for_cmd and not args.debugfs_path:
- print('ANDROID_HOST_OUT environment variable is not defined, --debugfs_path must be set',
- file=sys.stderr)
- sys.exit(1)
-
args.func(args)