Merge "AIDEGen: Collect the srcjar path of modules into module-info.json"
diff --git a/core/Makefile b/core/Makefile
index bbd7426..d6bd804 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -695,7 +695,7 @@
@echo APK certs list: $@
@mkdir -p $(dir $@)
@rm -f $@
- $(foreach p,$(PACKAGES),\
+ $(foreach p,$(sort $(PACKAGES)),\
$(if $(PACKAGES.$(p).EXTERNAL_KEY),\
$(call _apkcerts_write_line,$(p),"EXTERNAL","",$(PACKAGES.$(p).COMPRESSED),$@),\
$(call _apkcerts_write_line,$(p),$(PACKAGES.$(p).CERTIFICATE),$(PACKAGES.$(p).PRIVATE_KEY),$(PACKAGES.$(p).COMPRESSED),$@)))
@@ -3067,18 +3067,30 @@
$(error BOARD_AVB_VBMETA_SYSTEM and BOARD_AVB_VBMETA_VENDOR cannot have duplicates)
endif
-# Appends security patch level as a AVB property descriptor
+# Appends os version and security patch level as a AVB property descriptor
BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.system.os_version:$(PLATFORM_VERSION) \
--prop com.android.build.system.security_patch:$(PLATFORM_SECURITY_PATCH)
BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.product.os_version:$(PLATFORM_VERSION) \
--prop com.android.build.product.security_patch:$(PLATFORM_SECURITY_PATCH)
BOARD_AVB_PRODUCT_SERVICES_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.product_services.os_version:$(PLATFORM_VERSION) \
--prop com.android.build.product_services.security_patch:$(PLATFORM_SECURITY_PATCH)
-# The following vendor- and odm-specific images needs explicitly set per board.
+BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
+ --prop com.android.build.boot.os_version:$(PLATFORM_VERSION)
+
+BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.vendor.os_version:$(PLATFORM_VERSION)
+
+BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.odm.os_version:$(PLATFORM_VERSION)
+
+# The following vendor- and odm-specific images needs explicit SPL set per board.
ifdef BOOT_SECURITY_PATCH
BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
--prop com.android.build.boot.security_patch:$(BOOT_SECURITY_PATCH)
@@ -3369,8 +3381,12 @@
.PHONY: check-all-partition-sizes check-all-partition-sizes-nodeps
+check_all_partition_sizes_file := $(call intermediates-dir-for,PACKAGING,check-all-partition-sizes)/timestamp
+
+check-all-partition-sizes: $(check_all_partition_sizes_file)
+
# Add image dependencies so that generated_*_image_info.txt are written before checking.
-check-all-partition-sizes: \
+$(check_all_partition_sizes_file): \
build/make/tools/releasetools/sparse_img.py \
$(call images-for-partitions,$(BOARD_SUPER_PARTITION_PARTITION_LIST))
@@ -3438,7 +3454,12 @@
fi
endef
-check-all-partition-sizes check-all-partition-sizes-nodeps:
+$(check_all_partition_sizes_file):
+ $(call check-all-partition-sizes-target)
+ $(call check-super-partition-size)
+ touch $@
+
+check-all-partition-sizes-nodeps:
$(call check-all-partition-sizes-target)
$(call check-super-partition-size)
diff --git a/core/board_config.mk b/core/board_config.mk
index 597b10e..d83fa32 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -181,7 +181,7 @@
# Sanity check to warn about likely cryptic errors later in the build.
ifeq ($(TARGET_IS_64_BIT),true)
ifeq (,$(filter true false,$(TARGET_SUPPORTS_64_BIT_APPS)))
- $(warning Building a 32-bit-app-only product on a 64-bit device. \
+ $(error Building a 32-bit-app-only product on a 64-bit device. \
If this is intentional, set TARGET_SUPPORTS_64_BIT_APPS := false)
endif
endif
diff --git a/core/config.mk b/core/config.mk
index 1db37ef..088bb15 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -624,11 +624,9 @@
USE_OPENJDK9 := true
-ifeq ($(EXPERIMENTAL_USE_OPENJDK9),)
+ifeq ($(EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9),)
TARGET_OPENJDK9 :=
-else ifeq ($(EXPERIMENTAL_USE_OPENJDK9),1.8)
-TARGET_OPENJDK9 :=
-else ifeq ($(EXPERIMENTAL_USE_OPENJDK9),true)
+else ifeq ($(EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9),true)
TARGET_OPENJDK9 := true
endif
@@ -815,15 +813,6 @@
PLATFORM_SEPOLICY_VERSION \
TOT_SEPOLICY_VERSION \
-ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),)
- ifdef PRODUCT_SHIPPING_API_LEVEL
- ifeq (true,$(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),29))
- PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := true
- endif
- endif
-endif
-.KATI_READONLY := PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
-
ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
ifneq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
$(error PRODUCT_USE_DYNAMIC_PARTITIONS must be true when PRODUCT_RETROFIT_DYNAMIC_PARTITIONS \
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index b5834b0..c44e4bd 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -1,4 +1,4 @@
-DEX_PREOPT_CONFIG := $(PRODUCT_OUT)/dexpreopt.config
+DEX_PREOPT_CONFIG := $(SOONG_OUT_DIR)/dexpreopt.config
# The default value for LOCAL_DEX_PREOPT
DEX_PREOPT_DEFAULT ?= true
@@ -169,12 +169,6 @@
fi)
endif
-# Dummy rule to create dexpreopt.config, it will already have been created
-# by the $(file) call above, but a rule needs to exist to keep the dangling
-# rule check happy.
-$(DEX_PREOPT_CONFIG):
- @#empty
-
DEXPREOPT_GEN_DEPS := \
$(SOONG_HOST_OUT_EXECUTABLES)/profman \
$(DEX2OAT) \
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 85ddbfa..266ebd2 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -242,12 +242,12 @@
.KATI_RESTAT: $(my_dexpreopt_script) $(my_strip_script)
$(my_dexpreopt_script): PRIVATE_MODULE := $(LOCAL_MODULE)
- $(my_dexpreopt_script): PRIVATE_GLOBAL_CONFIG := $(PRODUCT_OUT)/dexpreopt.config
+ $(my_dexpreopt_script): PRIVATE_GLOBAL_CONFIG := $(DEX_PREOPT_CONFIG_FOR_MAKE)
$(my_dexpreopt_script): PRIVATE_MODULE_CONFIG := $(my_dexpreopt_config)
$(my_dexpreopt_script): PRIVATE_STRIP_SCRIPT := $(my_strip_script)
$(my_dexpreopt_script): .KATI_IMPLICIT_OUTPUTS := $(my_strip_script)
$(my_dexpreopt_script): $(DEXPREOPT_GEN)
- $(my_dexpreopt_script): $(my_dexpreopt_config) $(PRODUCT_OUT)/dexpreopt.config
+ $(my_dexpreopt_script): $(my_dexpreopt_config) $(DEX_PREOPT_CONFIG_FOR_MAKE)
@echo "$(PRIVATE_MODULE) dexpreopt gen"
$(DEXPREOPT_GEN) -global $(PRIVATE_GLOBAL_CONFIG) -module $(PRIVATE_MODULE_CONFIG) \
-dexpreopt_script $@ -strip_script $(PRIVATE_STRIP_SCRIPT) \
diff --git a/core/main.mk b/core/main.mk
index df5c13c..0225c89 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -714,7 +714,7 @@
$(eval req_files := )\
$(foreach req_mod,$(req_mods), \
$(eval req_file := $(filter $(TARGET_OUT_ROOT)/%, $(call module-installed-files,$(req_mod)))) \
- $(if $(strip $(req_file)),\
+ $(if $(strip $(req_file))$(ONE_SHOT_MAKEFILE),\
,\
$(error $(m).LOCAL_TARGET_REQUIRED_MODULES : illegal value $(req_mod) : not a device module. If you want to specify host modules to be required to be installed along with your host module, add those module names to LOCAL_REQUIRED_MODULES instead)\
)\
@@ -740,7 +740,7 @@
$(eval req_files := )\
$(foreach req_mod,$(req_mods), \
$(eval req_file := $(filter $(HOST_OUT)/%, $(call module-installed-files,$(req_mod)))) \
- $(if $(strip $(req_file)),\
+ $(if $(strip $(req_file))$(ONE_SHOT_MAKEFILE),\
,\
$(error $(m).LOCAL_HOST_REQUIRED_MODULES : illegal value $(req_mod) : not a host module. If you want to specify target modules to be required to be installed along with your target module, add those module names to LOCAL_REQUIRED_MODULES instead)\
)\
@@ -1214,6 +1214,8 @@
libartd.so \
libartpalette.so \
libc.so \
+ libc_malloc_debug.so \
+ libc_malloc_hooks.so \
libdexfile.so \
libdexfile_external.so \
libdexfiled.so \
diff --git a/core/product.mk b/core/product.mk
index 1a566f7..838673c 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -162,7 +162,9 @@
# used for adding properties to build.prop of product partition
_product_list_vars += PRODUCT_PRODUCT_SERVICES_PROPERTIES
_product_list_vars += PRODUCT_ODM_PROPERTIES
-_product_list_vars += PRODUCT_CHARACTERISTICS
+
+# The characteristics of the product, which among other things is passed to aapt
+_product_single_value_vars += PRODUCT_CHARACTERISTICS
# A list of words like <source path>:<destination path>[:<owner>].
# The file at the source path should be copied to the destination path
diff --git a/core/product_config.mk b/core/product_config.mk
index 8c739a4..cb58cf4 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -376,6 +376,23 @@
PRODUCT_BUILD_SUPER_PARTITION := $(PRODUCT_USE_DYNAMIC_PARTITIONS)
endif
+ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),)
+ ifdef PRODUCT_SHIPPING_API_LEVEL
+ ifeq (true,$(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),29))
+ PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := true
+ endif
+ endif
+endif
+
+# If build command defines OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS,
+# override PRODUCT_EXTRA_VNDK_VERSIONS with it.
+ifdef OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS
+ PRODUCT_EXTRA_VNDK_VERSIONS := $(OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS)
+endif
+
+$(KATI_obsolete_var OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS \
+ ,Use PRODUCT_EXTRA_VNDK_VERSIONS instead)
+
define product-overrides-config
$$(foreach rule,$$(PRODUCT_$(1)_OVERRIDES),\
$$(if $$(filter 2,$$(words $$(subst :,$$(space),$$(rule)))),,\
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index 31b0e63..7a8f46e 100644
--- a/core/soong_cc_prebuilt.mk
+++ b/core/soong_cc_prebuilt.mk
@@ -223,7 +223,9 @@
#
# Filter out some NDK libraries that are not being exported.
my_static_libraries := \
- $(filter-out ndk_libc++_static ndk_libc++abi ndk_libandroid_support ndk_libunwind, \
+ $(filter-out ndk_libc++_static ndk_libc++abi ndk_libandroid_support ndk_libunwind \
+ ndk_libc++_static.native_bridge ndk_libc++abi.native_bridge \
+ ndk_libandroid_support.native_bridge ndk_libunwind.native_bridge, \
$(LOCAL_STATIC_LIBRARIES))
installed_static_library_notice_file_targets := \
$(foreach lib,$(my_static_libraries) $(LOCAL_WHOLE_STATIC_LIBRARIES), \
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 48db6b1..220e2c8 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -121,6 +121,7 @@
$(call add_json_str, DeviceVndkVersion, $(BOARD_VNDK_VERSION))
$(call add_json_str, Platform_vndk_version, $(PLATFORM_VNDK_VERSION))
$(call add_json_list, ExtraVndkVersions, $(PRODUCT_EXTRA_VNDK_VERSIONS))
+$(call add_json_bool, BoardVndkRuntimeDisable, $(BOARD_VNDK_RUNTIME_DISABLE))
$(call add_json_list, DeviceSystemSdkVersions, $(BOARD_SYSTEMSDK_VERSIONS))
$(call add_json_list, Platform_systemsdk_versions, $(PLATFORM_SYSTEMSDK_VERSIONS))
$(call add_json_bool, Malloc_not_svelte, $(call invert_bool,$(filter true,$(MALLOC_SVELTE))))
diff --git a/core/tasks/check_boot_jars/package_whitelist.txt b/core/tasks/check_boot_jars/package_whitelist.txt
index b0becba..3b63843 100644
--- a/core/tasks/check_boot_jars/package_whitelist.txt
+++ b/core/tasks/check_boot_jars/package_whitelist.txt
@@ -46,6 +46,8 @@
java\.util\.spi
java\.util\.stream
java\.util\.zip
+# TODO: Remove javax.annotation.processing if possible, see http://b/132338110:
+javax\.annotation\.processing
javax\.crypto
javax\.crypto\.interfaces
javax\.crypto\.spec
diff --git a/core/tasks/vndk.mk b/core/tasks/vndk.mk
index 9420638..90ebd92 100644
--- a/core/tasks/vndk.mk
+++ b/core/tasks/vndk.mk
@@ -27,11 +27,10 @@
#
# Args:
# $(1): list of module and filename pairs (e.g., ld.config.txt:ld.config.27.txt ...)
-# $(2): if not empty, evaluates for TARGET_2ND_ARCH
define paths-of-intermediates
$(strip \
$(foreach pair,$(1), \
- $(eval module := $(call word-colon,1,$(pair))$(if $(2),$(TARGET_2ND_ARCH_MODULE_SUFFIX))) \
+ $(eval module := $(call word-colon,1,$(pair))) \
$(eval built := $(ALL_MODULES.$(module).BUILT_INSTALLED)) \
$(eval filename := $(call word-colon,2,$(pair))) \
$(if $(wordlist 2,100,$(built)), \
@@ -41,30 +40,6 @@
)
endef
-# Returns src:dest list of notice files
-#
-# Args:
-# $(1): list of lib names (e.g., libfoo.vendor)
-define paths-of-notice-files
-$(strip \
- $(foreach lib,$(1), \
- $(eval notice := $(sort \
- $(ALL_MODULES.$(lib).NOTICES) \
- $(if $(TARGET_2ND_ARCH),
- $(ALL_MODULES.$(lib)$(TARGET_2ND_ARCH_MODULE_SUFFIX).NOTICES)))) \
- $(if $(wordlist 2,100,$(notice)), \
- $(error Unable to handle multiple notice files ($(lib)): $(notice))) \
- $(if $(notice),$(notice):$(subst .vendor,,$(lib)).so.txt)))
-endef
-
-vndk_core_libs := $(addsuffix .vendor,$(VNDK_CORE_LIBRARIES))
-vndk_sp_libs := $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES))
-vndk_private_libs := $(addsuffix .vendor,$(VNDK_PRIVATE_LIBRARIES))
-
-vndk_snapshot_libs := \
- $(vndk_core_libs) \
- $(vndk_sp_libs)
-
vndk_prebuilt_txts := \
ld.config.txt \
vndksp.libraries.txt \
@@ -75,47 +50,6 @@
vndk_snapshot_configs_out := $(vndk_snapshot_top)/configs
#######################################
-# vndkcore.libraries.txt
-vndkcore.libraries.txt := $(vndk_snapshot_configs_out)/vndkcore.libraries.txt
-$(vndkcore.libraries.txt): PRIVATE_LIBS := $(vndk_core_libs)
-$(vndkcore.libraries.txt):
- @echo 'Generating: $@'
- @rm -f $@
- @mkdir -p $(dir $@)
- $(hide) echo -n > $@
- $(hide) $(foreach lib,$(PRIVATE_LIBS),echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
-
-
-#######################################
-# vndkprivate.libraries.txt
-vndkprivate.libraries.txt := $(vndk_snapshot_configs_out)/vndkprivate.libraries.txt
-$(vndkprivate.libraries.txt): PRIVATE_LIBS := $(vndk_private_libs)
-$(vndkprivate.libraries.txt):
- @echo 'Generating: $@'
- @rm -f $@
- @mkdir -p $(dir $@)
- $(hide) echo -n > $@
- $(hide) $(foreach lib,$(PRIVATE_LIBS),echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
-
-
-#######################################
-# module_paths.txt
-module_paths.txt := $(vndk_snapshot_configs_out)/module_paths.txt
-$(module_paths.txt): PRIVATE_LIBS := $(vndk_snapshot_libs)
-$(module_paths.txt):
- @echo 'Generating: $@'
- @rm -f $@
- @mkdir -p $(dir $@)
- $(hide) echo -n > $@
- $(hide) $(foreach lib,$(PRIVATE_LIBS),echo $(patsubst %.vendor,%,$(lib)).so $(ALL_MODULES.$(lib).PATH) >> $@;)
-
-
-vndk_snapshot_configs := \
- $(vndkcore.libraries.txt) \
- $(vndkprivate.libraries.txt) \
- $(module_paths.txt)
-
-#######################################
# vndk_snapshot_zip
vndk_snapshot_variant := $(vndk_snapshot_out)/$(TARGET_ARCH)
binder :=
@@ -130,44 +64,46 @@
$(vndk_snapshot_zip): PRIVATE_VNDK_SNAPSHOT_OUT := $(vndk_snapshot_out)
-deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(subst .vendor,,$(lib)).so))
+prebuilts := $(SOONG_VNDK_SNAPSHOT_CORE_LIBS)
$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_OUT := $(vndk_lib_dir)/shared/vndk-core
-$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES := $(deps)
-$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
-deps :=
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_SOONG_PREBUILTS := $(prebuilts)
+$(vndk_snapshot_zip): $(prebuilts)
+prebuilts :=
-deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(subst .vendor,,$(lib)).so))
+prebuilts := $(SOONG_VNDK_SNAPSHOT_SP_LIBS)
$(vndk_snapshot_zip): PRIVATE_VNDK_SP_OUT := $(vndk_lib_dir)/shared/vndk-sp
-$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES := $(deps)
-$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
-deps :=
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_SOONG_PREBUILTS := $(prebuilts)
+$(vndk_snapshot_zip): $(prebuilts)
+prebuilts :=
deps := $(call paths-of-intermediates,$(foreach txt,$(vndk_prebuilt_txts), \
- $(txt):$(patsubst %.txt,%.$(PLATFORM_VNDK_VERSION).txt,$(txt)))) \
- $(foreach config,$(vndk_snapshot_configs),$(config):$(notdir $(config)))
+ $(txt):$(patsubst %.txt,%.$(PLATFORM_VNDK_VERSION).txt,$(txt))))
+prebuilts := $(SOONG_VNDK_SNAPSHOT_CONFIGS)
$(vndk_snapshot_zip): PRIVATE_CONFIGS_OUT := $(vndk_snapshot_variant)/configs
$(vndk_snapshot_zip): PRIVATE_CONFIGS_INTERMEDIATES := $(deps)
-$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
+$(vndk_snapshot_zip): PRIVATE_CONFIGS_SOONG_PREBUILTS := $(prebuilts)
+$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d))) $(prebuilts)
deps :=
+prebuilts :=
-notices := $(call paths-of-notice-files,$(vndk_core_libs) $(vndk_sp_libs))
+prebuilts := $(SOONG_VNDK_SNAPSHOT_NOTICES)
$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_OUT := $(vndk_snapshot_variant)/NOTICE_FILES
-$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_INTERMEDIATES := $(notices)
-$(vndk_snapshot_zip): $(foreach n,$(notices),$(call word-colon,1,$(n)))
-notices :=
+$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_SOONG_PREBUILTS := $(prebuilts)
+$(vndk_snapshot_zip): $(prebuilts)
+prebuilts :=
ifdef TARGET_2ND_ARCH
-deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(subst .vendor,,$(lib)).so),true)
+prebuilts := $(SOONG_VNDK_SNAPSHOT_CORE_LIBS_2ND)
$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_OUT_2ND := $(vndk_lib_dir_2nd)/shared/vndk-core
-$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES_2ND := $(deps)
-$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
-deps :=
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_SOONG_PREBUILTS_2ND := $(prebuilts)
+$(vndk_snapshot_zip): $(prebuilts)
+prebuilts :=
-deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(subst .vendor,,$(lib)).so),true)
+prebuilts := $(SOONG_VNDK_SNAPSHOT_SP_LIBS_2ND)
$(vndk_snapshot_zip): PRIVATE_VNDK_SP_OUT_2ND := $(vndk_lib_dir_2nd)/shared/vndk-sp
-$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES_2ND := $(deps)
-$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
-deps :=
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_SOONG_PREBUILTS_2ND := $(prebuilts)
+$(vndk_snapshot_zip): $(prebuilts)
+prebuilts :=
endif
# Args
@@ -182,6 +118,15 @@
true \
))
+# Args
+# $(1): destination directory
+# $(2): list of prebuilts to copy
+$(vndk_snapshot_zip): private-copy-prebuilts = \
+ $(if $(2),$(strip \
+ @mkdir -p $(1) && \
+ $(foreach file, $(2), cp $(file) $(1) && ) \
+ true \
+ ))
$(vndk_snapshot_zip): $(SOONG_ZIP)
@echo 'Generating VNDK snapshot: $@'
@@ -189,18 +134,20 @@
@rm -rf $(PRIVATE_VNDK_SNAPSHOT_OUT)
@mkdir -p $(PRIVATE_VNDK_SNAPSHOT_OUT)
$(call private-copy-intermediates, \
- $(PRIVATE_VNDK_CORE_OUT),$(PRIVATE_VNDK_CORE_INTERMEDIATES))
- $(call private-copy-intermediates, \
- $(PRIVATE_VNDK_SP_OUT),$(PRIVATE_VNDK_SP_INTERMEDIATES))
- $(call private-copy-intermediates, \
$(PRIVATE_CONFIGS_OUT),$(PRIVATE_CONFIGS_INTERMEDIATES))
- $(call private-copy-intermediates, \
- $(PRIVATE_NOTICE_FILES_OUT),$(PRIVATE_NOTICE_FILES_INTERMEDIATES))
+ $(call private-copy-prebuilts, \
+ $(PRIVATE_VNDK_CORE_OUT),$(PRIVATE_VNDK_CORE_SOONG_PREBUILTS))
+ $(call private-copy-prebuilts, \
+ $(PRIVATE_VNDK_SP_OUT),$(PRIVATE_VNDK_SP_SOONG_PREBUILTS))
+ $(call private-copy-prebuilts, \
+ $(PRIVATE_CONFIGS_OUT),$(PRIVATE_CONFIGS_SOONG_PREBUILTS))
+ $(call private-copy-prebuilts, \
+ $(PRIVATE_NOTICE_FILES_OUT),$(PRIVATE_NOTICE_FILES_SOONG_PREBUILTS))
ifdef TARGET_2ND_ARCH
- $(call private-copy-intermediates, \
- $(PRIVATE_VNDK_CORE_OUT_2ND),$(PRIVATE_VNDK_CORE_INTERMEDIATES_2ND))
- $(call private-copy-intermediates, \
- $(PRIVATE_VNDK_SP_OUT_2ND),$(PRIVATE_VNDK_SP_INTERMEDIATES_2ND))
+ $(call private-copy-prebuilts, \
+ $(PRIVATE_VNDK_CORE_OUT_2ND),$(PRIVATE_VNDK_CORE_SOONG_PREBUILTS_2ND))
+ $(call private-copy-prebuilts, \
+ $(PRIVATE_VNDK_SP_OUT_2ND),$(PRIVATE_VNDK_SP_SOONG_PREBUILTS_2ND))
endif
$(hide) $(SOONG_ZIP) -o $@ -C $(PRIVATE_VNDK_SNAPSHOT_OUT) -D $(PRIVATE_VNDK_SNAPSHOT_OUT)
@@ -212,12 +159,7 @@
# clear global vars
clang-ubsan-vndk-core :=
paths-of-intermediates :=
-paths-of-notice-files :=
-vndk_core_libs :=
-vndk_sp_libs :=
-vndk_snapshot_libs :=
vndk_prebuilt_txts :=
-vndk_snapshot_configs :=
vndk_snapshot_top :=
vndk_snapshot_out :=
vndk_snapshot_configs_out :=
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index b248fd3..2714f83 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -261,7 +261,7 @@
# It must be of the form "YYYY-MM-DD" on production devices.
# It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
# If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
- PLATFORM_SECURITY_PATCH := 2019-04-05
+ PLATFORM_SECURITY_PATCH := 2019-05-05
endif
.KATI_READONLY := PLATFORM_SECURITY_PATCH
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index d14c94f..fb4ca76 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -19,11 +19,14 @@
import re
import shlex
import sys
+import zipfile
import common
logger = logging.getLogger(__name__)
+OPTIONS = common.OPTIONS
+
class ApexInfoError(Exception):
"""An Exception raised during Apex Information command."""
@@ -145,3 +148,72 @@
'Failed to find {} prop in {}'.format(key, payload_path))
return payload_info
+
+
+def SignApex(apex_data, payload_key, container_key, container_pw,
+ codename_to_api_level_map, signing_args=None):
+ """Signs the current APEX with the given payload/container keys.
+
+ Args:
+ apex_data: Raw APEX data.
+ payload_key: The path to payload signing key (w/ extension).
+ container_key: The path to container signing key (w/o extension).
+ container_pw: The matching password of the container_key, or None.
+ codename_to_api_level_map: A dict that maps from codename to API level.
+ signing_args: Additional args to be passed to the payload signer.
+
+ Returns:
+ The path to the signed APEX file.
+ """
+ apex_file = common.MakeTempFile(prefix='apex-', suffix='.apex')
+ with open(apex_file, 'wb') as apex_fp:
+ apex_fp.write(apex_data)
+
+ APEX_PAYLOAD_IMAGE = 'apex_payload.img'
+ APEX_PUBKEY = 'apex_pubkey'
+
+ # 1a. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given
+ # payload_key.
+ payload_dir = common.MakeTempDir(prefix='apex-payload-')
+ with zipfile.ZipFile(apex_file) as apex_fd:
+ payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
+
+ payload_info = ParseApexPayloadInfo(payload_file)
+ SignApexPayload(
+ payload_file,
+ payload_key,
+ payload_info['apex.key'],
+ payload_info['Algorithm'],
+ payload_info['Salt'],
+ signing_args)
+
+ # 1b. Update the embedded payload public key.
+ payload_public_key = common.ExtractAvbPublicKey(payload_key)
+
+ common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
+ common.ZipDelete(apex_file, APEX_PUBKEY)
+ apex_zip = zipfile.ZipFile(apex_file, 'a')
+ common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
+ common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
+ common.ZipClose(apex_zip)
+
+ # 2. Align the files at page boundary (same as in apexer).
+ aligned_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
+ common.RunAndCheckOutput(['zipalign', '-f', '4096', apex_file, aligned_apex])
+
+ # 3. Sign the APEX container with container_key.
+ signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
+
+ # Specify the 4K alignment when calling SignApk.
+ extra_signapk_args = OPTIONS.extra_signapk_args[:]
+ extra_signapk_args.extend(['-a', '4096'])
+
+ common.SignFile(
+ aligned_apex,
+ signed_apex,
+ container_key,
+ container_pw,
+ codename_to_api_level_map=codename_to_api_level_map,
+ extra_signapk_args=extra_signapk_args)
+
+ return signed_apex
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index 6165d96..8fb9871 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -180,8 +180,10 @@
OPTIONS.input_tmp = target_files
elif zipfile.is_zipfile(target_files):
logger.info("Building image zip from target files zip.")
- OPTIONS.input_tmp = common.UnzipTemp(target_files,
- ["IMAGES/*", "OTA/*", "META/*"])
+ # We need files under IMAGES/, OTA/, META/ for img_from_target_files.py.
+ # However, common.LoadInfoDict() may read additional files under BOOT/,
+ # RECOVERY/ and ROOT/. So unzip everything from the target_files.zip.
+ OPTIONS.input_tmp = common.UnzipTemp(target_files)
else:
raise ValueError("%s is not a valid path." % target_files)
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index f03cc1e..2a722c5 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -185,6 +185,26 @@
]
+def write_sorted_data(data, path):
+ """Write the sorted contents of either a list or dict to file.
+
+ This function sorts the contents of the list or dict and then
+ writes the resulting sorted contents to a file specified by path.
+
+ Args:
+ data: The list or dict to sort and write.
+ path: Path to the file to write the sorted values to. The file at path will
+ be overridden if it exists.
+ """
+ with open(path, 'w') as output:
+ sorted_data = sorted(data.keys()) if isinstance(data,
+ dict) else sorted(data)
+ for entry in sorted_data:
+ out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
+ data, dict) else '{}\n'.format(entry)
+ output.write(out_str)
+
+
def extract_items(target_files, target_files_temp_dir, extract_item_list):
"""Extract items from target files to temporary directory.
@@ -341,9 +361,7 @@
output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
'ab_partitions.txt')
- with open(output_ab_partitions_txt, 'w') as output:
- for partition in sorted(output_ab_partitions):
- output.write('%s\n' % partition)
+ write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
def append_recovery_to_filesystem_config(output_target_files_temp_dir):
@@ -485,10 +503,7 @@
output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
'misc_info.txt')
- with open(output_misc_info_txt, 'w') as output:
- sorted_keys = sorted(merged_info_dict.keys())
- for key in sorted_keys:
- output.write('{}={}\n'.format(key, merged_info_dict[key]))
+ write_sorted_data(data=merged_info_dict, path=output_misc_info_txt)
def process_dynamic_partitions_info_txt(system_target_files_dir,
@@ -538,10 +553,56 @@
output_dynamic_partitions_info_txt = os.path.join(
output_target_files_dir, 'META', 'dynamic_partitions_info.txt')
- with open(output_dynamic_partitions_info_txt, 'w') as output:
- sorted_keys = sorted(merged_dynamic_partitions_dict.keys())
- for key in sorted_keys:
- output.write('{}={}\n'.format(key, merged_dynamic_partitions_dict[key]))
+ write_sorted_data(
+ data=merged_dynamic_partitions_dict,
+ path=output_dynamic_partitions_info_txt)
+
+
+def process_apex_keys_apk_certs_common(system_target_files_dir,
+ other_target_files_dir,
+ output_target_files_dir, file_name):
+ """Perform special processing for META/apexkeys.txt or META/apkcerts.txt.
+
+ This function merges the contents of the META/apexkeys.txt or
+ META/apkcerts.txt
+ files from the system directory and the other directory, placing the merged
+ result in the output directory. The precondition in that the files are already
+ extracted.
+ The post condition is that the output META/apexkeys.txt or META/apkcerts.txt
+ contains the merged content.
+
+ Args:
+ system_target_files_dir: The name of a directory containing the special
+ items extracted from the system target files package.
+ other_target_files_dir: The name of a directory containing the special items
+ extracted from the other target files package.
+ output_target_files_dir: The name of a directory that will be used to create
+ the output target files package after all the special cases are processed.
+ file_name: The name of the file to merge. One of apkcerts.txt or
+ apexkeys.txt.
+ """
+
+ def read_helper(d):
+ temp = {}
+ file_path = os.path.join(d, 'META', file_name)
+ with open(file_path) as f:
+ for line in f:
+ if line.strip():
+ temp[line.split()[0]] = line.strip()
+ return temp
+
+ system_dict = read_helper(system_target_files_dir)
+ other_dict = read_helper(other_target_files_dir)
+
+ for key in system_dict:
+ if key in other_dict and other_dict[key] != system_dict[key]:
+ raise ValueError('Conflicting entries found in %s:\n %s and\n %s' %
+ (file_name, system_dict[key], other_dict[key]))
+ other_dict[key] = system_dict[key]
+
+ output_file = os.path.join(output_target_files_dir, 'META', file_name)
+
+ write_sorted_data(data=other_dict.values(), path=output_file)
def process_special_cases(system_target_files_temp_dir,
@@ -588,6 +649,18 @@
other_target_files_dir=other_target_files_temp_dir,
output_target_files_dir=output_target_files_temp_dir)
+ process_apex_keys_apk_certs_common(
+ system_target_files_dir=system_target_files_temp_dir,
+ other_target_files_dir=other_target_files_temp_dir,
+ output_target_files_dir=output_target_files_temp_dir,
+ file_name='apkcerts.txt')
+
+ process_apex_keys_apk_certs_common(
+ system_target_files_dir=system_target_files_temp_dir,
+ other_target_files_dir=other_target_files_temp_dir,
+ output_target_files_dir=output_target_files_temp_dir,
+ file_name='apexkeys.txt')
+
def merge_target_files(temp_dir, system_target_files, system_item_list,
system_misc_info_keys, other_target_files,
diff --git a/tools/releasetools/sign_apex.py b/tools/releasetools/sign_apex.py
new file mode 100755
index 0000000..1778615
--- /dev/null
+++ b/tools/releasetools/sign_apex.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Signs a standalone APEX file.
+
+Usage: sign_apex [flags] input_apex_file output_apex_file
+
+ --container_key <key>
+ Mandatory flag that specifies the container signing key.
+
+ --payload_key <key>
+ Mandatory flag that specifies the payload signing key.
+
+ --payload_extra_args <args>
+ Optional flag that specifies any extra args to be passed to payload signer
+ (e.g. --payload_extra_args="--signing_helper_with_files /path/to/helper").
+"""
+
+import logging
+import shutil
+import sys
+
+import apex_utils
+import common
+
+logger = logging.getLogger(__name__)
+
+
+def main(argv):
+
+ options = {}
+
+ def option_handler(o, a):
+ if o == '--container_key':
+ # Strip the suffix if any, as common.SignFile expects no suffix.
+ DEFAULT_CONTAINER_KEY_SUFFIX = '.x509.pem'
+ if a.endswith(DEFAULT_CONTAINER_KEY_SUFFIX):
+ a = a[:-len(DEFAULT_CONTAINER_KEY_SUFFIX)]
+ options['container_key'] = a
+ elif o == '--payload_key':
+ options['payload_key'] = a
+ elif o == '--payload_extra_args':
+ options['payload_extra_args'] = a
+ else:
+ return False
+ return True
+
+ args = common.ParseOptions(
+ argv, __doc__,
+ extra_opts='',
+ extra_long_opts=[
+ 'container_key=',
+ 'payload_extra_args=',
+ 'payload_key=',
+ ],
+ extra_option_handler=option_handler)
+
+ if (len(args) != 2 or 'container_key' not in options or
+ 'payload_key' not in options):
+ common.Usage(__doc__)
+ sys.exit(1)
+
+ common.InitLogging()
+
+ input_zip = args[0]
+ output_zip = args[1]
+ with open(input_zip) as input_fp:
+ apex_data = input_fp.read()
+
+ signed_apex = apex_utils.SignApex(
+ apex_data,
+ payload_key=options['payload_key'],
+ container_key=options['container_key'],
+ container_pw=None,
+ codename_to_api_level_map=None,
+ signing_args=options.get('payload_extra_args'))
+
+ shutil.copyfile(signed_apex, output_zip)
+ logger.info("done.")
+
+
+if __name__ == '__main__':
+ try:
+ main(sys.argv[1:])
+ except common.ExternalError:
+ logger.exception("\n ERROR:\n")
+ sys.exit(1)
+ finally:
+ common.Cleanup()
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 24ee91b..7de0978 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -403,77 +403,6 @@
return data
-def SignApex(apex_data, payload_key, container_key, container_pw,
- codename_to_api_level_map, signing_args=None):
- """Signs the current APEX with the given payload/container keys.
-
- Args:
- apex_data: Raw APEX data.
- payload_key: The path to payload signing key (w/ extension).
- container_key: The path to container signing key (w/o extension).
- container_pw: The matching password of the container_key, or None.
- codename_to_api_level_map: A dict that maps from codename to API level.
- signing_args: Additional args to be passed to the payload signer.
-
- Returns:
- The path to the signed APEX file.
- """
- apex_file = common.MakeTempFile(prefix='apex-', suffix='.apex')
- with open(apex_file, 'wb') as apex_fp:
- apex_fp.write(apex_data)
-
- APEX_PAYLOAD_IMAGE = 'apex_payload.img'
- APEX_PUBKEY = 'apex_pubkey'
-
- # 1a. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given
- # payload_key.
- payload_dir = common.MakeTempDir(prefix='apex-payload-')
- with zipfile.ZipFile(apex_file) as apex_fd:
- payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
-
- payload_info = apex_utils.ParseApexPayloadInfo(payload_file)
- apex_utils.SignApexPayload(
- payload_file,
- payload_key,
- payload_info['apex.key'],
- payload_info['Algorithm'],
- payload_info['Salt'],
- signing_args)
-
- # 1b. Update the embedded payload public key.
- payload_public_key = common.ExtractAvbPublicKey(payload_key)
-
- common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
- common.ZipDelete(apex_file, APEX_PUBKEY)
- apex_zip = zipfile.ZipFile(apex_file, 'a')
- common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
- common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
- common.ZipClose(apex_zip)
-
- # 2. Align the files at page boundary (same as in apexer).
- aligned_apex = common.MakeTempFile(
- prefix='apex-container-', suffix='.apex')
- common.RunAndCheckOutput(
- ['zipalign', '-f', '4096', apex_file, aligned_apex])
-
- # 3. Sign the APEX container with container_key.
- signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
-
- # Specify the 4K alignment when calling SignApk.
- extra_signapk_args = OPTIONS.extra_signapk_args[:]
- extra_signapk_args.extend(['-a', '4096'])
-
- common.SignFile(
- aligned_apex,
- signed_apex,
- container_key,
- container_pw,
- codename_to_api_level_map=codename_to_api_level_map,
- extra_signapk_args=extra_signapk_args)
-
- return signed_apex
-
-
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
apk_keys, apex_keys, key_passwords,
platform_api_level, codename_to_api_level_map,
@@ -538,7 +467,7 @@
print(" : %-*s payload (%s)" % (
maxsize, name, payload_key))
- signed_apex = SignApex(
+ signed_apex = apex_utils.SignApex(
data,
payload_key,
container_key,
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
index 3f15d8f..1e29fde 100644
--- a/tools/releasetools/test_merge_target_files.py
+++ b/tools/releasetools/test_merge_target_files.py
@@ -22,7 +22,8 @@
default_system_item_list,
default_other_item_list,
default_system_misc_info_keys, copy_items,
- merge_dynamic_partition_info_dicts)
+ merge_dynamic_partition_info_dicts,
+ process_apex_keys_apk_certs_common)
class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
@@ -160,3 +161,55 @@
'super_group_b_size': '2000',
}
self.assertEqual(merged_dict, expected_merged_dict)
+
+ def test_process_apex_keys_apk_certs_ReturnsTrueIfNoConflicts(self):
+ output_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(output_dir, 'META'))
+
+ system_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(system_dir, 'META'))
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_system.txt'),
+ os.path.join(system_dir, 'META', 'apexkeys.txt'))
+
+ other_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(other_dir, 'META'))
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_other.txt'),
+ os.path.join(other_dir, 'META', 'apexkeys.txt'))
+
+ process_apex_keys_apk_certs_common(system_dir, other_dir, output_dir,
+ 'apexkeys.txt')
+
+ merged_entries = []
+ merged_path = os.path.join(self.testdata_dir, 'apexkeys_merge.txt')
+
+ with open(merged_path) as f:
+ merged_entries = f.read().split('\n')
+
+ output_entries = []
+ output_path = os.path.join(output_dir, 'META', 'apexkeys.txt')
+
+ with open(output_path) as f:
+ output_entries = f.read().split('\n')
+
+ return self.assertEqual(merged_entries, output_entries)
+
+ def test_process_apex_keys_apk_certs_ReturnsFalseIfConflictsPresent(self):
+ output_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(output_dir, 'META'))
+
+ system_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(system_dir, 'META'))
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_system.txt'),
+ os.path.join(system_dir, 'META', 'apexkeys.txt'))
+
+ conflict_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(conflict_dir, 'META'))
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_system_conflict.txt'),
+ os.path.join(conflict_dir, 'META', 'apexkeys.txt'))
+
+ self.assertRaises(ValueError, process_apex_keys_apk_certs_common,
+ system_dir, conflict_dir, output_dir, 'apexkeys.txt')
diff --git a/tools/releasetools/testdata/apexkeys_merge.txt b/tools/releasetools/testdata/apexkeys_merge.txt
new file mode 100644
index 0000000..48e789f
--- /dev/null
+++ b/tools/releasetools/testdata/apexkeys_merge.txt
@@ -0,0 +1,4 @@
+name="com.android.conscrypt.apex" public_key="external/conscrypt/apex/com.android.conscrypt.avbpubkey" private_key="external/conscrypt/apex/com.android.conscrypt.pem" container_certificate="external/conscrypt/apex/com.android.conscrypt.x509.pem" container_private_key="external/conscrypt/apex/com.android.conscrypt.pk8"
+name="com.android.runtime.debug.apex" public_key="art/build/apex/com.android.runtime.avbpubkey" private_key="art/build/apex/com.android.runtime.pem" container_certificate="art/build/apex/com.android.runtime.debug.x509.pem" container_private_key="art/build/apex/com.android.runtime.debug.pk8"
+name="com.android.runtime.release.apex" public_key="art/build/apex/com.android.runtime.avbpubkey" private_key="art/build/apex/com.android.runtime.pem" container_certificate="art/build/apex/com.android.runtime.release.x509.pem" container_private_key="art/build/apex/com.android.runtime.release.pk8"
+name="com.android.support.apexer.apex" public_key="system/apex/apexer/etc/com.android.support.apexer.avbpubkey" private_key="system/apex/apexer/etc/com.android.support.apexer.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
diff --git a/tools/releasetools/testdata/apexkeys_other.txt b/tools/releasetools/testdata/apexkeys_other.txt
new file mode 100644
index 0000000..b751227
--- /dev/null
+++ b/tools/releasetools/testdata/apexkeys_other.txt
@@ -0,0 +1,3 @@
+name="com.android.runtime.release.apex" public_key="art/build/apex/com.android.runtime.avbpubkey" private_key="art/build/apex/com.android.runtime.pem" container_certificate="art/build/apex/com.android.runtime.release.x509.pem" container_private_key="art/build/apex/com.android.runtime.release.pk8"
+name="com.android.support.apexer.apex" public_key="system/apex/apexer/etc/com.android.support.apexer.avbpubkey" private_key="system/apex/apexer/etc/com.android.support.apexer.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
+name="com.android.runtime.debug.apex" public_key="art/build/apex/com.android.runtime.avbpubkey" private_key="art/build/apex/com.android.runtime.pem" container_certificate="art/build/apex/com.android.runtime.debug.x509.pem" container_private_key="art/build/apex/com.android.runtime.debug.pk8"
diff --git a/tools/releasetools/testdata/apexkeys_system.txt b/tools/releasetools/testdata/apexkeys_system.txt
new file mode 100644
index 0000000..2346668
--- /dev/null
+++ b/tools/releasetools/testdata/apexkeys_system.txt
@@ -0,0 +1,2 @@
+name="com.android.runtime.debug.apex" public_key="art/build/apex/com.android.runtime.avbpubkey" private_key="art/build/apex/com.android.runtime.pem" container_certificate="art/build/apex/com.android.runtime.debug.x509.pem" container_private_key="art/build/apex/com.android.runtime.debug.pk8"
+name="com.android.conscrypt.apex" public_key="external/conscrypt/apex/com.android.conscrypt.avbpubkey" private_key="external/conscrypt/apex/com.android.conscrypt.pem" container_certificate="external/conscrypt/apex/com.android.conscrypt.x509.pem" container_private_key="external/conscrypt/apex/com.android.conscrypt.pk8"
diff --git a/tools/releasetools/testdata/apexkeys_system_conflict.txt b/tools/releasetools/testdata/apexkeys_system_conflict.txt
new file mode 100644
index 0000000..caa21c2
--- /dev/null
+++ b/tools/releasetools/testdata/apexkeys_system_conflict.txt
@@ -0,0 +1 @@
+name="com.android.runtime.debug.apex" public_key="art/build/apex/com.android.runtime.avbpubkey" private_key="art/build/apex/com.android.runtime.pem" container_certificate="art/build/apex/com.android.runtime.release.x509.pem" container_private_key="art/build/apex/com.android.runtime.debug.pk8"