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"