Merge "Exclude libdexfile_external.so to fix aosp_marlin-userdebug builds."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 51139ed..3d9a1ef 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -610,6 +610,9 @@
 $(call add-clean-step, rm -rf $(TARGET_OUT_DATA)/*)
 $(call add-clean-step, rm -rf $(HOST_OUT)/vts/*)
 $(call add-clean-step, rm -rf $(HOST_OUT)/framework/vts-tradefed.jar)
+
+# Clean up old location of system_other.avbpubkey
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/security/avb/)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index a15e42e..1c53459 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -222,10 +222,22 @@
 
 BUILDINFO_SH := build/make/tools/buildinfo.sh
 BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh
-# Generates a set of common build system properties to a file.
+
+# Generates a set of sysprops common to all partitions to a file.
 # $(1): Partition name
 # $(2): Output file name
 define generate-common-build-props
+	PRODUCT_BRAND="$(PRODUCT_BRAND)" \
+	PRODUCT_DEVICE="$(TARGET_DEVICE)" \
+	PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
+	PRODUCT_MODEL="$(PRODUCT_MODEL)" \
+	PRODUCT_NAME="$(TARGET_PRODUCT)" \
+	$(call generate-common-build-props-with-product-vars-set,$(1),$(2))
+endef
+
+# Like the above macro, but requiring the relevant PRODUCT_ environment
+# variables to be set when called.
+define generate-common-build-props-with-product-vars-set
 	BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
 	BUILD_ID="$(BUILD_ID)" \
 	BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
@@ -233,12 +245,7 @@
 	DATE="$(DATE_FROM_FILE)" \
 	PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
 	PLATFORM_VERSION="$(PLATFORM_VERSION)" \
-	PRODUCT_BRAND="$(PRODUCT_BRAND)" \
-	PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
-	PRODUCT_MODEL="$(PRODUCT_MODEL)" \
-	PRODUCT_NAME="$(TARGET_PRODUCT)" \
 	TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
-	TARGET_DEVICE="$(TARGET_DEVICE)" \
 	bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2)
 endef
 
@@ -426,7 +433,12 @@
 	$(hide) $(foreach prop,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES), \
 	    echo "import /oem/oem.prop $(prop)" >> $@;)
 endif
-	$(hide) $(call generate-common-build-props,system,$@)
+	$(hide) PRODUCT_BRAND="$(PRODUCT_SYSTEM_BRAND)" \
+	        PRODUCT_MANUFACTURER="$(PRODUCT_SYSTEM_MANUFACTURER)" \
+	        PRODUCT_MODEL="$(PRODUCT_SYSTEM_MODEL)" \
+	        PRODUCT_NAME="$(PRODUCT_SYSTEM_NAME)" \
+	        PRODUCT_DEVICE="$(PRODUCT_SYSTEM_DEVICE)" \
+	        $(call generate-common-build-props-with-product-vars-set,system,$@)
 	$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
 	        TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
 	        TARGET_DEVICE="$(TARGET_DEVICE)" \
@@ -718,6 +730,15 @@
 $(call dist-for-goals,droidcore,$(BUILD_SYSTEM_STATS))
 
 # -----------------------------------------------------------------
+# build /product/etc/security/avb/system_other.avbpubkey if needed
+ifdef BUILDING_SYSTEM_OTHER_IMAGE
+ifeq ($(BOARD_AVB_ENABLE),true)
+INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET := $(TARGET_OUT_PRODUCT_ETC)/security/avb/system_other.avbpubkey
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET)
+endif # BOARD_AVB_ENABLE
+endif # BUILDING_SYSTEM_OTHER_IMAGE
+
+# -----------------------------------------------------------------
 # Modules ready to be converted to Soong, ordered by how many
 # modules depend on them.
 SOONG_CONV := $(sort $(SOONG_CONV))
@@ -1451,8 +1472,7 @@
 $(if $(BOARD_AVB_ENABLE),\
     $(if $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH),\
         $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_system_extract_system_other_key=true" >> $(1)))
+        $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),\
@@ -3036,9 +3056,11 @@
 BOARD_AVB_SYSTEM_OTHER_ALGORITHM := $(BOARD_AVB_ALGORITHM)
 endif
 
-# To extract the public key of SYSTEM_OTHER_KEY_PATH will into system.img:
-# /system/etc/security/avb/system_other.avbpubkey.
-FULL_SYSTEMIMAGE_DEPS += $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)
+$(INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET): $(AVBTOOL) $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)
+	@echo Extracting system_other avb key: $@
+	@rm -f $@
+	@mkdir -p $(dir $@)
+	$(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH) --output $@
 
 ifndef BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX
 BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
@@ -4282,7 +4304,7 @@
 	@echo "Package symbols: $@"
 	$(hide) rm -rf $@ $(PRIVATE_LIST_FILE)
 	$(hide) mkdir -p $(dir $@) $(TARGET_OUT_UNSTRIPPED) $(dir $(PRIVATE_LIST_FILE))
-	$(hide) find $(TARGET_OUT_UNSTRIPPED) | sort >$(PRIVATE_LIST_FILE)
+	$(hide) find -L $(TARGET_OUT_UNSTRIPPED) -type f | sort >$(PRIVATE_LIST_FILE)
 	$(hide) $(SOONG_ZIP) -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE)
 # -----------------------------------------------------------------
 # A zip of the coverage directory.
diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk
new file mode 100644
index 0000000..b429dca
--- /dev/null
+++ b/core/app_prebuilt_internal.mk
@@ -0,0 +1,280 @@
+#
+# 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.
+#
+
+############################################################
+# Internal build rules for APPS prebuilt modules
+############################################################
+
+ifneq (APPS,$(LOCAL_MODULE_CLASS))
+$(call pretty-error,app_prebuilt_internal.mk is for APPS modules only)
+endif
+
+ifdef LOCAL_COMPRESSED_MODULE
+  ifneq (true,$(LOCAL_COMPRESSED_MODULE))
+    $(call pretty-error, Unknown value for LOCAL_COMPRESSED_MODULE $(LOCAL_COMPRESSED_MODULE))
+  endif
+  LOCAL_BUILT_MODULE_STEM := package.apk.gz
+  ifndef LOCAL_INSTALLED_MODULE_STEM
+    PACKAGES.$(LOCAL_MODULE).COMPRESSED := gz
+    LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk.gz
+  endif
+else  # LOCAL_COMPRESSED_MODULE
+  LOCAL_BUILT_MODULE_STEM := package.apk
+  ifndef LOCAL_INSTALLED_MODULE_STEM
+    LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk
+  endif
+endif  # LOCAL_COMPRESSED_MODULE
+
+include $(BUILD_SYSTEM)/base_rules.mk
+built_module := $(LOCAL_BUILT_MODULE)
+
+# Run veridex on product, product_services and vendor modules.
+# We skip it for unbundled app builds where we cannot build veridex.
+module_run_appcompat :=
+ifeq (true,$(non_system_module))
+ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))  # ! unbundled app build
+ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
+  module_run_appcompat := true
+endif
+endif
+endif
+
+PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
+
+my_extract_apk := $(strip $(LOCAL_EXTRACT_APK))
+
+# Select dpi-specific source
+ifdef LOCAL_DPI_VARIANTS
+my_dpi := $(firstword $(filter $(LOCAL_DPI_VARIANTS),$(PRODUCT_AAPT_PREF_CONFIG) $(PRODUCT_AAPT_PREBUILT_DPI)))
+ifdef my_dpi
+ifdef LOCAL_DPI_FILE_STEM
+my_prebuilt_dpi_file_stem := $(LOCAL_DPI_FILE_STEM)
+else
+my_prebuilt_dpi_file_stem := $(LOCAL_MODULE)_%.apk
+endif
+my_prebuilt_src_file := $(dir $(my_prebuilt_src_file))$(subst %,$(my_dpi),$(my_prebuilt_dpi_file_stem))
+
+ifneq ($(strip $(LOCAL_EXTRACT_DPI_APK)),)
+my_extract_apk := $(subst %,$(my_dpi),$(LOCAL_EXTRACT_DPI_APK))
+endif  # LOCAL_EXTRACT_DPI_APK
+endif  # my_dpi
+endif  # LOCAL_DPI_VARIANTS
+
+ifdef my_extract_apk
+my_extracted_apk := $(intermediates)/extracted.apk
+
+$(my_extracted_apk): PRIVATE_EXTRACT := $(my_extract_apk)
+$(my_extracted_apk): $(my_prebuilt_src_file)
+	@echo Extract APK: $@
+	$(hide) mkdir -p $(dir $@) && rm -f $@
+	$(hide) unzip -p $< $(PRIVATE_EXTRACT) >$@
+
+my_prebuilt_src_file := $(my_extracted_apk)
+my_extracted_apk :=
+my_extract_apk :=
+ifeq ($(PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK),true)
+# If the product property is set, always preopt for extracted modules to prevent executing out of
+# the APK.
+my_preopt_for_extracted_apk := true
+endif
+endif
+
+dex_preopt_profile_src_file := $(my_prebuilt_src_file)
+
+rs_compatibility_jni_libs :=
+include $(BUILD_SYSTEM)/install_jni_libs.mk
+
+ifeq ($(LOCAL_CERTIFICATE),EXTERNAL)
+  # The magic string "EXTERNAL" means this package will be signed with
+  # the default dev key throughout the build process, but we expect
+  # the final package to be signed with a different key.
+  #
+  # This can be used for packages where we don't have access to the
+  # keys, but want the package to be predexopt'ed.
+  LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
+  PACKAGES.$(LOCAL_MODULE).EXTERNAL_KEY := 1
+
+  $(built_module) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
+  $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+endif
+ifeq ($(LOCAL_CERTIFICATE),)
+  # It is now a build error to add a prebuilt .apk without
+  # specifying a key for it.
+  $(error No LOCAL_CERTIFICATE specified for prebuilt "$(my_prebuilt_src_file)")
+else ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
+  # The magic string "PRESIGNED" means this package is already checked
+  # signed with its release key.
+  #
+  # By setting .CERTIFICATE but not .PRIVATE_KEY, this package will be
+  # mentioned in apkcerts.txt (with certificate set to "PRESIGNED")
+  # but the dexpreopt process will not try to re-sign the app.
+  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := PRESIGNED
+  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
+else
+  # If this is not an absolute certificate, assign it to a generic one.
+  ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)
+    LOCAL_CERTIFICATE := $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))$(LOCAL_CERTIFICATE)
+  endif
+
+  PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
+
+  $(built_module) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
+  $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+endif
+
+include $(BUILD_SYSTEM)/app_certificate_validate.mk
+
+# Disable dex-preopt of prebuilts to save space, if requested.
+ifndef LOCAL_DEX_PREOPT
+ifeq ($(DONT_DEXPREOPT_PREBUILTS),true)
+LOCAL_DEX_PREOPT := false
+endif
+endif
+
+# If the module is a compressed module, we don't pre-opt it because its final
+# installation location will be the data partition.
+ifdef LOCAL_COMPRESSED_MODULE
+LOCAL_DEX_PREOPT := false
+endif
+
+my_dex_jar := $(my_prebuilt_src_file)
+
+#######################################
+# defines built_odex along with rule to install odex
+include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
+#######################################
+ifneq ($(LOCAL_REPLACE_PREBUILT_APK_INSTALLED),)
+# There is a replacement for the prebuilt .apk we can install without any processing.
+$(built_module) : $(LOCAL_REPLACE_PREBUILT_APK_INSTALLED)
+	$(transform-prebuilt-to-target)
+
+else  # ! LOCAL_REPLACE_PREBUILT_APK_INSTALLED
+# Sign and align non-presigned .apks.
+# The embedded prebuilt jni to uncompress.
+ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
+# For PRESIGNED apks we must uncompress every .so file:
+# even if the .so file isn't for the current TARGET_ARCH,
+# we can't strip the file.
+embedded_prebuilt_jni_libs :=
+endif
+ifndef embedded_prebuilt_jni_libs
+# No LOCAL_PREBUILT_JNI_LIBS, uncompress all.
+embedded_prebuilt_jni_libs :=
+endif
+$(built_module): PRIVATE_EMBEDDED_JNI_LIBS := $(embedded_prebuilt_jni_libs)
+
+ifdef LOCAL_COMPRESSED_MODULE
+$(built_module) : $(MINIGZIP)
+endif
+
+ifeq ($(module_run_appcompat),true)
+$(built_module) : $(appcompat-files)
+$(LOCAL_BUILT_MODULE): PRIVATE_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
+endif
+
+ifneq ($(BUILD_PLATFORM_ZIP),)
+$(built_module) : .KATI_IMPLICIT_OUTPUTS := $(dir $(LOCAL_BUILT_MODULE))package.dex.apk
+endif
+ifneq ($(LOCAL_CERTIFICATE),PRESIGNED)
+ifdef LOCAL_DEX_PREOPT
+$(built_module) : PRIVATE_STRIP_SCRIPT := $(intermediates)/strip.sh
+$(built_module) : $(intermediates)/strip.sh
+$(built_module) : | $(DEXPREOPT_STRIP_DEPS)
+$(built_module) : .KATI_DEPFILE := $(built_module).d
+endif
+endif
+$(built_module) : $(my_prebuilt_src_file) | $(ZIPALIGN) $(ZIP2ZIP) $(SIGNAPK_JAR)
+	$(transform-prebuilt-to-target)
+	$(uncompress-prebuilt-embedded-jni-libs)
+ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
+	$(uncompress-dexs)
+endif  # LOCAL_UNCOMPRESS_DEX
+ifdef LOCAL_DEX_PREOPT
+ifneq ($(BUILD_PLATFORM_ZIP),)
+	@# Keep a copy of apk with classes.dex unstripped
+	$(hide) cp -f $@ $(dir $@)package.dex.apk
+endif  # BUILD_PLATFORM_ZIP
+endif  # LOCAL_DEX_PREOPT
+ifneq ($(LOCAL_CERTIFICATE),PRESIGNED)
+	@# Only strip out files if we can re-sign the package.
+# Run appcompat before stripping the classes.dex file.
+ifeq ($(module_run_appcompat),true)
+ifeq ($(LOCAL_USE_AAPT2),true)
+	$(call appcompat-header, aapt2)
+else
+	$(appcompat-header)
+endif
+	$(run-appcompat)
+endif  # module_run_appcompat
+ifdef LOCAL_DEX_PREOPT
+	mv -f $@ $@.tmp
+	$(PRIVATE_STRIP_SCRIPT) $@.tmp $@
+endif  # LOCAL_DEX_PREOPT
+	$(sign-package)
+	# No need for align-package because sign-package takes care of alignment
+else  # LOCAL_CERTIFICATE == PRESIGNED
+	$(align-package)
+endif  # LOCAL_CERTIFICATE
+ifdef LOCAL_COMPRESSED_MODULE
+	$(compress-package)
+endif  # LOCAL_COMPRESSED_MODULE
+endif  # ! LOCAL_REPLACE_PREBUILT_APK_INSTALLED
+
+
+###############################
+## Install split apks.
+ifdef LOCAL_PACKAGE_SPLITS
+ifdef LOCAL_COMPRESSED_MODULE
+$(error $(LOCAL_MODULE): LOCAL_COMPRESSED_MODULE is not currently supported for split installs)
+endif  # LOCAL_COMPRESSED_MODULE
+
+# LOCAL_PACKAGE_SPLITS is a list of apks to be installed.
+built_apk_splits := $(addprefix $(intermediates)/,$(notdir $(LOCAL_PACKAGE_SPLITS)))
+installed_apk_splits := $(addprefix $(my_module_path)/,$(notdir $(LOCAL_PACKAGE_SPLITS)))
+
+# Rules to sign the split apks.
+my_src_dir := $(sort $(dir $(LOCAL_PACKAGE_SPLITS)))
+ifneq (1,$(words $(my_src_dir)))
+$(error You must put all the split source apks in the same folder: $(LOCAL_PACKAGE_SPLITS))
+endif
+my_src_dir := $(LOCAL_PATH)/$(my_src_dir)
+
+$(built_apk_splits) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
+$(built_apk_splits) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+$(built_apk_splits) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+$(built_apk_splits) : $(intermediates)/%.apk : $(my_src_dir)/%.apk
+	$(copy-file-to-new-target)
+	$(sign-package)
+
+# Rules to install the split apks.
+$(installed_apk_splits) : $(my_module_path)/%.apk : $(intermediates)/%.apk
+	@echo "Install: $@"
+	$(copy-file-to-new-target)
+
+# Register the additional built and installed files.
+ALL_MODULES.$(my_register_name).INSTALLED += $(installed_apk_splits)
+ALL_MODULES.$(my_register_name).BUILT_INSTALLED += \
+  $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(intermediates)/$(notdir $(s)):$(my_module_path)/$(notdir $(s)))
+
+# Make sure to install the splits when you run "make <module_name>".
+$(my_all_targets): $(installed_apk_splits)
+
+endif # LOCAL_PACKAGE_SPLITS
+
diff --git a/core/base_rules.mk b/core/base_rules.mk
index b2bbe46..7e7d6dc 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -477,8 +477,6 @@
 
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 ifneq ($(LOCAL_INSTALLED_MODULE),$(my_default_test_module))
-# Install into the testcase folder
-$(LOCAL_INSTALLED_MODULE) : $(my_default_test_module)
 $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
 $(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE)
 	@echo "Install: $@"
@@ -622,6 +620,13 @@
 
 multi_arch :=
 
+my_default_test_module :=
+my_default_test_module := $($(my_prefix)OUT_TESTCASES)/$(LOCAL_MODULE)$(arch_dir)/$(my_installed_module_stem)
+ifneq ($(LOCAL_INSTALLED_MODULE),$(my_default_test_module))
+# Install into the testcase folder
+$(LOCAL_INSTALLED_MODULE) : $(my_default_test_module)
+endif
+
 # The module itself.
 $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
   $(eval my_compat_dist_$(suite) := $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
@@ -771,6 +776,10 @@
     $(ALL_MODULES.$(my_register_name).CHECKED) $(my_checked_module)
 ALL_MODULES.$(my_register_name).BUILT := \
     $(ALL_MODULES.$(my_register_name).BUILT) $(LOCAL_BUILT_MODULE)
+ifndef LOCAL_IS_HOST_MODULE
+ALL_MODULES.$(my_register_name).TARGET_BUILT := \
+    $(ALL_MODULES.$(my_register_name).TARGET_BUILT) $(LOCAL_BUILT_MODULE)
+endif
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 ALL_MODULES.$(my_register_name).INSTALLED := \
     $(strip $(ALL_MODULES.$(my_register_name).INSTALLED) \
diff --git a/core/binary.mk b/core/binary.mk
index ad3d76b..da188ae 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -1214,17 +1214,17 @@
         # with vendor_available: false
         my_link_type := native:vendor
         my_warn_types :=
-        my_allowed_types := native:vendor native:vndk
+        my_allowed_types := native:vendor native:vndk native:platform_vndk
     endif
 else ifneq ($(filter $(TARGET_RECOVERY_OUT)/%,$(call get_non_asan_path,$(LOCAL_MODULE_PATH))),)
 my_link_type := native:recovery
 my_warn_types :=
 # TODO(b/113303515) remove native:platform and my_allowed_ndk_types
-my_allowed_types := native:recovery native:platform $(my_allowed_ndk_types)
+my_allowed_types := native:recovery native:platform native:platform_vndk $(my_allowed_ndk_types)
 else
 my_link_type := native:platform
 my_warn_types := $(my_warn_ndk_types)
-my_allowed_types := $(my_allowed_ndk_types) native:platform
+my_allowed_types := $(my_allowed_ndk_types) native:platform native:platform_vndk
 endif
 
 my_link_deps := $(addprefix STATIC_LIBRARIES:,$(my_whole_static_libraries) $(my_static_libraries))
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 1e3f6ae..d67c9f8 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -263,8 +263,10 @@
 LOCAL_SOONG_LINK_TYPE :=
 LOCAL_SOONG_PROGUARD_DICT :=
 LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
-LOCAL_SOONG_RRO_DIRS :=
+LOCAL_SOONG_DEVICE_RRO_DIRS :=
+LOCAL_SOONG_PRODUCT_RRO_DIRS :=
 LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=
+LOCAL_SOONG_SYMBOL_PATH :=
 LOCAL_SOONG_TOC :=
 LOCAL_SOONG_UNSTRIPPED_BINARY :=
 # '',true
@@ -295,6 +297,7 @@
 LOCAL_USES_LIBRARIES:=
 LOCAL_VENDOR_MODULE:=
 LOCAL_VINTF_FRAGMENTS:=
+LOCAL_VNDK_DEPEND_ON_CORE_VARIANT:=
 LOCAL_VTSC_FLAGS:=
 LOCAL_VTS_INCLUDES:=
 LOCAL_VTS_MODE:=
diff --git a/core/combo/arch/x86/amberlake.mk b/core/combo/arch/x86/amberlake.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86/amberlake.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86/broadwell.mk b/core/combo/arch/x86/broadwell.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86/broadwell.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86/icelake.mk b/core/combo/arch/x86/icelake.mk
new file mode 100644
index 0000000..76fe212
--- /dev/null
+++ b/core/combo/arch/x86/icelake.mk
@@ -0,0 +1,14 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_AVX512 := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86/kabylake.mk b/core/combo/arch/x86/kabylake.mk
new file mode 100644
index 0000000..50518d6
--- /dev/null
+++ b/core/combo/arch/x86/kabylake.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors.
+# that support AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86/skylake.mk b/core/combo/arch/x86/skylake.mk
new file mode 100644
index 0000000..03705c0
--- /dev/null
+++ b/core/combo/arch/x86/skylake.mk
@@ -0,0 +1,15 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors.
+# that support AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_AVX512 := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
+
diff --git a/core/combo/arch/x86/tigerlake.mk b/core/combo/arch/x86/tigerlake.mk
new file mode 100644
index 0000000..76fe212
--- /dev/null
+++ b/core/combo/arch/x86/tigerlake.mk
@@ -0,0 +1,14 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_AVX512 := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86/whiskeylake.mk b/core/combo/arch/x86/whiskeylake.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86/whiskeylake.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86/x86.mk b/core/combo/arch/x86/x86.mk
index a55cc7a..db55ff8 100644
--- a/core/combo/arch/x86/x86.mk
+++ b/core/combo/arch/x86/x86.mk
@@ -11,3 +11,6 @@
 ARCH_X86_HAVE_SSSE3 := false
 ARCH_X86_HAVE_MOVBE := false
 ARCH_X86_HAVE_POPCNT := false
+ARCH_X86_HAVE_AVX := false
+ARCH_X86_HAVE_AVX2 := false
+ARCH_X86_HAVE_AVX512 := false
diff --git a/core/combo/arch/x86_64/amberlake.mk b/core/combo/arch/x86_64/amberlake.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86_64/amberlake.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/broadwell.mk b/core/combo/arch/x86_64/broadwell.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86_64/broadwell.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/icelake.mk b/core/combo/arch/x86_64/icelake.mk
new file mode 100644
index 0000000..76fe212
--- /dev/null
+++ b/core/combo/arch/x86_64/icelake.mk
@@ -0,0 +1,14 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_AVX512 := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/kabylake.mk b/core/combo/arch/x86_64/kabylake.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86_64/kabylake.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/skylake.mk b/core/combo/arch/x86_64/skylake.mk
new file mode 100644
index 0000000..76fe212
--- /dev/null
+++ b/core/combo/arch/x86_64/skylake.mk
@@ -0,0 +1,14 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_AVX512 := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/tigerlake.mk b/core/combo/arch/x86_64/tigerlake.mk
new file mode 100644
index 0000000..76fe212
--- /dev/null
+++ b/core/combo/arch/x86_64/tigerlake.mk
@@ -0,0 +1,14 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_AVX512 := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/whiskeylake.mk b/core/combo/arch/x86_64/whiskeylake.mk
new file mode 100644
index 0000000..37100a4
--- /dev/null
+++ b/core/combo/arch/x86_64/whiskeylake.mk
@@ -0,0 +1,13 @@
+# Configuration for Linux on x86.
+# Generating binaries for processors
+# that have AVX2 feature flag
+#
+
+ARCH_X86_HAVE_SSSE3  := true
+ARCH_X86_HAVE_SSE4   := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AVX2   := true
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_MOVBE  := true
diff --git a/core/combo/arch/x86_64/x86_64.mk b/core/combo/arch/x86_64/x86_64.mk
index 26a9d0f..e7c8928 100755
--- a/core/combo/arch/x86_64/x86_64.mk
+++ b/core/combo/arch/x86_64/x86_64.mk
@@ -11,3 +11,6 @@
 ARCH_X86_HAVE_SSE4 := true
 ARCH_X86_HAVE_SSE4_1 := true
 ARCH_X86_HAVE_SSE4_2 := true
+ARCH_X86_HAVE_AVX := false
+ARCH_X86_HAVE_AVX2 := false
+ARCH_X86_HAVE_AVX512 := false
diff --git a/core/config.mk b/core/config.mk
index 0bc460e..cca6200 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -836,17 +836,18 @@
     ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
         $(error BOARD_BUILD_SYSTEM_ROOT_IMAGE cannot be true for devices with dynamic partitions)
     endif
-
-    requirements := \
-        PRODUCT_USE_DYNAMIC_PARTITION_SIZE \
-        PRODUCT_BUILD_SUPER_PARTITION \
-
-    $(foreach req,$(requirements),$(if $(filter false,$($(req))),\
-        $(error PRODUCT_USE_DYNAMIC_PARTITIONS requires $(req) to be true)))
-
-    requirements :=
+    ifneq ($(PRODUCT_USE_DYNAMIC_PARTITION_SIZE),true)
+        $(error PRODUCT_USE_DYNAMIC_PARTITION_SIZE must be true for devices with dynamic partitions)
+    endif
 endif
 
+ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
+    ifneq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
+        $(error Can only build super partition for devices with dynamic partitions)
+    endif
+endif
+
+
 ifeq ($(PRODUCT_USE_DYNAMIC_PARTITION_SIZE),true)
 
 ifneq ($(BOARD_SYSTEMIMAGE_PARTITION_SIZE),)
@@ -886,7 +887,7 @@
 
 endif # PRODUCT_USE_DYNAMIC_PARTITION_SIZE
 
-ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
+ifeq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
 
 # BOARD_SUPER_PARTITION_GROUPS defines a list of "updatable groups". Each updatable group is a
 # group of partitions that share the same pool of free spaces.
@@ -897,12 +898,16 @@
 #     - BOARD_{GROUP}_PARTITION_PARTITION_LIST: the list of partitions that belongs to this group.
 #       If empty, no partitions belong to this group, and the sum of sizes is effectively 0.
 $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
-    $(eval BOARD_$(group)_SIZE := $(strip $(BOARD_$(group)_SIZE))) \
-    $(if $(BOARD_$(group)_SIZE),,$(error BOARD_$(group)_SIZE must not be empty)) \
-    $(eval .KATI_READONLY := BOARD_$(group)_SIZE) \
     $(eval BOARD_$(group)_PARTITION_LIST ?=) \
     $(eval .KATI_READONLY := BOARD_$(group)_PARTITION_LIST) \
 )
+ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
+$(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
+    $(eval BOARD_$(group)_SIZE := $(strip $(BOARD_$(group)_SIZE))) \
+    $(if $(BOARD_$(group)_SIZE),,$(error BOARD_$(group)_SIZE must not be empty)) \
+    $(eval .KATI_READONLY := BOARD_$(group)_SIZE) \
+)
+endif # PRODUCT_BUILD_SUPER_PARTITION
 
 # BOARD_*_PARTITION_LIST: a list of the following tokens
 valid_super_partition_list := system vendor product product_services odm
@@ -924,6 +929,10 @@
         $(BOARD_$(group)_PARTITION_LIST))
 .KATI_READONLY := BOARD_SUPER_PARTITION_PARTITION_LIST
 
+endif # PRODUCT_USE_DYNAMIC_PARTITIONS
+
+ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
+
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
 
diff --git a/core/definitions.mk b/core/definitions.mk
index e880fa5..02b737c 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -651,6 +651,18 @@
 
 ###########################################################
 ## Convert a list of short modules names (e.g., "framework", "Browser")
+## into the list of files that are built *for the target* for those modules.
+## NOTE: this won't return reliable results until after all
+## sub-makefiles have been included.
+## $(1): target list
+###########################################################
+
+define module-target-built-files
+$(foreach module,$(1),$(ALL_MODULES.$(module).TARGET_BUILT))
+endef
+
+###########################################################
+## Convert a list of short modules names (e.g., "framework", "Browser")
 ## into the list of files that should be used when linking
 ## against that module as a public API.
 ## TODO: Allow this for more than JAVA_LIBRARIES modules
@@ -3318,9 +3330,8 @@
   $(eval enforce_rro_source_manifest_package_info := $(word 3,$(_o))) \
   $(eval enforce_rro_use_res_lib := $(word 4,$(_o))) \
   $(eval enforce_rro_source_overlays := $(subst :, ,$(word 5,$(_o)))) \
-  $(eval enforce_rro_module := $(enforce_rro_source_module)__auto_generated_rro) \
   $(eval include $(BUILD_SYSTEM)/generate_enforce_rro.mk) \
-  $(eval ALL_MODULES.$(enforce_rro_source_module).REQUIRED += $(enforce_rro_module)) \
+  $(eval ALL_MODULES.$$(enforce_rro_source_module).REQUIRED += $$(LOCAL_PACKAGE_NAME)) \
 )
 endef
 
@@ -3387,3 +3398,19 @@
   initialize-package-file \
   add-jni-shared-libs-to-package,\
   These functions have been removed)
+
+###########################################################
+## Verify the variants of a VNDK library are identical
+##
+## $(1): Path to the core variant shared library file.
+## $(2): Path to the vendor variant shared library file.
+## $(3): TOOLS_PREFIX
+###########################################################
+LIBRARY_IDENTITY_CHECK_SCRIPT := build/make/tools/check_identical_lib.sh
+define verify-vndk-libs-identical
+@echo "Checking VNDK vendor variant: $(2)"
+$(hide) CLANG_BIN="$(LLVM_PREBUILTS_PATH)" \
+	CROSS_COMPILE="$(strip $(3))" \
+	XZ="$(XZ)" \
+	$(LIBRARY_IDENTITY_CHECK_SCRIPT) $(SOONG_STRIP_PATH) $(1) $(2)
+endef
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index ad734b5..ad073c7 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -67,6 +67,7 @@
 ALL_MODULES += $(dpi_apk_name)
 ALL_MODULES.$(dpi_apk_name).CLASS := APPS
 ALL_MODULES.$(dpi_apk_name).BUILT := $(built_dpi_apk)
+ALL_MODULES.$(dpi_apk_name).TARGET_BUILT := $(built_dpi_apk)
 PACKAGES := $(PACKAGES) $(dpi_apk_name)
 PACKAGES.$(dpi_apk_name).PRIVATE_KEY := $(private_key)
 PACKAGES.$(dpi_apk_name).CERTIFICATE := $(certificate)
diff --git a/core/generate_enforce_rro.mk b/core/generate_enforce_rro.mk
index 6c95983..6124a4f 100644
--- a/core/generate_enforce_rro.mk
+++ b/core/generate_enforce_rro.mk
@@ -1,24 +1,29 @@
 include $(CLEAR_VARS)
 
+enforce_rro_module := $(enforce_rro_source_module)__auto_generated_rro
 LOCAL_PACKAGE_NAME := $(enforce_rro_module)
 
 intermediates := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
 rro_android_manifest_file := $(intermediates)/AndroidManifest.xml
 
 ifeq (true,$(enforce_rro_source_is_manifest_package_name))
-$(rro_android_manifest_file): PRIVATE_PACKAGE_NAME := $(enforce_rro_source_manifest_package_info)
-$(rro_android_manifest_file): build/make/tools/generate-enforce-rro-android-manifest.py
-	$(hide) build/make/tools/generate-enforce-rro-android-manifest.py -u -p $(PRIVATE_PACKAGE_NAME) -o $@
+  use_package_name_arg := --use-package-name
 else
-$(rro_android_manifest_file): PRIVATE_SOURCE_MANIFEST_FILE := $(enforce_rro_source_manifest_package_info)
-$(rro_android_manifest_file): $(enforce_rro_source_manifest_package_info) build/make/tools/generate-enforce-rro-android-manifest.py
-	$(hide) build/make/tools/generate-enforce-rro-android-manifest.py -p $(PRIVATE_SOURCE_MANIFEST_FILE) -o $@
+  use_package_name_arg :=
+$(rro_android_manifest_file): $(enforce_rro_source_manifest_package_info)
 endif
 
+$(rro_android_manifest_file): PRIVATE_PACKAGE_INFO := $(enforce_rro_source_manifest_package_info)
+$(rro_android_manifest_file): build/make/tools/generate-enforce-rro-android-manifest.py
+	$(hide) build/make/tools/generate-enforce-rro-android-manifest.py \
+	    --package-info $(PRIVATE_PACKAGE_INFO) \
+	    $(use_package_name_arg) \
+	    -o $@
+
 LOCAL_PATH:= $(intermediates)
 
 ifeq ($(enforce_rro_use_res_lib),true)
-LOCAL_RES_LIBRARIES := $(enforce_rro_source_module)
+  LOCAL_RES_LIBRARIES := $(enforce_rro_source_module)
 endif
 
 LOCAL_FULL_MANIFEST_FILE := $(rro_android_manifest_file)
@@ -32,7 +37,7 @@
   # Technically we are linking against the app (if only to grab its resources),
   # and because it's potentially not building against the SDK, we can't either.
   LOCAL_PRIVATE_PLATFORM_APIS := true
-else ifeq (framework-res__auto_generated_rro,$(enforce_rro_module))
+else ifeq (framework-res,$(enforce_rro_source_module))
   LOCAL_PRIVATE_PLATFORM_APIS := true
 else
   LOCAL_SDK_VERSION := current
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index e0f1ad4..a79a49a 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -113,12 +113,12 @@
 my_warn_types := native:platform $(my_warn_ndk_types)
 my_allowed_types := $(my_allowed_ndk_types)
     ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
-        my_allowed_types += native:vendor native:vndk
+        my_allowed_types += native:vendor native:vndk native:platform_vndk
     endif
 else
 my_link_type := app:platform
 my_warn_types := $(my_warn_ndk_types)
-my_allowed_types := $(my_allowed_ndk_types) native:platform native:vendor native:vndk native:vndk_private
+my_allowed_types := $(my_allowed_ndk_types) native:platform native:vendor native:vndk native:vndk_private native:platform_vndk
 endif
 
 my_link_deps := $(addprefix SHARED_LIBRARIES:,$(LOCAL_JNI_SHARED_LIBRARIES))
diff --git a/core/main.mk b/core/main.mk
index 22cba4e..43c80ee 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -501,6 +501,10 @@
 subdir_makefiles_total := $(words init post finish)
 endif
 
+droid_targets: no_vendor_variant_vndk_check
+.PHONY: no_vendor_variant_vndk_check
+no_vendor_variant_vndk_check:
+
 $(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] finishing build rules ...)
 
 # -------------------------------------------------------------------
@@ -1144,27 +1148,28 @@
 )
 endef
 
-ifeq (true|,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_PACKAGES_EXIST)|$(filter true,$(ALLOW_MISSING_DEPENDENCIES)))
-  _whitelist := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_PACKAGES_EXIST_WHITELIST)
-  _modules := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
-  # Sanity check all modules in PRODUCT_PACKAGES exist. We check for the
-  # existence if either <module> or the <module>_32 variant.
-  _nonexistant_modules := $(filter-out $(ALL_MODULES),$(_modules))
-  _nonexistant_modules := $(foreach m,$(_nonexistant_modules),\
-    $(if $(call get-32-bit-modules,$(m)),,$(m)))
-  $(call maybe-print-list-and-error,$(filter-out $(_whitelist),$(_nonexistant_modules)),\
-    $(INTERNAL_PRODUCT) includes non-existant modules in PRODUCT_PACKAGES)
-  $(call maybe-print-list-and-error,$(filter-out $(_nonexistant_modules),$(_whitelist)),\
-    $(INTERNAL_PRODUCT) includes redundant whitelist entries for nonexistant PRODUCT_PACKAGES)
-endif
-
 ifdef FULL_BUILD
-  # Check to ensure that all modules in PRODUCT_HOST_PACKAGES exist
-  #
-  # Many host modules are Linux-only, so skip this check on Mac. If we ever have Mac-only modules,
-  # maybe it would make sense to have PRODUCT_HOST_PACKAGES_LINUX/_DARWIN?
-  ifneq ($(HOST_OS),darwin)
-    ifneq (true,$(ALLOW_MISSING_DEPENDENCIES))
+  ifneq (true,$(ALLOW_MISSING_DEPENDENCIES))
+    # Check to ensure that all modules in PRODUCT_PACKAGES exist (opt in per product)
+    ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_PACKAGES_EXIST))
+      _whitelist := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_PACKAGES_EXIST_WHITELIST)
+      _modules := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
+      # Sanity check all modules in PRODUCT_PACKAGES exist. We check for the
+      # existence if either <module> or the <module>_32 variant.
+      _nonexistant_modules := $(filter-out $(ALL_MODULES),$(_modules))
+      _nonexistant_modules := $(foreach m,$(_nonexistant_modules),\
+        $(if $(call get-32-bit-modules,$(m)),,$(m)))
+      $(call maybe-print-list-and-error,$(filter-out $(_whitelist),$(_nonexistant_modules)),\
+        $(INTERNAL_PRODUCT) includes non-existant modules in PRODUCT_PACKAGES)
+      $(call maybe-print-list-and-error,$(filter-out $(_nonexistant_modules),$(_whitelist)),\
+        $(INTERNAL_PRODUCT) includes redundant whitelist entries for nonexistant PRODUCT_PACKAGES)
+    endif
+
+    # Check to ensure that all modules in PRODUCT_HOST_PACKAGES exist
+    #
+    # Many host modules are Linux-only, so skip this check on Mac. If we ever have Mac-only modules,
+    # maybe it would make sense to have PRODUCT_HOST_PACKAGES_LINUX/_DARWIN?
+    ifneq ($(HOST_OS),darwin)
       _modules := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_HOST_PACKAGES)
       _nonexistant_modules := $(foreach m,$(_modules),\
         $(if $(filter FAKE,$(ALL_MODULES.$(m).CLASS))$(filter $(HOST_OUT_ROOT)/%,$(ALL_MODULES.$(m).INSTALLED)),,$(m)))
@@ -1582,21 +1587,21 @@
   ifeq ($(EMMA_INSTRUMENT),true)
     $(JACOCO_REPORT_CLASSES_ALL) : $(INSTALLED_SYSTEMIMAGE_TARGET)
     $(call dist-for-goals, dist_files, $(JACOCO_REPORT_CLASSES_ALL))
+  endif
 
-    # Put XML formatted API files in the dist dir.
-    $(TARGET_OUT_COMMON_INTERMEDIATES)/api.xml: $(call java-lib-header-files,android_stubs_current) $(APICHECK)
-    $(TARGET_OUT_COMMON_INTERMEDIATES)/system-api.xml: $(call java-lib-header-files,android_system_stubs_current) $(APICHECK)
-    $(TARGET_OUT_COMMON_INTERMEDIATES)/test-api.xml: $(call java-lib-header-files,android_test_stubs_current) $(APICHECK)
+  # Put XML formatted API files in the dist dir.
+  $(TARGET_OUT_COMMON_INTERMEDIATES)/api.xml: $(call java-lib-header-files,android_stubs_current) $(APICHECK)
+  $(TARGET_OUT_COMMON_INTERMEDIATES)/system-api.xml: $(call java-lib-header-files,android_system_stubs_current) $(APICHECK)
+  $(TARGET_OUT_COMMON_INTERMEDIATES)/test-api.xml: $(call java-lib-header-files,android_test_stubs_current) $(APICHECK)
 
-    api_xmls := $(addprefix $(TARGET_OUT_COMMON_INTERMEDIATES)/,api.xml system-api.xml test-api.xml)
-    $(api_xmls):
+  api_xmls := $(addprefix $(TARGET_OUT_COMMON_INTERMEDIATES)/,api.xml system-api.xml test-api.xml)
+  $(api_xmls):
 	$(hide) echo "Converting API file to XML: $@"
 	$(hide) mkdir -p $(dir $@)
 	$(hide) $(APICHECK_COMMAND) --input-api-jar $< --api-xml $@
 
-    $(call dist-for-goals, dist_files, $(api_xmls))
-    api_xmls :=
-  endif
+  $(call dist-for-goals, dist_files, $(api_xmls))
+  api_xmls :=
 
 # Building a full system-- the default is to build droidcore
 droid_targets: droidcore dist_files
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 3be4635..89296e6 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -109,56 +109,50 @@
 # Process Support Library dependencies.
 include $(BUILD_SYSTEM)/support_libraries.mk
 
-package_resource_overlays := $(strip \
+# Determine whether auto-RRO is enabled for this package.
+enforce_rro_enabled :=
+ifeq ($(PRODUCT_ENFORCE_RRO_TARGETS),*)
+  # * means all system APKs, so enable conditionally based on module path.
+
+  # Note that base_rules.mk has not yet been included, so it's likely that only
+  # one of LOCAL_MODULE_PATH and the LOCAL_X_MODULE flags has been set.
+  ifeq (,$(LOCAL_MODULE_PATH))
+    non_system_module := $(filter true,\
+        $(LOCAL_ODM_MODULE) \
+        $(LOCAL_OEM_MODULE) \
+        $(LOCAL_PRODUCT_MODULE) \
+        $(LOCAL_PRODUCT_SERVICES_MODULE) \
+        $(LOCAL_PROPRIETARY_MODULE) \
+        $(LOCAL_VENDOR_MODULE))
+    enforce_rro_enabled := $(if $(non_system_module),,true)
+  else ifneq ($(filter $(TARGET_OUT)/%,$(LOCAL_MODULE_PATH)),)
+    enforce_rro_enabled := true
+  endif
+else ifneq (,$(filter $(LOCAL_PACKAGE_NAME), $(PRODUCT_ENFORCE_RRO_TARGETS)))
+  enforce_rro_enabled := true
+endif
+
+all_package_resource_overlays := $(strip \
     $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
       $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \
     $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \
       $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
 
-enforce_rro_enabled :=
-ifneq ($(PRODUCT_ENFORCE_RRO_TARGETS),)
-  ifneq ($(package_resource_overlays),)
-    ifeq ($(PRODUCT_ENFORCE_RRO_TARGETS),*)
-      enforce_rro_enabled := true
-    else ifneq (,$(filter $(LOCAL_PACKAGE_NAME), $(PRODUCT_ENFORCE_RRO_TARGETS)))
-      enforce_rro_enabled := true
-    endif
-  endif
-
-  ifdef enforce_rro_enabled
-    ifeq (,$(LOCAL_MODULE_PATH))
-      ifeq (true,$(LOCAL_PROPRIETARY_MODULE))
-        enforce_rro_enabled :=
-      else ifeq (true,$(LOCAL_OEM_MODULE))
-        enforce_rro_enabled :=
-      else ifeq (true,$(LOCAL_ODM_MODULE))
-        enforce_rro_enabled :=
-      else ifeq (true,$(LOCAL_PRODUCT_MODULE))
-        enforce_rro_enabled :=
-      else ifeq (true,$(LOCAL_PRODUCT_SERVICES_MODULE))
-        enforce_rro_enabled :=
-      endif
-    else ifeq ($(filter $(TARGET_OUT)/%,$(LOCAL_MODULE_PATH)),)
-      enforce_rro_enabled :=
-    endif
-  endif
-endif
-
+static_resource_overlays :=
+runtime_resource_overlays :=
 ifdef enforce_rro_enabled
   ifneq ($(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS),)
-    static_only_resource_overlays := $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(package_resource_overlays))
-    ifneq ($(static_only_resource_overlays),)
-      package_resource_overlays := $(filter-out $(static_only_resource_overlays),$(package_resource_overlays))
-      LOCAL_RESOURCE_DIR := $(static_only_resource_overlays) $(LOCAL_RESOURCE_DIR)
-      ifeq ($(package_resource_overlays),)
-        enforce_rro_enabled :=
-      endif
-    endif
+    static_resource_overlays += $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(all_package_resource_overlays))
   endif
+  runtime_resource_overlays := $(filter-out $(static_resource_overlays),$(all_package_resource_overlays))
 else
-LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR)
+  static_resource_overlays := $(all_package_resource_overlays)
 endif
 
+# Add the static overlays. Auto-RRO is created later, as it depends on
+# other logic in this file.
+LOCAL_RESOURCE_DIR := $(static_resource_overlays) $(LOCAL_RESOURCE_DIR)
+
 all_assets := $(strip \
     $(foreach dir, $(LOCAL_ASSET_DIR), \
       $(addprefix $(dir)/, \
@@ -796,7 +790,7 @@
 # Reset internal variables.
 all_res_assets :=
 
-ifdef enforce_rro_enabled
+ifdef runtime_resource_overlays
   ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
     enforce_rro_use_res_lib := true
   else
@@ -811,11 +805,11 @@
     enforce_rro_manifest_package_info := $(full_android_manifest)
   endif
 
-$(call append_enforce_rro_sources, \
-    $(my_register_name), \
-    $(enforce_rro_is_manifest_package_name), \
-    $(enforce_rro_manifest_package_info), \
-    $(enforce_rro_use_res_lib), \
-    $(package_resource_overlays) \
-    )
-endif  # enforce_rro_enabled
+  $(call append_enforce_rro_sources, \
+      $(my_register_name), \
+      $(enforce_rro_is_manifest_package_name), \
+      $(enforce_rro_manifest_package_info), \
+      $(enforce_rro_use_res_lib), \
+      $(runtime_resource_overlays) \
+  )
+endif
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index c5ea538..e505945 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -39,6 +39,13 @@
 
 LOCAL_CHECKED_MODULE := $(my_prebuilt_src_file)
 
+ifeq (APPS,$(LOCAL_MODULE_CLASS))
+include $(BUILD_SYSTEM)/app_prebuilt_internal.mk
+else
+#
+# Non-APPS prebuilt modules handling almost to the end of the file
+#
+
 my_strip_module := $(firstword \
   $(LOCAL_STRIP_MODULE_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) \
   $(LOCAL_STRIP_MODULE))
@@ -69,44 +76,9 @@
   prebuilt_module_is_dex_javalib :=
 endif
 
-# Run veridex on product, product_services and vendor modules.
-# We skip it for unbundled app builds where we cannot build veridex.
-module_run_appcompat :=
-ifeq (true,$(non_system_module))
-ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))  # ! unbundled app build
-ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
-  module_run_appcompat := true
-endif
-endif
-endif
-
-ifdef LOCAL_COMPRESSED_MODULE
-ifneq (true,$(LOCAL_COMPRESSED_MODULE))
-$(call pretty-error, Unknown value for LOCAL_COMPRESSED_MODULE $(LOCAL_COMPRESSED_MODULE))
-endif
-endif
-
-ifeq ($(LOCAL_MODULE_CLASS),APPS)
-ifdef LOCAL_COMPRESSED_MODULE
-LOCAL_BUILT_MODULE_STEM := package.apk.gz
-else
-LOCAL_BUILT_MODULE_STEM := package.apk
-endif  # LOCAL_COMPRESSED_MODULE
-
-ifndef LOCAL_INSTALLED_MODULE_STEM
-ifdef LOCAL_COMPRESSED_MODULE
-PACKAGES.$(LOCAL_MODULE).COMPRESSED := gz
-LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk.gz
-else
-LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk
-endif  # LOCAL_COMPRESSED_MODULE
-endif  # LOCAL_INSTALLED_MODULE_STEM
-
-else  # $(LOCAL_MODULE_CLASS) != APPS)
 ifdef LOCAL_COMPRESSED_MODULE
 $(error $(LOCAL_MODULE) : LOCAL_COMPRESSED_MODULE can only be defined for module class APPS)
 endif  # LOCAL_COMPRESSED_MODULE
-endif
 
 my_check_elf_file_shared_lib_files :=
 
@@ -247,234 +219,7 @@
 endif
 endif
 
-ifeq ($(LOCAL_MODULE_CLASS),APPS)
-PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
-
-my_extract_apk := $(strip $(LOCAL_EXTRACT_APK))
-
-# Select dpi-specific source
-ifdef LOCAL_DPI_VARIANTS
-my_dpi := $(firstword $(filter $(LOCAL_DPI_VARIANTS),$(PRODUCT_AAPT_PREF_CONFIG) $(PRODUCT_AAPT_PREBUILT_DPI)))
-ifdef my_dpi
-ifdef LOCAL_DPI_FILE_STEM
-my_prebuilt_dpi_file_stem := $(LOCAL_DPI_FILE_STEM)
-else
-my_prebuilt_dpi_file_stem := $(LOCAL_MODULE)_%.apk
-endif
-my_prebuilt_src_file := $(dir $(my_prebuilt_src_file))$(subst %,$(my_dpi),$(my_prebuilt_dpi_file_stem))
-
-ifneq ($(strip $(LOCAL_EXTRACT_DPI_APK)),)
-my_extract_apk := $(subst %,$(my_dpi),$(LOCAL_EXTRACT_DPI_APK))
-endif  # LOCAL_EXTRACT_DPI_APK
-endif  # my_dpi
-endif  # LOCAL_DPI_VARIANTS
-
-ifdef my_extract_apk
-my_extracted_apk := $(intermediates)/extracted.apk
-
-$(my_extracted_apk): PRIVATE_EXTRACT := $(my_extract_apk)
-$(my_extracted_apk): $(my_prebuilt_src_file)
-	@echo Extract APK: $@
-	$(hide) mkdir -p $(dir $@) && rm -f $@
-	$(hide) unzip -p $< $(PRIVATE_EXTRACT) >$@
-
-my_prebuilt_src_file := $(my_extracted_apk)
-my_extracted_apk :=
-my_extract_apk :=
-ifeq ($(PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK),true)
-# If the product property is set, always preopt for extracted modules to prevent executing out of
-# the APK.
-my_preopt_for_extracted_apk := true
-endif
-endif
-
-dex_preopt_profile_src_file := $(my_prebuilt_src_file)
-
-rs_compatibility_jni_libs :=
-include $(BUILD_SYSTEM)/install_jni_libs.mk
-
-ifeq ($(LOCAL_CERTIFICATE),EXTERNAL)
-  # The magic string "EXTERNAL" means this package will be signed with
-  # the default dev key throughout the build process, but we expect
-  # the final package to be signed with a different key.
-  #
-  # This can be used for packages where we don't have access to the
-  # keys, but want the package to be predexopt'ed.
-  LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
-  PACKAGES.$(LOCAL_MODULE).EXTERNAL_KEY := 1
-
-  $(built_module) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
-  $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
-  $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
-endif
-ifeq ($(LOCAL_CERTIFICATE),)
-  # It is now a build error to add a prebuilt .apk without
-  # specifying a key for it.
-  $(error No LOCAL_CERTIFICATE specified for prebuilt "$(my_prebuilt_src_file)")
-else ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
-  # The magic string "PRESIGNED" means this package is already checked
-  # signed with its release key.
-  #
-  # By setting .CERTIFICATE but not .PRIVATE_KEY, this package will be
-  # mentioned in apkcerts.txt (with certificate set to "PRESIGNED")
-  # but the dexpreopt process will not try to re-sign the app.
-  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := PRESIGNED
-  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
-else
-  # If this is not an absolute certificate, assign it to a generic one.
-  ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)
-      LOCAL_CERTIFICATE := $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))$(LOCAL_CERTIFICATE)
-  endif
-
-  PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
-  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
-  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
-
-  $(built_module) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
-  $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
-  $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
-endif
-
-include $(BUILD_SYSTEM)/app_certificate_validate.mk
-
-# Disable dex-preopt of prebuilts to save space, if requested.
-ifndef LOCAL_DEX_PREOPT
-ifeq ($(DONT_DEXPREOPT_PREBUILTS),true)
-LOCAL_DEX_PREOPT := false
-endif
-endif
-
-# If the module is a compressed module, we don't pre-opt it because its final
-# installation location will be the data partition.
-ifdef LOCAL_COMPRESSED_MODULE
-LOCAL_DEX_PREOPT := false
-endif
-
-my_dex_jar := $(my_prebuilt_src_file)
-
-#######################################
-# defines built_odex along with rule to install odex
-include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
-#######################################
-ifneq ($(LOCAL_REPLACE_PREBUILT_APK_INSTALLED),)
-# There is a replacement for the prebuilt .apk we can install without any processing.
-$(built_module) : $(LOCAL_REPLACE_PREBUILT_APK_INSTALLED)
-	$(transform-prebuilt-to-target)
-
-else  # ! LOCAL_REPLACE_PREBUILT_APK_INSTALLED
-# Sign and align non-presigned .apks.
-# The embedded prebuilt jni to uncompress.
-ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
-# For PRESIGNED apks we must uncompress every .so file:
-# even if the .so file isn't for the current TARGET_ARCH,
-# we can't strip the file.
-embedded_prebuilt_jni_libs :=
-endif
-ifndef embedded_prebuilt_jni_libs
-# No LOCAL_PREBUILT_JNI_LIBS, uncompress all.
-embedded_prebuilt_jni_libs :=
-endif
-$(built_module): PRIVATE_EMBEDDED_JNI_LIBS := $(embedded_prebuilt_jni_libs)
-
-ifdef LOCAL_COMPRESSED_MODULE
-$(built_module) : $(MINIGZIP)
-endif
-
-ifeq ($(module_run_appcompat),true)
-$(built_module) : $(appcompat-files)
-$(LOCAL_BUILT_MODULE): PRIVATE_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
-endif
-
-ifneq ($(BUILD_PLATFORM_ZIP),)
-$(built_module) : .KATI_IMPLICIT_OUTPUTS := $(dir $(LOCAL_BUILT_MODULE))package.dex.apk
-endif
-ifneq ($(LOCAL_CERTIFICATE),PRESIGNED)
-ifdef LOCAL_DEX_PREOPT
-$(built_module) : PRIVATE_STRIP_SCRIPT := $(intermediates)/strip.sh
-$(built_module) : $(intermediates)/strip.sh
-$(built_module) : | $(DEXPREOPT_STRIP_DEPS)
-$(built_module) : .KATI_DEPFILE := $(built_module).d
-endif
-endif
-$(built_module) : $(my_prebuilt_src_file) | $(ZIPALIGN) $(ZIP2ZIP) $(SIGNAPK_JAR)
-	$(transform-prebuilt-to-target)
-	$(uncompress-prebuilt-embedded-jni-libs)
-ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
-	$(uncompress-dexs)
-endif  # LOCAL_UNCOMPRESS_DEX
-ifdef LOCAL_DEX_PREOPT
-ifneq ($(BUILD_PLATFORM_ZIP),)
-	@# Keep a copy of apk with classes.dex unstripped
-	$(hide) cp -f $@ $(dir $@)package.dex.apk
-endif  # BUILD_PLATFORM_ZIP
-endif  # LOCAL_DEX_PREOPT
-ifneq ($(LOCAL_CERTIFICATE),PRESIGNED)
-	@# Only strip out files if we can re-sign the package.
-# Run appcompat before stripping the classes.dex file.
-ifeq ($(module_run_appcompat),true)
-ifeq ($(LOCAL_USE_AAPT2),true)
-	$(call appcompat-header, aapt2)
-else
-	$(appcompat-header)
-endif
-	$(run-appcompat)
-endif  # module_run_appcompat
-ifdef LOCAL_DEX_PREOPT
-	mv -f $@ $@.tmp
-	$(PRIVATE_STRIP_SCRIPT) $@.tmp $@
-endif  # LOCAL_DEX_PREOPT
-	$(sign-package)
-	# No need for align-package because sign-package takes care of alignment
-else  # LOCAL_CERTIFICATE == PRESIGNED
-	$(align-package)
-endif  # LOCAL_CERTIFICATE
-ifdef LOCAL_COMPRESSED_MODULE
-	$(compress-package)
-endif  # LOCAL_COMPRESSED_MODULE
-endif  # ! LOCAL_REPLACE_PREBUILT_APK_INSTALLED
-
-
-###############################
-## Install split apks.
-ifdef LOCAL_PACKAGE_SPLITS
-ifdef LOCAL_COMPRESSED_MODULE
-$(error $(LOCAL_MODULE): LOCAL_COMPRESSED_MODULE is not currently supported for split installs)
-endif  # LOCAL_COMPRESSED_MODULE
-
-# LOCAL_PACKAGE_SPLITS is a list of apks to be installed.
-built_apk_splits := $(addprefix $(intermediates)/,$(notdir $(LOCAL_PACKAGE_SPLITS)))
-installed_apk_splits := $(addprefix $(my_module_path)/,$(notdir $(LOCAL_PACKAGE_SPLITS)))
-
-# Rules to sign the split apks.
-my_src_dir := $(sort $(dir $(LOCAL_PACKAGE_SPLITS)))
-ifneq (1,$(words $(my_src_dir)))
-$(error You must put all the split source apks in the same folder: $(LOCAL_PACKAGE_SPLITS))
-endif
-my_src_dir := $(LOCAL_PATH)/$(my_src_dir)
-
-$(built_apk_splits) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
-$(built_apk_splits) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
-$(built_apk_splits) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
-$(built_apk_splits) : $(intermediates)/%.apk : $(my_src_dir)/%.apk
-	$(copy-file-to-new-target)
-	$(sign-package)
-
-# Rules to install the split apks.
-$(installed_apk_splits) : $(my_module_path)/%.apk : $(intermediates)/%.apk
-	@echo "Install: $@"
-	$(copy-file-to-new-target)
-
-# Register the additional built and installed files.
-ALL_MODULES.$(my_register_name).INSTALLED += $(installed_apk_splits)
-ALL_MODULES.$(my_register_name).BUILT_INSTALLED += \
-  $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(intermediates)/$(notdir $(s)):$(my_module_path)/$(notdir $(s)))
-
-# Make sure to install the splits when you run "make <module_name>".
-$(my_all_targets): $(installed_apk_splits)
-
-endif # LOCAL_PACKAGE_SPLITS
-
-else ifeq ($(prebuilt_module_is_dex_javalib),true)  # ! LOCAL_MODULE_CLASS != APPS
+ifeq ($(prebuilt_module_is_dex_javalib),true)
 my_dex_jar := $(my_prebuilt_src_file)
 # This is a target shared library, i.e. a jar with classes.dex.
 
@@ -701,6 +446,8 @@
 
 endif # JAVA_LIBRARIES
 
+endif # APPS
+
 $(built_module) : $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
 my_prebuilt_src_file :=
diff --git a/core/product-graph.mk b/core/product-graph.mk
index 1efc687..a114b65 100644
--- a/core/product-graph.mk
+++ b/core/product-graph.mk
@@ -36,8 +36,6 @@
 
 this_makefile := build/make/core/product-graph.mk
 
-products_svg := $(OUT_DIR)/products.svg
-products_pdf := $(OUT_DIR)/products.pdf
 products_graph := $(OUT_DIR)/products.dot
 ifeq ($(strip $(ANDROID_PRODUCT_GRAPH)),)
 products_list := $(INTERNAL_PRODUCT)
@@ -137,13 +135,8 @@
 			$(eval product_debug_files += $(call product-debug-filename, $(p))) \
    )
 
-$(products_pdf): $(products_graph)
-	@echo Product graph PDF: $@
-	dot -Tpdf -Nshape=box -o $@ $<
-
-$(products_svg): $(products_graph) $(product_debug_files)
-	@echo Product graph SVG: $@
-	dot -Tsvg -Nshape=box -o $@ $<
-
-product-graph: $(products_pdf) $(products_svg)
 .PHONY: product-graph
+product-graph: $(products_graph)
+	@echo Product graph .dot file: $(products_graph)
+	@echo Command to convert to pdf: dot -Tpdf -Nshape=box -o $(OUT_DIR)/products.pdf $(products_graph)
+	@echo Command to convert to svg: dot -Tsvg -Nshape=box -o $(OUT_DIR)/products.svg $(products_graph)
diff --git a/core/product.mk b/core/product.mk
index a367a6b..bb63ab8 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -126,6 +126,11 @@
     PRODUCT_DEVICE \
     PRODUCT_MANUFACTURER \
     PRODUCT_BRAND \
+    PRODUCT_SYSTEM_NAME \
+    PRODUCT_SYSTEM_MODEL \
+    PRODUCT_SYSTEM_DEVICE \
+    PRODUCT_SYSTEM_BRAND \
+    PRODUCT_SYSTEM_MANUFACTURER \
     PRODUCT_PROPERTY_OVERRIDES \
     PRODUCT_DEFAULT_PROPERTY_OVERRIDES \
     PRODUCT_PRODUCT_PROPERTIES \
diff --git a/core/product_config.mk b/core/product_config.mk
index cff42db..7ab1d6d 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -299,18 +299,39 @@
 PRODUCT_AAPT_CONFIG := \
     $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
 
+PRODUCT_SYSTEM_NAME := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_NAME))
+ifndef PRODUCT_SYSTEM_NAME
+  PRODUCT_SYSTEM_NAME := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))
+endif
+
+PRODUCT_SYSTEM_DEVICE := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_DEVICE))
+ifndef PRODUCT_SYSTEM_DEVICE
+  PRODUCT_SYSTEM_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)
+endif
+
 PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
+PRODUCT_SYSTEM_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BRAND))
+ifndef PRODUCT_SYSTEM_BRAND
+  PRODUCT_SYSTEM_BRAND := $(PRODUCT_BRAND)
+endif
 
 PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))
 ifndef PRODUCT_MODEL
   PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))
 endif
+PRODUCT_SYSTEM_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_MODEL))
+ifndef PRODUCT_SYSTEM_MODEL
+  PRODUCT_SYSTEM_MODEL := $(PRODUCT_MODEL)
+endif
 
-PRODUCT_MANUFACTURER := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
+PRODUCT_MANUFACTURER := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
 ifndef PRODUCT_MANUFACTURER
   PRODUCT_MANUFACTURER := unknown
 endif
+PRODUCT_SYSTEM_MANUFACTURER := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_MANUFACTURER))
+ifndef PRODUCT_SYSTEM_MANUFACTURER
+  PRODUCT_SYSTEM_MANUFACTURER := $(PRODUCT_MANUFACTURER)
+endif
 
 ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)
   TARGET_AAPT_CHARACTERISTICS := default
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index a9169eb..cfcb0c6 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -159,13 +159,13 @@
 include $(BUILD_SYSTEM)/link_type.mk
 endif # !LOCAL_IS_HOST_MODULE
 
-ifdef LOCAL_SOONG_RRO_DIRS
+ifneq (,$(LOCAL_SOONG_DEVICE_RRO_DIRS)$(LOCAL_SOONG_PRODUCT_RRO_DIRS))
   $(call append_enforce_rro_sources, \
       $(my_register_name), \
       false, \
       $(LOCAL_FULL_MANIFEST_FILE), \
       $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
-      $(LOCAL_SOONG_RRO_DIRS))
+      $(LOCAL_SOONG_DEVICE_RRO_DIRS) $(LOCAL_SOONG_PRODUCT_RRO_DIRS))
 endif
 
 SOONG_ALREADY_CONV := $(SOONG_ALREADY_CONV) $(LOCAL_MODULE)
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index dd33852..679d5b8 100644
--- a/core/soong_cc_prebuilt.mk
+++ b/core/soong_cc_prebuilt.mk
@@ -86,11 +86,13 @@
 endif
 
 ifdef LOCAL_USE_VNDK
-  name_without_suffix := $(patsubst %.vendor,%,$(LOCAL_MODULE))
-  ifneq ($(name_without_suffix),$(LOCAL_MODULE)
-    SPLIT_VENDOR.$(LOCAL_MODULE_CLASS).$(name_without_suffix) := 1
+  ifneq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+    name_without_suffix := $(patsubst %.vendor,%,$(LOCAL_MODULE))
+    ifneq ($(name_without_suffix),$(LOCAL_MODULE)
+      SPLIT_VENDOR.$(LOCAL_MODULE_CLASS).$(name_without_suffix) := 1
+    endif
+    name_without_suffix :=
   endif
-  name_without_suffix :=
 endif
 
 # Check prebuilt ELF binaries.
@@ -113,26 +115,52 @@
   endif
 endif
 
+ifeq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+  # Add $(LOCAL_BUILT_MODULE) as a dependency to no_vendor_variant_vndk_check so
+  # that the vendor variant will be built and checked against the core variant.
+  no_vendor_variant_vndk_check: $(LOCAL_BUILT_MODULE)
+
+  my_core_register_name := $(subst .vendor,,$(my_register_name))
+  my_core_variant_files := $(call module-target-built-files,$(my_core_register_name))
+  my_core_shared_lib := $(sort $(filter %.so,$(my_core_variant_files)))
+  $(LOCAL_BUILT_MODULE): PRIVATE_CORE_VARIANT := $(my_core_shared_lib)
+
+  # The built vendor variant library needs to depend on the built core variant
+  # so that we can perform identity check against the core variant.
+  $(LOCAL_BUILT_MODULE): $(my_core_shared_lib)
+endif
+
+ifeq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE) $(LIBRARY_IDENTITY_CHECK_SCRIPT)
+	$(call verify-vndk-libs-identical,\
+		$(PRIVATE_CORE_VARIANT),\
+		$<,\
+		$($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)TOOLS_PREFIX))
+	$(copy-file-to-target)
+else
 $(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE)
 	$(transform-prebuilt-to-target)
+endif
 ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
 	$(hide) chmod +x $@
 endif
 
 ifndef LOCAL_IS_HOST_MODULE
   ifdef LOCAL_SOONG_UNSTRIPPED_BINARY
-    # Store a copy with symbols for symbolic debugging
-    my_unstripped_path := $(TARGET_OUT_UNSTRIPPED)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
-    # drop /root as /root is mounted as /
-    my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
-    symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
-    $(eval $(call copy-one-file,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
-    $(call add-dependency,$(LOCAL_BUILT_MODULE),$(symbolic_output))
+    ifneq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+      my_symbol_path := $(if $(LOCAL_SOONG_SYMBOL_PATH),$(LOCAL_SOONG_SYMBOL_PATH),$(my_module_path))
+      # Store a copy with symbols for symbolic debugging
+      my_unstripped_path := $(TARGET_OUT_UNSTRIPPED)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
+      # drop /root as /root is mounted as /
+      my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
+      symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
+      $(eval $(call copy-one-file,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
+      $(call add-dependency,$(LOCAL_BUILT_MODULE),$(symbolic_output))
 
-    ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
-      my_breakpad_path := $(TARGET_OUT_BREAKPAD)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
-      breakpad_output := $(my_breakpad_path)/$(my_installed_module_stem).sym
-      $(breakpad_output) : $(LOCAL_SOONG_UNSTRIPPED_BINARY) | $(BREAKPAD_DUMP_SYMS) $(PRIVATE_READELF)
+      ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
+        my_breakpad_path := $(TARGET_OUT_BREAKPAD)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
+        breakpad_output := $(my_breakpad_path)/$(my_installed_module_stem).sym
+        $(breakpad_output) : $(LOCAL_SOONG_UNSTRIPPED_BINARY) | $(BREAKPAD_DUMP_SYMS) $(PRIVATE_READELF)
 	@echo "target breakpad: $(PRIVATE_MODULE) ($@)"
 	@mkdir -p $(dir $@)
 	$(hide) if $(PRIVATE_READELF) -S $< > /dev/null 2>&1 ; then \
@@ -141,7 +169,8 @@
 	  echo "skipped for non-elf file."; \
 	  touch $@; \
 	fi
-      $(call add-dependency,$(LOCAL_BUILT_MODULE),$(breakpad_output))
+        $(call add-dependency,$(LOCAL_BUILT_MODULE),$(breakpad_output))
+      endif
     endif
   endif
 endif
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 3c82e88..baba31b 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -61,7 +61,8 @@
 $(call add_json_str,  CrossHostArch,                     $(HOST_CROSS_ARCH))
 $(call add_json_str,  CrossHostSecondaryArch,            $(HOST_CROSS_2ND_ARCH))
 
-$(call add_json_list, ResourceOverlays,                  $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS))
+$(call add_json_list, DeviceResourceOverlays,            $(DEVICE_PACKAGE_OVERLAYS))
+$(call add_json_list, ProductResourceOverlays,           $(PRODUCT_PACKAGE_OVERLAYS))
 $(call add_json_list, EnforceRROTargets,                 $(PRODUCT_ENFORCE_RRO_TARGETS))
 $(call add_json_list, EnforceRROExcludedOverlays,        $(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS))
 
@@ -115,6 +116,8 @@
 
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
 
+$(call add_json_bool, VndkUseCoreVariant,                $(TARGET_VNDK_USE_CORE_VARIANT))
+
 $(call add_json_bool, Product_is_iot,                    $(filter true,$(PRODUCT_IOT)))
 
 $(call add_json_bool, Treble_linker_namespaces,          $(filter true,$(PRODUCT_TREBLE_LINKER_NAMESPACES)))
diff --git a/target/product/gsi/adb_debug.prop b/target/product/gsi/adb_debug.prop
new file mode 100644
index 0000000..37e2f2d
--- /dev/null
+++ b/target/product/gsi/adb_debug.prop
@@ -0,0 +1,12 @@
+# Note: This file will be loaded with highest priority to override
+# other system properties, if a special ramdisk with "/force_debuggable"
+# is used and the device is unlocked.
+
+# Disable adb authentication to allow test automation on user build GSI
+ro.adb.secure=0
+
+# Allow 'adb root' on user build GSI
+ro.debuggable=1
+
+# Introduce this property to indicate that init has loaded adb_debug.prop
+ro.force.debuggable=1
diff --git a/target/product/gsi_common.mk b/target/product/gsi_common.mk
index fb0478d..72d8b41 100644
--- a/target/product/gsi_common.mk
+++ b/target/product/gsi_common.mk
@@ -51,13 +51,13 @@
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/etc/init/config/skip_mount.cfg \
     system/etc/init/init.gsi.rc \
+    system/etc/adb_debug.prop \
 
 # Exclude all files under system/product and system/product_services
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/product/% \
     system/product_services/%
 
-
 # Split selinux policy
 PRODUCT_FULL_TREBLE_OVERRIDE := true
 
@@ -97,3 +97,7 @@
 #   Provide a libnfc-nci.conf to GSI product
 PRODUCT_COPY_FILES += \
     device/generic/common/nfc/libnfc-nci.conf:$(TARGET_COPY_OUT_PRODUCT)/etc/libnfc-nci.conf
+
+# Allow 'adb root' on user build GSI
+PRODUCT_COPY_FILES += \
+    build/make/target/product/gsi/adb_debug.prop:$(TARGET_COPY_OUT_SYSTEM)/etc/adb_debug.prop
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index 0ddc3db..ecd5691 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -81,7 +81,6 @@
     libminui \
     libnl \
     libprotobuf-cpp-full \
-    libprotobuf-cpp-full-rtti \
 
 PRODUCT_PACKAGES_DEBUG += \
     avbctl \
diff --git a/tools/buildinfo_common.sh b/tools/buildinfo_common.sh
index f7f798c..6041d79 100755
--- a/tools/buildinfo_common.sh
+++ b/tools/buildinfo_common.sh
@@ -21,7 +21,7 @@
 echo "ro.${partition}.build.version.sdk=$PLATFORM_SDK_VERSION"
 
 echo "ro.product.${partition}.brand=$PRODUCT_BRAND"
-echo "ro.product.${partition}.device=$TARGET_DEVICE"
+echo "ro.product.${partition}.device=$PRODUCT_DEVICE"
 echo "ro.product.${partition}.manufacturer=$PRODUCT_MANUFACTURER"
 echo "ro.product.${partition}.model=$PRODUCT_MODEL"
 echo "ro.product.${partition}.name=$PRODUCT_NAME"
diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py
index 38c1cf4..de855c6 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -260,13 +260,20 @@
   _SYMBOL_ENTRY_END_PATTERN = '  }'
 
 
-  @classmethod
-  def _parse_symbol_name(cls, name_with_version):
+  @staticmethod
+  def _parse_symbol_name(name_with_version):
     """Split `name_with_version` into name and version. This function may split
     at last occurrence of `@@` or `@`."""
-    name, version = name_with_version.rsplit('@', 1)
-    if name and name[-1] == '@':
-      name = name[:-1]
+    pos = name_with_version.rfind('@')
+    if pos == -1:
+      name = name_with_version
+      version = ''
+    else:
+      if pos > 0 and name_with_version[pos - 1] == '@':
+        name = name_with_version[0:pos - 1]
+      else:
+        name = name_with_version[0:pos]
+      version = name_with_version[pos + 1:]
     return (name, version)
 
 
diff --git a/tools/check_identical_lib.sh b/tools/check_identical_lib.sh
new file mode 100755
index 0000000..01007c0
--- /dev/null
+++ b/tools/check_identical_lib.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -e
+
+STRIP_PATH="${1}"
+CORE="${2}"
+VENDOR="${3}"
+
+stripped_core="${CORE}.vndk_lib_check.stripped"
+stripped_vendor="${VENDOR}.vndk_lib_check.stripped"
+
+function cleanup() {
+  rm -f ${stripped_core} ${stripped_vendor}
+}
+trap cleanup EXIT
+
+function strip_lib() {
+  ${STRIP_PATH} \
+    -i ${1} \
+    -o ${2} \
+    -d /dev/null \
+    --remove-build-id
+}
+
+strip_lib ${CORE} ${stripped_core}
+strip_lib ${VENDOR} ${stripped_vendor}
+if ! cmp -s ${stripped_core} ${stripped_vendor}; then
+  echo "VNDK library not in vndkMustUseVendorVariantList but has different core and vendor variant: $(basename ${CORE})"
+  echo "If the two variants need to have different runtime behavior, consider using libvndksupport."
+  exit 1
+fi
diff --git a/tools/generate-enforce-rro-android-manifest.py b/tools/generate-enforce-rro-android-manifest.py
index 68331cf..0d7623f 100755
--- a/tools/generate-enforce-rro-android-manifest.py
+++ b/tools/generate-enforce-rro-android-manifest.py
@@ -48,8 +48,9 @@
 def main(argv):
   args = get_args()
 
-  package_name = args.package_info
-  if not args.use_package_name:
+  if args.use_package_name:
+    package_name = args.package_info
+  else:
     with open(args.package_info) as f:
       data = f.read()
       f.close()
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 5132ae7..10aecf9 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -146,11 +146,12 @@
     ofile.write(data)
     ofile.close()
 
-    arc_name = "SYSTEM/" + fn
-    if arc_name in output_zip.namelist():
-      OPTIONS.replace_updated_files_list.append(arc_name)
-    else:
-      common.ZipWrite(output_zip, ofile.name, arc_name)
+    if output_zip:
+      arc_name = "SYSTEM/" + fn
+      if arc_name in output_zip.namelist():
+        OPTIONS.replace_updated_files_list.append(arc_name)
+      else:
+        common.ZipWrite(output_zip, ofile.name, arc_name)
 
   if OPTIONS.rebuild_recovery:
     logger.info("Building new recovery patch")
@@ -260,7 +261,7 @@
 
   # AVB-sign the image as needed.
   if OPTIONS.info_dict.get("avb_enable") == "true":
-    avbtool = os.getenv('AVBTOOL') or OPTIONS.info_dict["avb_avbtool"]
+    avbtool = OPTIONS.info_dict["avb_avbtool"]
     part_size = OPTIONS.info_dict["dtbo_size"]
     # The AVB hash footer will be replaced if already present.
     cmd = [avbtool, "add_hash_footer", "--image", img.name,
@@ -428,7 +429,7 @@
     logger.info("%s.img already exists; not rebuilding...", name)
     return img.name
 
-  avbtool = os.getenv('AVBTOOL') or OPTIONS.info_dict["avb_avbtool"]
+  avbtool = OPTIONS.info_dict["avb_avbtool"]
   cmd = [avbtool, "make_vbmeta_image", "--output", img.name]
   common.AppendAVBSigningArgs(cmd, name)
 
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 5e3d68a..d2f4e25 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -739,26 +739,6 @@
   with open(filename, "w") as f:
     f.writelines(["%s=%s" % (key, value) for (key, value) in glob_dict.items()])
 
-def ExtractSystemOtherAvbKey(in_dir, glob_dict):
-  if glob_dict.get("avb_system_extract_system_other_key") != "true":
-    return
-
-  extract_to = os.path.join(in_dir, "etc/security/avb/system_other.avbpubkey")
-  extract_to_dir = os.path.dirname(extract_to)
-
-  if os.path.isdir(extract_to_dir):
-    shutil.rmtree(extract_to_dir)
-  elif os.path.isfile(extract_to_dir):
-    os.remove(extract_to_dir)
-  os.mkdir(extract_to_dir);
-
-  # Extracts the public key used to sign system_other.img, into system.img:
-  #   /system/etc/security/avb/system_other.avbpubkey.
-  avbtool = os.getenv('AVBTOOL') or glob_dict.get("avb_avbtool")
-  extract_from = glob_dict.get("avb_system_other_key_path")
-  cmd = [avbtool, "extract_public_key", "--key", extract_from,
-         "--output", extract_to]
-  common.RunAndCheckOutput(cmd, verbose=False)
 
 def main(argv):
   if len(argv) < 4 or len(argv) > 5:
@@ -783,7 +763,6 @@
     mount_point = ""
     if image_filename == "system.img":
       mount_point = "system"
-      ExtractSystemOtherAvbKey(in_dir, glob_dict)
     elif image_filename == "system_other.img":
       mount_point = "system_other"
     elif image_filename == "userdata.img":
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index e71667b..34c1359 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -17,6 +17,7 @@
 import collections
 import copy
 import errno
+import fnmatch
 import getopt
 import getpass
 import gzip
@@ -704,7 +705,7 @@
 
   # AVB: if enabled, calculate and add hash to boot.img or recovery.img.
   if info_dict.get("avb_enable") == "true":
-    avbtool = os.getenv('AVBTOOL') or info_dict["avb_avbtool"]
+    avbtool = info_dict["avb_avbtool"]
     part_size = info_dict[partition_name + "_size"]
     cmd = [avbtool, "add_hash_footer", "--image", img.name,
            "--partition_size", str(part_size), "--partition_name",
@@ -771,21 +772,29 @@
     shutil.copyfileobj(in_file, out_file)
 
 
-def UnzipToDir(filename, dirname, pattern=None):
+def UnzipToDir(filename, dirname, patterns=None):
   """Unzips the archive to the given directory.
 
   Args:
     filename: The name of the zip file to unzip.
-
     dirname: Where the unziped files will land.
-
-    pattern: Files to unzip from the archive. If omitted, will unzip the entire
-    archvie.
+    patterns: Files to unzip from the archive. If omitted, will unzip the entire
+        archvie. Non-matching patterns will be filtered out. If there's no match
+        after the filtering, no file will be unzipped.
   """
-
   cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
-  if pattern is not None:
-    cmd.extend(pattern)
+  if patterns is not None:
+    # Filter out non-matching patterns. unzip will complain otherwise.
+    with zipfile.ZipFile(filename) as input_zip:
+      names = input_zip.namelist()
+    filtered = [
+        pattern for pattern in patterns if fnmatch.filter(names, pattern)]
+
+    # There isn't any matching files. Don't unzip anything.
+    if not filtered:
+      return
+    cmd.extend(filtered)
+
   RunAndCheckOutput(cmd)
 
 
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 5014516..1d62e3b 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -43,6 +43,10 @@
 
   --output-target-files output-target-files-package
       The output merged target files package. Also a zip archive.
+
+  --rebuild_recovery
+      Rebuild the recovery patch used by non-A/B devices and write it to the
+      system image.
 """
 
 from __future__ import print_function
@@ -65,6 +69,7 @@
 OPTIONS.other_target_files = None
 OPTIONS.other_item_list = None
 OPTIONS.output_target_files = None
+OPTIONS.rebuild_recovery = False
 OPTIONS.keep_tmp = False
 
 # default_system_item_list is a list of items to extract from the partial
@@ -199,6 +204,38 @@
     return config_file.read().splitlines()
 
 
+def validate_config_lists(system_item_list, other_item_list):
+  """Performs validations on the merge config lists.
+
+  Args:
+    system_item_list: The list of items to extract from the partial
+    system target files package as is.
+
+    other_item_list: The list of items to extract from the partial
+    other target files package as is.
+
+  Returns:
+    False if a validation fails, otherwise true.
+  """
+  default_combined_item_set = set(default_system_item_list)
+  default_combined_item_set.update(default_other_item_list)
+
+  combined_item_set = set(system_item_list)
+  combined_item_set.update(other_item_list)
+
+  # Check that the merge config lists are not missing any item specified
+  # by the default config lists.
+  difference = default_combined_item_set.difference(combined_item_set)
+  if difference:
+    logger.error('Missing merge config items: %s' % list(difference))
+    logger.error('Please ensure missing items are in either the '
+                 'system-item-list or other-item-list files provided to '
+                 'this script.')
+    return False
+
+  return True
+
+
 def process_ab_partitions_txt(
     system_target_files_temp_dir,
     other_target_files_temp_dir,
@@ -433,7 +470,8 @@
     system_misc_info_keys,
     other_target_files,
     other_item_list,
-    output_target_files):
+    output_target_files,
+    rebuild_recovery):
   """Merge two target files packages together.
 
   This function takes system and other target files packages as input, performs
@@ -466,6 +504,9 @@
 
     output_target_files: The name of the output zip archive target files
     package created by merging system and other.
+
+    rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
+    devices and write it to the system image.
   """
 
   logger.info(
@@ -531,10 +572,10 @@
 
   # Regenerate IMAGES in the temporary directory.
 
-  add_img_args = [
-      '--verbose',
-      output_target_files_temp_dir,
-  ]
+  add_img_args = ['--verbose']
+  if rebuild_recovery:
+    add_img_args.append('--rebuild_recovery')
+  add_img_args.append(output_target_files_temp_dir)
 
   add_img_to_target_files.main(add_img_args)
 
@@ -630,6 +671,8 @@
       OPTIONS.other_item_list = a
     elif o == '--output-target-files':
       OPTIONS.output_target_files = a
+    elif o == '--rebuild_recovery':
+      OPTIONS.rebuild_recovery = True
     elif o == '--keep_tmp':
       OPTIONS.keep_tmp = True
     else:
@@ -645,6 +688,7 @@
           'other-target-files=',
           'other-item-list=',
           'output-target-files=',
+          'rebuild_recovery',
           "keep_tmp",
       ],
       extra_option_handler=option_handler)
@@ -671,6 +715,11 @@
   else:
     other_item_list = default_other_item_list
 
+  if not validate_config_lists(
+      system_item_list=system_item_list,
+      other_item_list=other_item_list):
+    sys.exit(1)
+
   call_func_with_temp_dir(
       lambda temp_dir: merge_target_files(
           temp_dir=temp_dir,
@@ -679,7 +728,8 @@
           system_misc_info_keys=system_misc_info_keys,
           other_target_files=OPTIONS.other_target_files,
           other_item_list=other_item_list,
-          output_target_files=OPTIONS.output_target_files),
+          output_target_files=OPTIONS.output_target_files,
+          rebuild_recovery=OPTIONS.rebuild_recovery),
       OPTIONS.keep_tmp)
 
 
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index fe40936..37f4e38 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -236,7 +236,7 @@
 POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
 DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
 AB_PARTITIONS = 'META/ab_partitions.txt'
-UNZIP_PATTERN = ['IMAGES/*', 'META/*']
+UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'RADIO/*']
 RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS]
 
 
@@ -1802,12 +1802,7 @@
     infolist = input_zip.infolist()
     namelist = input_zip.namelist()
 
-  # Additionally unzip 'RADIO/*' if exists.
-  unzip_pattern = UNZIP_PATTERN[:]
-  if any([entry.startswith('RADIO/') for entry in namelist]):
-    unzip_pattern.append('RADIO/*')
-  input_tmp = common.UnzipTemp(input_file, unzip_pattern)
-
+  input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
   for info in infolist:
     unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
     if info.filename == 'IMAGES/system_other.img':
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index f1f032d..75a98fd 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -91,12 +91,12 @@
       Replace the veritykeyid in BOOT/cmdline of input_target_file_zip
       with keyid of the cert pointed by <path_to_X509_PEM_cert_file>.
 
-  --avb_{boot,system,vendor,dtbo,vbmeta}_algorithm <algorithm>
-  --avb_{boot,system,vendor,dtbo,vbmeta}_key <key>
+  --avb_{boot,system,system_other,vendor,dtbo,vbmeta}_algorithm <algorithm>
+  --avb_{boot,system,system_other,vendor,dtbo,vbmeta}_key <key>
       Use the specified algorithm (e.g. SHA256_RSA4096) and the key to AVB-sign
       the specified image. Otherwise it uses the existing values in info dict.
 
-  --avb_{apex,boot,system,vendor,dtbo,vbmeta}_extra_args <args>
+  --avb_{apex,boot,system,system_other,vendor,dtbo,vbmeta}_extra_args <args>
       Specify any additional args that are needed to AVB-sign the image
       (e.g. "--signing_helper /path/to/helper"). The args will be appended to
       the existing ones in info dict.
@@ -166,7 +166,7 @@
 def GetApexKeys(keys_info, key_map):
   """Gets APEX payload and container signing keys by applying the mapping rules.
 
-  We currently don't allow PRESIGNED payload / container keys.
+  Presigned payload / container keys will be set accordingly.
 
   Args:
     keys_info: A dict that maps from APEX filenames to a tuple of (payload_key,
@@ -180,7 +180,8 @@
   # Apply all the --extra_apex_payload_key options to override the payload
   # signing keys in the given keys_info.
   for apex, key in OPTIONS.extra_apex_payload_keys.items():
-    assert key, 'Presigned APEX payload for {} is not allowed'.format(apex)
+    if not key:
+      key = 'PRESIGNED'
     keys_info[apex] = (key, keys_info[apex][1])
 
   # Apply the key remapping to container keys.
@@ -192,7 +193,8 @@
     # Skip non-APEX containers.
     if apex not in keys_info:
       continue
-    assert key, 'Presigned APEX container for {} is not allowed'.format(apex)
+    if not key:
+      key = 'PRESIGNED'
     keys_info[apex] = (keys_info[apex][0], key_map.get(key, key))
 
   return keys_info
@@ -245,7 +247,7 @@
 
 
 def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
-                                 compressed_extension):
+                                 compressed_extension, apex_keys):
   """Checks that all the APKs and APEXes have keys specified.
 
   Args:
@@ -253,6 +255,8 @@
     known_keys: A set of APKs and APEXes that have known signing keys.
     compressed_extension: The extension string of compressed APKs, such as
         '.gz', or None if there's no compressed APKs.
+    apex_keys: A dict that contains the key mapping from APEX name to
+        (payload_key, container_key).
 
   Raises:
     AssertionError: On finding unknown APKs and APEXes.
@@ -284,6 +288,31 @@
        "Use '-e <apkname>=' to specify a key (which may be an empty string to "
        "not sign this apk).".format("\n  ".join(unknown_files)))
 
+  # For all the APEXes, double check that we won't have an APEX that has only
+  # one of the payload / container keys set.
+  if not apex_keys:
+    return
+
+  invalid_apexes = []
+  for info in input_tf_zip.infolist():
+    if (not info.filename.startswith('SYSTEM/apex') or
+        not info.filename.endswith('.apex')):
+      continue
+
+    name = os.path.basename(info.filename)
+    (payload_key, container_key) = apex_keys[name]
+    if ((payload_key in common.SPECIAL_CERT_STRINGS and
+         container_key not in common.SPECIAL_CERT_STRINGS) or
+        (payload_key not in common.SPECIAL_CERT_STRINGS and
+         container_key in common.SPECIAL_CERT_STRINGS)):
+      invalid_apexes.append(
+          "{}: payload_key {}, container_key {}".format(
+              name, payload_key, container_key))
+
+  assert not invalid_apexes, \
+      "Invalid APEX keys specified:\n  {}\n".format(
+          "\n  ".join(invalid_apexes))
+
 
 def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
             is_compressed):
@@ -468,19 +497,29 @@
       name = os.path.basename(filename)
       payload_key, container_key = apex_keys[name]
 
-      print("    signing: %-*s container (%s)" % (maxsize, name, container_key))
-      print("           : %-*s payload   (%s)" % (maxsize, name, payload_key))
+      # We've asserted not having a case with only one of them PRESIGNED.
+      if (payload_key not in common.SPECIAL_CERT_STRINGS and
+          container_key not in common.SPECIAL_CERT_STRINGS):
+        print("    signing: %-*s container (%s)" % (
+            maxsize, name, container_key))
+        print("           : %-*s payload   (%s)" % (
+            maxsize, name, payload_key))
 
-      (signed_apex, payload_key_name) = SignApex(
-          data,
-          payload_key,
-          container_key,
-          key_passwords[container_key],
-          codename_to_api_level_map,
-          OPTIONS.avb_extra_args.get('apex'))
-      common.ZipWrite(output_tf_zip, signed_apex, filename)
+        (signed_apex, payload_key_name) = SignApex(
+            data,
+            payload_key,
+            container_key,
+            key_passwords[container_key],
+            codename_to_api_level_map,
+            OPTIONS.avb_extra_args.get('apex'))
+        common.ZipWrite(output_tf_zip, signed_apex, filename)
+        updated_apex_payload_keys[payload_key_name] = payload_key
 
-      updated_apex_payload_keys[payload_key_name] = payload_key
+      else:
+        print(
+            "NOT signing: %s\n"
+            "        (skipped due to special cert string)" % (name,))
+        common.ZipWriteStr(output_tf_zip, out_info, data)
 
     # AVB public keys for the installed APEXes, which will be updated later.
     elif (os.path.dirname(filename) == 'SYSTEM/etc/security/apex' and
@@ -545,6 +584,18 @@
     elif filename == "META/care_map.pb" or filename == "META/care_map.txt":
       pass
 
+    # Updates system_other.avbpubkey in /product/etc/.
+    elif filename in (
+        "PRODUCT/etc/security/avb/system_other.avbpubkey",
+        "SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
+      # Only update system_other's public key, if the corresponding signing
+      # key is specified via --avb_system_other_key.
+      signing_key = OPTIONS.avb_keys.get("system_other")
+      if signing_key:
+        public_key = common.ExtractAvbPublicKey(signing_key)
+        print("    Rewriting AVB public key of system_other in /product")
+        common.ZipWrite(output_tf_zip, public_key, filename)
+
     # A non-APK file; copy it verbatim.
     else:
       common.ZipWriteStr(output_tf_zip, out_info, data)
@@ -557,8 +608,10 @@
       continue
 
     name = os.path.basename(filename)
-    assert name in updated_apex_payload_keys, \
-        'Unsigned APEX payload key: {}'.format(filename)
+
+    # Skip PRESIGNED APEXes.
+    if name not in updated_apex_payload_keys:
+      continue
 
     key_path = updated_apex_payload_keys[name]
     if not os.path.exists(key_path) and not key_path.endswith('.pem'):
@@ -893,6 +946,7 @@
       'dtbo' : 'avb_dtbo_add_hash_footer_args',
       'recovery' : 'avb_recovery_add_hash_footer_args',
       'system' : 'avb_system_add_hashtree_footer_args',
+      'system_other' : 'avb_system_other_add_hashtree_footer_args',
       'vendor' : 'avb_vendor_add_hashtree_footer_args',
       'vbmeta' : 'avb_vbmeta_args',
   }
@@ -1112,6 +1166,12 @@
       OPTIONS.avb_algorithms['system'] = a
     elif o == "--avb_system_extra_args":
       OPTIONS.avb_extra_args['system'] = a
+    elif o == "--avb_system_other_key":
+      OPTIONS.avb_keys['system_other'] = a
+    elif o == "--avb_system_other_algorithm":
+      OPTIONS.avb_algorithms['system_other'] = a
+    elif o == "--avb_system_other_extra_args":
+      OPTIONS.avb_extra_args['system_other'] = a
     elif o == "--avb_vendor_key":
       OPTIONS.avb_keys['vendor'] = a
     elif o == "--avb_vendor_algorithm":
@@ -1151,6 +1211,9 @@
           "avb_system_algorithm=",
           "avb_system_key=",
           "avb_system_extra_args=",
+          "avb_system_other_algorithm=",
+          "avb_system_other_key=",
+          "avb_system_other_extra_args=",
           "avb_vendor_algorithm=",
           "avb_vendor_key=",
           "avb_vendor_extra_args=",
@@ -1181,7 +1244,8 @@
   CheckApkAndApexKeysAvailable(
       input_zip,
       set(apk_keys.keys()) | set(apex_keys.keys()),
-      compressed_extension)
+      compressed_extension,
+      apex_keys)
 
   key_passwords = common.GetKeyPasswords(
       set(apk_keys.values()) | set(itertools.chain(*apex_keys.values())))
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 8709124..d4fa5f3 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -359,6 +359,90 @@
     finally:
       os.remove(zip_file.name)
 
+  @staticmethod
+  def _test_UnzipTemp_createZipFile():
+    zip_file = common.MakeTempFile(suffix='.zip')
+    output_zip = zipfile.ZipFile(
+        zip_file, 'w', compression=zipfile.ZIP_DEFLATED)
+    contents = os.urandom(1024)
+    with tempfile.NamedTemporaryFile() as entry_file:
+      entry_file.write(contents)
+      common.ZipWrite(output_zip, entry_file.name, arcname='Test1')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Test2')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Foo3')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Bar4')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Dir5/Baz5')
+      common.ZipClose(output_zip)
+    common.ZipClose(output_zip)
+    return zip_file
+
+  def test_UnzipTemp(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file)
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test1'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test1', 'Foo3'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test*', 'Foo3*'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['*Test1', '*Baz*'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withEmptyPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file, [])
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withPartiallyMatchingPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test*', 'Nonexistent*'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withNoMatchingPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file, ['Foo4', 'Nonexistent*'])
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
 
 class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
   """Tests the APK utils related functions."""
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 9d21429..6082baf 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -33,6 +33,7 @@
   <signer signature="{}"><seinfo value="media"/></signer>
 </policy>"""
 
+  # pylint: disable=line-too-long
   APEX_KEYS_TXT = """name="apex.apexd_test.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
 name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
 """
@@ -223,17 +224,50 @@
         'App3.apk' : 'key3',
     }
     with zipfile.ZipFile(input_file) as input_zip:
-      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None)
-      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.gz')
+      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, {})
+      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.gz', {})
 
       # 'App2.apk.gz' won't be considered as an APK.
-      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None)
-      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.xz')
+      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, {})
+      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.xz', {})
 
       del apk_key_map['App2.apk']
       self.assertRaises(
           AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
-          '.gz')
+          '.gz', {})
+
+  def test_CheckApkAndApexKeysAvailable_invalidApexKeys(self):
+    input_file = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(input_file, 'w') as input_zip:
+      input_zip.writestr('SYSTEM/apex/Apex1.apex', "Apex1-content")
+      input_zip.writestr('SYSTEM/apex/Apex2.apex', "Apex2-content")
+
+    apk_key_map = {
+        'Apex1.apex' : 'key1',
+        'Apex2.apex' : 'key2',
+        'Apex3.apex' : 'key3',
+    }
+    apex_keys = {
+        'Apex1.apex' : ('payload-key1', 'container-key1'),
+        'Apex2.apex' : ('payload-key2', 'container-key2'),
+    }
+    with zipfile.ZipFile(input_file) as input_zip:
+      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
+
+      # Fine to have both keys as PRESIGNED.
+      apex_keys['Apex2.apex'] = ('PRESIGNED', 'PRESIGNED')
+      CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
+
+      # Having only one of them as PRESIGNED is not allowed.
+      apex_keys['Apex2.apex'] = ('payload-key2', 'PRESIGNED')
+      self.assertRaises(
+          AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
+          None, apex_keys)
+
+      apex_keys['Apex2.apex'] = ('PRESIGNED', 'container-key1')
+      self.assertRaises(
+          AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
+          None, apex_keys)
 
   def test_GetApkFileInfo(self):
     (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
@@ -358,16 +392,14 @@
     with zipfile.ZipFile(target_files) as target_files_zip:
       keys_info = ReadApexKeysInfo(target_files_zip)
 
-    self.assertEqual(
-        {
-          'apex.apexd_test.apex': (
-              'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
-              'build/target/product/security/testkey'),
-          'apex.apexd_test_different_app.apex': (
-              'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
-              'build/target/product/security/testkey'),
-        },
-        keys_info)
+    self.assertEqual({
+        'apex.apexd_test.apex': (
+            'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
+            'build/target/product/security/testkey'),
+        'apex.apexd_test_different_app.apex': (
+            'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+            'build/target/product/security/testkey'),
+        }, keys_info)
 
   def test_ReadApexKeysInfo_mismatchingKeys(self):
     # Mismatching payload public / private keys.
@@ -398,13 +430,11 @@
     with zipfile.ZipFile(target_files) as target_files_zip:
       keys_info = ReadApexKeysInfo(target_files_zip)
 
-    self.assertEqual(
-        {
-          'apex.apexd_test.apex': (
-              'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
-              'build/target/product/security/testkey'),
-          'apex.apexd_test_different_app.apex': (
-              'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
-              'build/target/product/security/testkey'),
-        },
-        keys_info)
+    self.assertEqual({
+        'apex.apexd_test.apex': (
+            'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
+            'build/target/product/security/testkey'),
+        'apex.apexd_test_different_app.apex': (
+            'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+            'build/target/product/security/testkey'),
+        }, keys_info)