Merge "Remove Arvo/Lato/ArbutusSlab/Rubik fonts from all product targets."
diff --git a/Changes.md b/Changes.md
index 1ed6bf8..1fadcef 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,65 @@
 # Build System Changes for Android.mk Writers
 
+## `PRODUCT_HOST_PACKAGES` split from `PRODUCT_PACKAGES` {#PRODUCT_HOST_PACKAGES}
+
+Previously, adding a module to `PRODUCT_PACKAGES` that supported both the host
+and the target (`host_supported` in Android.bp; two modules with the same name
+in Android.mk) would cause both to be built and installed. In many cases you
+only want either the host or target versions to be built/installed by default,
+and would be over-building with both. So `PRODUCT_PACKAGES` will be changing to
+just affect target modules, while `PRODUCT_HOST_PACKAGES` is being added for
+host modules.
+
+Functional differences between `PRODUCT_PACKAGES` and `PRODUCT_HOST_PACKAGES`:
+
+* `PRODUCT_HOST_PACKAGES` does not have `_ENG`/`_DEBUG` variants, as that's a
+  property of the target, not the host.
+* `PRODUCT_HOST_PACKAGES` does not support `LOCAL_MODULE_OVERRIDES`.
+* `PRODUCT_HOST_PACKAGES` requires listed modules to exist, and be host
+  modules. (Unless `ALLOW_MISSING_DEPENDENCIES` is set)
+
+This is still an active migration, so currently it still uses
+`PRODUCT_PACKAGES` to make installation decisions, but verifies that if we used
+`PRODUCT_HOST_PACKAGES`, it would trigger installation for all of the same host
+packages. This check ignores shared libraries, as those are not normally
+necessary in `PRODUCT_*PACKAGES`, and tended to be over-built (especially the
+32-bit variants).
+
+Future changes will switch installation decisions to `PRODUCT_HOST_PACKAGES`
+for host modules, error when there's a host-only module in `PRODUCT_PACKAGES`,
+and do some further cleanup where `LOCAL_REQUIRED_MODULES` are still merged
+between host and target modules with the same name.
+
+## `*.c.arm` / `*.cpp.arm` deprecation  {#file_arm}
+
+In Android.mk files, you used to be able to change LOCAL_ARM_MODE for each
+source file by appending `.arm` to the end of the filename in
+`LOCAL_SRC_FILES`.
+
+Soong does not support this uncommonly used behavior, instead expecting those
+files to be split out into a separate static library that chooses `arm` over
+`thumb` for the entire library. This must now also be done in Android.mk files.
+
+## Windows cross-compiles no longer supported in Android.mk
+
+Modules that build for Windows (our only `HOST_CROSS` OS currently) must now be
+defined in `Android.bp` files.
+
+## `LOCAL_MODULE_TAGS := eng debug` deprecation  {#LOCAL_MODULE_TAGS}
+
+`LOCAL_MODULE_TAGS` value `eng` and `debug` are being deprecated. They allowed
+modules to specify that they should always be installed on `-eng`, or `-eng`
+and `-userdebug` builds. This conflicted with the ability for products to
+specify which modules should be installed, effectively making it impossible to
+build a stripped down product configuration that did not include those modules.
+
+For the equivalent functionality, specify the modules in `PRODUCT_PACKAGES_ENG`
+or `PRODUCT_PACKAGES_DEBUG` in the appropriate product makefiles.
+
+Core android packages like `su` got added to the list in
+`build/make/target/product/base_system.mk`, but for device-specific modules
+there are often better base product makefiles to use instead.
+
 ## `USER` deprecation  {#USER}
 
 `USER` will soon be `nobody` in many cases due to the addition of a sandbox
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f09b892..f5f2a14 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -540,7 +540,85 @@
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib*/libopenjdk.so)
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib*/libexpat.so)
 
+# Merge product_services into product
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product_services)
 
+# Clean up old location of hiddenapi files
+$(call add-clean-step, rm -f $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi*)
+
+# Clean up previous default location of RROs
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/overlay)
+
+# Remove ART artifacts installed only by modules `art-runtime` and
+# `art-tools` in /system on target.
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dalvikvm)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dalvikvm32)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dalvikvm64)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dex2oat)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dex2oatd)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dexdiag)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dexdump)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dexlist)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dexoptanalyzer)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/dexoptanalyzerd)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/oatdump)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/profman)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/profmand)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libadbconnection.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libadbconnectiond.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libart-compiler.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libartd-compiler.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libart-dexlayout.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libartd-dexlayout.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libart-disassembler.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libart.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libartd.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libartbase.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libartbased.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libdexfile.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libdexfiled.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libdexfile_external.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libdexfile_support.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libdt_fd_forward.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libdt_socket.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjdwp.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libnpt.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libopenjdkd.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libopenjdkjvm.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libopenjdkjvmd.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libopenjdkjvmti.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libopenjdkjvmtid.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libprofile.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libprofiled.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libtombstoned_client.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libvixl.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libvixld.so)
+
+# Clean up old location of dexpreopted boot jars
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/dex_bootjars)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/dex_bootjars_input)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libnpt.so)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*)
+
+# Clean up old testcase files
+$(call add-clean-step, rm -rf $(TARGET_OUT_TESTCASES)/*)
+$(call add-clean-step, rm -rf $(HOST_OUT_TESTCASES)/*)
+$(call add-clean-step, rm -rf $(HOST_CROSS_OUT_TESTCASES)/*)
+$(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/)
+
+# Clean up bufferhub files
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hw/android.frameworks.bufferhub@1.0-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/android.frameworks.bufferhub@1.0-service.rc)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/super.img)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/OWNERS b/OWNERS
index 7bc9fe0..77496f1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,9 @@
+# Core build team (MTV)
 ccross@android.com
 dwillemsen@google.com
 
-per-file * = ccross@android.com,dwillemsen@google.com
+# To expedite LON reviews
+hansson@google.com
 
-# for version updates
+# For version updates
 per-file version_defaults.mk = aseaton@google.com,elisapascual@google.com
diff --git a/core/Makefile b/core/Makefile
index 793c16f..db2ddc4 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -75,11 +75,17 @@
 has_dup_copy_headers :=
 $(foreach dest,$(ALL_COPIED_HEADERS), \
     $(eval _srcs := $(ALL_COPIED_HEADERS.$(dest).SRC)) \
-    $(eval _src := $(word $(words $(_srcs)),$(_srcs))) \
+    $(eval _src := $(lastword $(_srcs))) \
     $(if $(call streq,$(_src),$(_srcs)),, \
         $(warning Duplicate header copy: $(dest)) \
-	$(warning Defined in: $(ALL_COPIED_HEADERS.$(dest).MAKEFILE)) \
-	$(eval has_dup_copy_headers := true)) \
+        $(warning _ Using $(_src)) \
+        $(warning __ from $(lastword $(ALL_COPIED_HEADERS.$(dest).MAKEFILE))) \
+        $(eval _makefiles := $$(wordlist 1,$(call int_subtract,$(words $(ALL_COPIED_HEADERS.$(dest).MAKEFILE)),1),$$(ALL_COPIED_HEADERS.$$(dest).MAKEFILE))) \
+        $(foreach src,$(wordlist 1,$(call int_subtract,$(words $(_srcs)),1),$(_srcs)), \
+            $(warning _ Ignoring $(src)) \
+            $(warning __ from $(firstword $(_makefiles))) \
+            $(eval _makefiles := $$(wordlist 2,9999,$$(_makefiles)))) \
+        $(eval has_dup_copy_headers := true)) \
     $(eval $(call copy-one-header,$(_src),$(dest))))
 all_copied_headers: $(ALL_COPIED_HEADERS)
 
@@ -175,10 +181,24 @@
 FINAL_VENDOR_DEFAULT_PROPERTIES += \
     $(call collapse-pairs, $(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
 
+# Add cpu properties for bionic and ART.
 FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH)
-FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT)
+FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME)
 FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_arch=$(TARGET_2ND_ARCH)
-FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT)
+FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT_RUNTIME)
+
+FINAL_VENDOR_DEFAULT_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so
+FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT_RUNTIME)
+ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
+  FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
+endif
+
+ifdef TARGET_2ND_ARCH
+  FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME)
+  ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
+    FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
+  endif
+endif
 
 # Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger
 # mode (via libminui).
@@ -202,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)" \
@@ -213,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
 
@@ -353,7 +380,7 @@
     ro.product.name \
     ro.product.device
 OEM_THUMBPRINT_PROPERTIES := $(filter $(KNOWN_OEM_THUMBPRINT_PROPERTIES),\
-    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES))
+    $(PRODUCT_OEM_PROPERTIES))
 
 # Display parameters shown under Settings -> About Phone
 ifeq ($(TARGET_BUILD_VARIANT),user)
@@ -399,23 +426,24 @@
 	@echo Target buildinfo: $@
 	@mkdir -p $(dir $@)
 	$(hide) echo > $@
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),)
+ifneq ($(PRODUCT_OEM_PROPERTIES),)
 	$(hide) echo "#" >> $@; \
 	        echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
 	        echo "#" >> $@;
-	$(hide) $(foreach prop,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES), \
+	$(hide) $(foreach prop,$(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)" \
-	        PRODUCT_NAME="$(TARGET_PRODUCT)" \
-	        PRODUCT_BRAND="$(PRODUCT_BRAND)" \
 	        PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
 	        PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
-	        PRODUCT_MODEL="$(PRODUCT_MODEL)" \
-	        PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
 	        PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
 	        BUILD_ID="$(BUILD_ID)" \
 	        BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
@@ -435,7 +463,6 @@
 	        PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \
 	        PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION="$(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION)" \
 	        BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
-	        BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
 	        $(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT_FROM_FILE)") \
 	        TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \
 	        TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \
@@ -461,7 +488,7 @@
 	$(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \
 	    echo "$(line)" >> $@;)
 	$(hide) cat $(INSTALLED_ANDROID_INFO_TXT_TARGET) | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' >> $@
-	$(hide) build/make/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
+	$(hide) build/make/tools/post_process_props.py $@ $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
 
 build_desc :=
 
@@ -512,7 +539,7 @@
 	$(hide) $(foreach line,$(FINAL_VENDOR_BUILD_PROPERTIES), \
 	    echo "$(line)" >> $@;)
 endif  # property_overrides_split_enabled
-	$(hide) build/make/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_PROPERTY_BLACKLIST)
+	$(hide) build/make/tools/post_process_props.py $@ $(PRODUCT_VENDOR_PROPERTY_BLACKLIST)
 
 # -----------------------------------------------------------------
 # product build.prop
@@ -693,8 +720,10 @@
 
 ifneq (,$(TARGET_BUILD_APPS))
   $(call dist-for-goals, apps_only, $(APKCERTS_FILE):apkcerts.txt)
+  $(call dist-for-goals, apps_only, $(SOONG_APEX_KEYS_FILE):apexkeys.txt)
 endif
 
+
 # -----------------------------------------------------------------
 # build system stats
 BUILD_SYSTEM_STATS := $(PRODUCT_OUT)/build_system_stats.txt
@@ -705,6 +734,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))
@@ -785,7 +823,7 @@
 # directory).
 event_log_tags_src := \
     $(sort $(foreach m,\
-      $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES) \
+      $(PRODUCT_PACKAGES) \
       $(call module-names-for-tag-list,user), \
       $(ALL_MODULES.$(m).EVENT_LOG_TAGS)) \
       $(filter-out vendor/% device/% out/%,$(all_event_log_tags_src)))
@@ -844,8 +882,7 @@
 
 ifdef BOARD_PREBUILT_DTBIMAGE_DIR
 INSTALLED_DTBIMAGE_TARGET := $(PRODUCT_OUT)/dtb.img
-$(INSTALLED_DTBIMAGE_TARGET) : $(addprefix $(BOARD_PREBUILT_DTBIMAGE_DIR)/,\
-	$(call find-files-in-subdirs,$(BOARD_PREBUILT_DTBIMAGE_DIR),*.dtb,.))
+$(INSTALLED_DTBIMAGE_TARGET) : $(sort $(wildcard $(BOARD_PREBUILT_DTBIMAGE_DIR)/*.dtb))
 	cat $^ > $@
 endif
 
@@ -861,6 +898,7 @@
 $(INSTALLED_FILES_FILE_RAMDISK): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_RAMDISK)
 $(INSTALLED_FILES_FILE_RAMDISK) : $(INTERNAL_RAMDISK_FILES) $(FILESLIST)
 	@echo Installed file list: $@
+	@mkdir -p $(TARGET_RAMDISK_OUT)
 	@mkdir -p $(dir $@)
 	@rm -f $@
 	$(hide) $(FILESLIST) $(TARGET_RAMDISK_OUT) > $(@:.txt=.json)
@@ -911,14 +949,14 @@
   INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
 endif
 
-ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
+ifeq ($(PRODUCT_SUPPORTS_VERITY),true)
 ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
-VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
+VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
                 | grep keyid | sed 's/://g' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/keyid//g'`
 endif
 endif
 
-INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
+INTERNAL_KERNEL_CMDLINE := $(strip $(INTERNAL_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
 ifdef INTERNAL_KERNEL_CMDLINE
 INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
 endif
@@ -955,34 +993,34 @@
 	  --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
 	  $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
 
-else ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)) # BOARD_AVB_ENABLE != true
+else ifeq (true,$(PRODUCT_SUPPORTS_BOOT_SIGNER)) # BOARD_AVB_ENABLE != true
 
 $(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER)
 	$(call pretty,"Target boot image: $@")
 	$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
-	$(BOOT_SIGNER) /boot $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $@
+	$(BOOT_SIGNER) /boot $@ $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $@
 	$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
 
 .PHONY: bootimage-nodeps
 bootimage-nodeps: $(MKBOOTIMG) $(BOOT_SIGNER)
 	@echo "make $@: ignoring dependencies"
 	$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET)
-	$(BOOT_SIGNER) /boot $(INSTALLED_BOOTIMAGE_TARGET) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(INSTALLED_BOOTIMAGE_TARGET)
+	$(BOOT_SIGNER) /boot $(INSTALLED_BOOTIMAGE_TARGET) $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(INSTALLED_BOOTIMAGE_TARGET)
 	$(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
 
-else ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)) # PRODUCT_SUPPORTS_BOOT_SIGNER != true
+else ifeq (true,$(PRODUCT_SUPPORTS_VBOOT)) # PRODUCT_SUPPORTS_BOOT_SIGNER != true
 
 $(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(VBOOT_SIGNER) $(FUTILITY)
 	$(call pretty,"Target boot image: $@")
 	$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@.unsigned
-	$(VBOOT_SIGNER) $(FUTILITY) $@.unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $@.keyblock $@
+	$(VBOOT_SIGNER) $(FUTILITY) $@.unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $@.keyblock $@
 	$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
 
 .PHONY: bootimage-nodeps
 bootimage-nodeps: $(MKBOOTIMG) $(VBOOT_SIGNER) $(FUTILITY)
 	@echo "make $@: ignoring dependencies"
 	$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET).unsigned
-	$(VBOOT_SIGNER) $(FUTILITY) $(INSTALLED_BOOTIMAGE_TARGET).unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(INSTALLED_BOOTIMAGE_TARGET).keyblock $(INSTALLED_BOOTIMAGE_TARGET)
+	$(VBOOT_SIGNER) $(FUTILITY) $(INSTALLED_BOOTIMAGE_TARGET).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(INSTALLED_BOOTIMAGE_TARGET).keyblock $(INSTALLED_BOOTIMAGE_TARGET)
 	$(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
 
 else # PRODUCT_SUPPORTS_VBOOT != true
@@ -1009,7 +1047,6 @@
 endif
 $(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
 else # BOARD_PREBUILT_BOOTIMAGE not defined
-INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
 INSTALLED_BOOTIMAGE_TARGET :=
 endif # BOARD_PREBUILT_BOOTIMAGE
 endif # TARGET_NO_KERNEL
@@ -1294,9 +1331,9 @@
 
 INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
 
-ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY))
+ifeq (true,$(PRODUCT_SUPPORTS_VERITY))
 INTERNAL_USERIMAGES_DEPS += $(BUILD_VERITY_METADATA) $(BUILD_VERITY_TREE) $(APPEND2SIMG) $(VERITY_SIGNER)
-ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC))
+ifeq (true,$(PRODUCT_SUPPORTS_VERITY_FEC))
 INTERNAL_USERIMAGES_DEPS += $(FEC)
 endif
 endif
@@ -1310,7 +1347,7 @@
 
 ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
 
-ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
+ifeq ($(PRODUCT_SUPPORTS_VERITY),true)
   $(error vboot 1.0 doesn't support logical partition)
 endif
 
@@ -1325,6 +1362,7 @@
 define generate-image-prop-dictionary
 $(if $(filter $(2),system),\
     $(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1))
+    $(if $(INTERNAL_SYSTEM_OTHER_PARTITION_SIZE),$(hide) echo "system_other_size=$(INTERNAL_SYSTEM_OTHER_PARTITION_SIZE)" >> $(1))
     $(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
     $(if $(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "system_extfs_inode_count=$(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
     $(if $(BOARD_SYSTEMIMAGE_EXTFS_RSV_PCT),$(hide) echo "system_extfs_rsv_pct=$(BOARD_SYSTEMIMAGE_EXTFS_RSV_PCT)" >> $(1))
@@ -1333,8 +1371,8 @@
     $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
     $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_squashfs_block_size=$(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
     $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_squashfs_disable_4k_align=$(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH),$(hide) echo "system_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH)" >> $(1))
-    $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_HEADROOM),$(hide) echo "system_headroom=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_HEADROOM)" >> $(1))
+    $(if $(PRODUCT_SYSTEM_BASE_FS_PATH),$(hide) echo "system_base_fs_file=$(PRODUCT_SYSTEM_BASE_FS_PATH)" >> $(1))
+    $(if $(PRODUCT_SYSTEM_HEADROOM),$(hide) echo "system_headroom=$(PRODUCT_SYSTEM_HEADROOM)" >> $(1))
     $(if $(BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "system_reserved_size=$(BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
 )
 $(if $(filter $(2),userdata),\
@@ -1355,7 +1393,7 @@
     $(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "vendor_squashfs_compressor_opt=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
     $(if $(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_squashfs_block_size=$(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
     $(if $(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_squashfs_disable_4k_align=$(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1))
+    $(if $(PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1))
     $(if $(BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "vendor_reserved_size=$(BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
 )
 $(if $(filter $(2),product),\
@@ -1368,7 +1406,7 @@
     $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "product_squashfs_compressor_opt=$(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
     $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "product_squashfs_block_size=$(BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
     $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "product_squashfs_disable_4k_align=$(BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH),$(hide) echo "product_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH)" >> $(1))
+    $(if $(PRODUCT_PRODUCT_BASE_FS_PATH),$(hide) echo "product_base_fs_file=$(PRODUCT_PRODUCT_BASE_FS_PATH)" >> $(1))
     $(if $(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "product_reserved_size=$(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
 )
 $(if $(filter $(2),product_services),\
@@ -1393,7 +1431,7 @@
     $(if $(BOARD_ODMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "odm_squashfs_compressor_opt=$(BOARD_ODMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
     $(if $(BOARD_ODMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "odm_squashfs_block_size=$(BOARD_ODMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
     $(if $(BOARD_ODMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "odm_squashfs_disable_4k_align=$(BOARD_ODMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH),$(hide) echo "odm_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH)" >> $(1))
+    $(if $(PRODUCT_ODM_BASE_FS_PATH),$(hide) echo "odm_base_fs_file=$(PRODUCT_ODM_BASE_FS_PATH)" >> $(1))
     $(if $(BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "odm_reserved_size=$(BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
 )
 $(if $(filter $(2),oem),\
@@ -1411,21 +1449,21 @@
 $(if $(BOARD_FLASH_LOGICAL_BLOCK_SIZE), $(hide) echo "flash_logical_block_size=$(BOARD_FLASH_LOGICAL_BLOCK_SIZE)" >> $(1))
 $(if $(BOARD_FLASH_ERASE_BLOCK_SIZE), $(hide) echo "flash_erase_block_size=$(BOARD_FLASH_ERASE_BLOCK_SIZE)" >> $(1))
 $(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1)
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER),$(hide) echo "boot_signer=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(notdir $(VERITY_SIGNER))" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC),$(hide) echo "verity_fec=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_BOOT_SIGNER),$(hide) echo "boot_signer=$(PRODUCT_SUPPORTS_BOOT_SIGNER)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity=$(PRODUCT_SUPPORTS_VERITY)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCT_VERITY_SIGNING_KEY)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(notdir $(VERITY_SIGNER))" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VERITY_FEC),$(hide) echo "verity_fec=$(PRODUCT_SUPPORTS_VERITY_FEC)" >> $(1))
 $(if $(filter eng, $(TARGET_BUILD_VARIANT)),$(hide) echo "verity_disable=true" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_VERITY_PARTITION),$(hide) echo "product_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_VERITY_PARTITION)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION),$(hide) echo "product_services_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(notdir $(FUTILITY))" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
+$(if $(PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCT_PRODUCT_VERITY_PARTITION),$(hide) echo "product_verity_block_device=$(PRODUCT_PRODUCT_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION),$(hide) echo "product_services_verity_block_device=$(PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCT_SUPPORTS_VBOOT)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCT_VBOOT_SIGNING_KEY)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(notdir $(FUTILITY))" >> $(1))
+$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_avbtool=$(notdir $(AVBTOOL))" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
@@ -1543,13 +1581,11 @@
     $(TARGET_RECOVERY_ROOT_OUT)/plat_file_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/vendor_file_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/plat_property_contexts \
-    $(TARGET_RECOVERY_ROOT_OUT)/vendor_property_contexts
-
-ifdef BOARD_ODM_SEPOLICY_DIRS
-recovery_sepolicy += \
+    $(TARGET_RECOVERY_ROOT_OUT)/vendor_property_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/odm_file_contexts \
-    $(TARGET_RECOVERY_ROOT_OUT)/odm_property_contexts
-endif
+    $(TARGET_RECOVERY_ROOT_OUT)/odm_property_contexts \
+    $(TARGET_RECOVERY_ROOT_OUT)/product_file_contexts \
+    $(TARGET_RECOVERY_ROOT_OUT)/product_property_contexts
 
 # Passed into rsync from non-recovery root to recovery root, to avoid overwriting recovery-specific
 # SELinux files
@@ -1798,8 +1834,12 @@
   INTERNAL_RECOVERYIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
 endif
 ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
+  INTERNAL_RECOVERYIMAGE_ARGS += --recovery_dtbo $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE)
+else
   INTERNAL_RECOVERYIMAGE_ARGS += --recovery_dtbo $(BOARD_PREBUILT_DTBOIMAGE)
 endif
+endif
 ifdef BOARD_INCLUDE_RECOVERY_ACPIO
   INTERNAL_RECOVERYIMAGE_ARGS += --recovery_acpio $(BOARD_RECOVERY_ACPIO)
 endif
@@ -1859,17 +1899,17 @@
   $(hide) ln -sf prop.default $(TARGET_RECOVERY_ROOT_OUT)/default.prop
   $(BOARD_RECOVERY_IMAGE_PREPARE)
   $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
-  $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
+  $(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
     $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1).unsigned, \
     $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1) --id > $(RECOVERYIMAGE_ID_FILE))
-  $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)),\
+  $(if $(filter true,$(PRODUCT_SUPPORTS_BOOT_SIGNER)),\
     $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
-      $(BOOT_SIGNER) /boot $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1),\
-      $(BOOT_SIGNER) /recovery $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1)\
+      $(BOOT_SIGNER) /boot $(1) $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1),\
+      $(BOOT_SIGNER) /recovery $(1) $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1)\
     )\
   )
-  $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
-    $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
+  $(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
+    $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
   $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
     $(hide) $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))), \
     $(hide) $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))))
@@ -1880,18 +1920,22 @@
 endef
 
 ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
-ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER))
+ifeq (true,$(PRODUCT_SUPPORTS_BOOT_SIGNER))
 $(INSTALLED_BOOTIMAGE_TARGET) : $(BOOT_SIGNER)
 endif
-ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
+ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
 $(INSTALLED_BOOTIMAGE_TARGET) : $(VBOOT_SIGNER)
 endif
 ifeq (true,$(BOARD_AVB_ENABLE))
 $(INSTALLED_BOOTIMAGE_TARGET) : $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH)
 endif
 ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
+$(INSTALLED_BOOTIMAGE_TARGET): $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE)
+else
 $(INSTALLED_BOOTIMAGE_TARGET): $(BOARD_PREBUILT_DTBOIMAGE)
 endif
+endif
 ifdef BOARD_INCLUDE_RECOVERY_ACPIO
 $(INSTALLED_BOOTIMAGE_TARGET): $(BOARD_RECOVERY_ACPIO)
 endif
@@ -1916,8 +1960,12 @@
 endif # BOARD_USES_RECOVERY_AS_BOOT
 
 ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
+$(INSTALLED_RECOVERYIMAGE_TARGET): $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE)
+else
 $(INSTALLED_RECOVERYIMAGE_TARGET): $(BOARD_PREBUILT_DTBOIMAGE)
 endif
+endif
 ifdef BOARD_INCLUDE_RECOVERY_ACPIO
 $(INSTALLED_RECOVERYIMAGE_TARGET): $(BOARD_RECOVERY_ACPIO)
 endif
@@ -2100,12 +2148,89 @@
 endef
 endif
 
+# Check that libraries that should only be in APEXes don't end up in the system
+# image. For the Runtime APEX this complements the checks in
+# art/build/apex/art_apex_test.py.
+# TODO(b/128708192): Implement this restriction in Soong instead.
+
+# TODO(b/124293228): Fix remaining bugs and add these libraries to the list:
+#   libart-compiler.so
+#   libart-dexlayout.so
+#   libart.so
+#   libartbase.so
+#   libartpalette.so
+#   libdexfile.so
+#   libdexfile_external.so  - aosp_marlin-userdebug gets this in a vndk-sp-Q subdirectory.
+#   libicui18n.so
+#   libicuuc.so
+#   libnativehelper.so  - cf_x86_phone-userdebug builds get this in system/lib/arm
+#   libprofile.so
+#   libsigchain.so  - cf_x86_phone-userdebug builds get this in system/lib/arm
+#   libtombstoned_client.so
+APEX_MODULE_LIBS= \
+  libadbconnection.so \
+  libandroidicu.so \
+  libdt_fd_forward.so \
+  libdt_socket.so \
+  libjavacore.so \
+  libjdwp.so \
+  libnativebridge.so \
+  libnativeloader.so \
+  libnpt.so \
+  libopenjdk.so \
+  libopenjdkjvm.so \
+  libopenjdkjvmti.so \
+  libpac.so \
+
+# An option to disable the check below, for local use since some build targets
+# still may create these libraries in /system (b/129006418).
+DISABLE_APEX_LIBS_ABSENCE_CHECK ?=
+
+# If the check below fails, some library has ended up in system/lib or
+# system/lib64 that is intended to only go into some APEX package. The likely
+# cause is that a library or binary in /system has grown a dependency that
+# directly or indirectly pulls in the prohibited library.
+#
+# To resolve this, look for the APEX package that the library belong to - search
+# for it in 'native_shared_lib' properties in 'apex' build modules (see
+# art/build/apex/Android.bp for an example). Then check if there is an exported
+# library in that APEX package that should be used instead, i.e. one listed in
+# its 'native_shared_lib' property for which the corresponding 'cc_library'
+# module has a 'stubs' clause (like libdexfile_external in
+# art/libdexfile/Android.bp).
+#
+# If you cannot find an APEX exported library that fits your needs, or you think
+# that the library you want to depend on should be allowed in /system, then
+# please contact the owners of the APEX package containing the library.
+#
+# If you get this error for a library that is exported in an APEX, then the APEX
+# might be misconfigured or something is wrong in the build system. Please reach
+# out to the APEX package owners and/or soong-team@, or
+# android-building@googlegroups.com externally.
+ifndef DISABLE_APEX_LIBS_ABSENCE_CHECK
+define check-apex-libs-absence
+$(hide) ( \
+  cd $(TARGET_OUT); \
+  findres=$$(find lib* -type f \( -false $(foreach lib,$(APEX_MODULE_LIBS),-o -name $(lib)) \) -print) || exit 1; \
+  if [ -n "$$findres" ]; then \
+    echo "APEX libraries found in system image (see comment in build/make/core/Makefile for details):" 1>&2; \
+    echo "$$findres" | sort 1>&2; \
+    false; \
+  fi; \
+)
+endef
+else
+define check-apex-libs-absence
+endef
+endif
+
 # $(1): output file
 define build-systemimage-target
   @echo "Target system fs image: $(1)"
   $(call create-system-vendor-symlink)
   $(call create-system-product-symlink)
   $(call create-system-product_services-symlink)
+  $(call check-apex-libs-absence)
   @mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt
   $(call generate-image-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt,system, \
       skip_fsck=true)
@@ -2160,6 +2285,19 @@
 $(INSTALLED_SYSTEMIMAGE_TARGET): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH)
 	@echo "Install system fs image: $@"
 	$(copy-file-to-target)
+ifdef RECOVERY_FROM_BOOT_PATCH
+ifeq ($(PRODUCT_USE_DYNAMIC_PARTITION_SIZE),true)
+ifeq ($(BOARD_SYSTEMIMAGE_PARTITION_SIZE),)
+	# system image size is dynamic, hence system_size in generated_system_image_info.txt does not
+	# have room for recovery from boot patch. Increase system_size so that check-all-partition-sizes
+	# accounts for the size of the patch.
+	sed -i'.bak' -e 's/^system_size=.*$$/system_size='"$$(( \
+	      $(call read-image-prop-dictionary,$(systemimage_intermediates)/generated_system_image_info.txt,system_size) + \
+	      $$($(call get-file-size,$(RECOVERY_FROM_BOOT_PATCH))) ))"'/' \
+	    $(systemimage_intermediates)/generated_system_image_info.txt
+endif
+endif
+endif
 	$(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),\
 	    $(call read-image-prop-dictionary,\
 	        $(systemimage_intermediates)/generated_system_image_info.txt,system_size))
@@ -2516,6 +2654,17 @@
 	$(hide) $(FILESLIST) $(TARGET_OUT_SYSTEM_OTHER) > $(@:.txt=.json)
 	$(hide) build/make/tools/fileslist_util.py -c $(@:.txt=.json) > $@
 
+# Determines partition size for system_other.img.
+ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
+ifneq ($(filter system,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES)),)
+INTERNAL_SYSTEM_OTHER_PARTITION_SIZE := $(BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE)
+endif
+endif
+
+ifndef INTERNAL_SYSTEM_OTHER_PARTITION_SIZE
+INTERNAL_SYSTEM_OTHER_PARTITION_SIZE:= $(BOARD_SYSTEMIMAGE_PARTITION_SIZE)
+endif
+
 systemotherimage_intermediates := \
     $(call intermediates-dir-for,PACKAGING,system_other)
 BUILT_SYSTEMOTHERIMAGE_TARGET := $(PRODUCT_OUT)/system_other.img
@@ -2532,7 +2681,7 @@
       $(systemotherimage_intermediates)/generated_system_other_image_info.txt
   $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),\
     $(call read-image-prop-dictionary,\
-      $(systemotherimage_intermediates)/generated_system_other_image_info.txt,system_size))
+      $(systemotherimage_intermediates)/generated_system_other_image_info.txt,system_other_size))
 endef
 
 # We just build this directly to the install location.
@@ -2564,7 +2713,7 @@
 # image which defines a vintf_fragment.
 ifdef BUILT_VENDOR_MANIFEST
 BUILT_ASSEMBLED_VENDOR_MANIFEST := $(PRODUCT_OUT)/verified_assembled_vendor_manifest.xml
-ifeq (true,$(strip $(PRODUCT_ENFORCE_VINTF_MANIFEST)))
+ifeq (true,$(PRODUCT_ENFORCE_VINTF_MANIFEST))
 ifneq ($(strip $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE) $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)),)
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_SYSTEM_ASSEMBLE_VINTF_ENV_VARS := VINTF_ENFORCE_NO_UNUSED_HALS=true
 endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
@@ -2573,10 +2722,71 @@
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BUILT_SYSTEM_MATRIX)
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BUILT_VENDOR_MANIFEST)
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(INTERNAL_VENDORIMAGE_FILES)
+
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS :=
+
+# -- Kernel version and configurations.
+ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),true)
+
+# BOARD_KERNEL_CONFIG_FILE and BOARD_KERNEL_VERSION can be used to override the values extracted
+# from INSTALLED_KERNEL_TARGET.
+ifdef BOARD_KERNEL_CONFIG_FILE
+ifdef BOARD_KERNEL_VERSION
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BOARD_KERNEL_CONFIG_FILE)
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $(BOARD_KERNEL_VERSION):$(BOARD_KERNEL_CONFIG_FILE)
+my_board_extracted_kernel := true
+endif # BOARD_KERNEL_VERSION
+endif # BOARD_KERNEL_CONFIG_FILE
+
+ifneq ($(my_board_extracted_kernel),true)
+ifndef INSTALLED_KERNEL_TARGET
+$(warning No INSTALLED_KERNEL_TARGET is defined when PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS \
+    is true. Information about the updated kernel cannot be built into OTA update package. \
+    You can fix this by: (1) setting TARGET_NO_KERNEL to false and installing the built kernel \
+    to $(PRODUCT_OUT)/kernel, so that kernel information will be extracted from the built kernel; \
+    or (2) extracting kernel configuration and defining BOARD_KERNEL_CONFIG_FILE and \
+    BOARD_KERNEL_VERSION manually; or (3) unsetting PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS \
+    manually.)
+else
+intermediates := $(call intermediates-dir-for,ETC,$(notdir $(BUILT_ASSEMBLED_VENDOR_MANIFEST)))
+
+# Tools for decompression that is not in PATH.
+# Check $(EXTRACT_KERNEL) for decompression algorithms supported by the script.
+# Algorithms that are in the script but not in this list will be found in PATH.
+my_decompress_tools := \
+    lz4:$(HOST_OUT_EXECUTABLES)/lz4 \
+
+my_kernel_configs := $(intermediates)/kernel_configs.txt
+my_kernel_version := $(intermediates)/kernel_version.txt
+$(my_kernel_configs): .KATI_IMPLICIT_OUTPUTS := $(my_kernel_version)
+$(my_kernel_configs): PRIVATE_KERNEL_VERSION_FILE := $(my_kernel_version)
+$(my_kernel_configs): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
+$(my_kernel_configs): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
+$(my_kernel_configs): $(EXTRACT_KERNEL) $(INSTALLED_KERNEL_TARGET)
+	$< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(INSTALLED_KERNEL_TARGET) \
+	  --output-configs $@ \
+	  --output-version $(PRIVATE_KERNEL_VERSION_FILE)
+
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(my_kernel_configs) $(my_kernel_version)
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $$(cat $(my_kernel_version)):$(my_kernel_configs)
+
+intermediates :=
+my_kernel_configs :=
+my_kernel_version :=
+my_decompress_tools :=
+
+endif # my_board_extracted_kernel
+my_board_extracted_kernel :=
+
+endif # INSTALLED_KERNEL_TARGET
+endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
+
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST):
 	@echo "Verifying vendor VINTF manifest."
 	PRODUCT_ENFORCE_VINTF_MANIFEST=$(PRODUCT_ENFORCE_VINTF_MANIFEST) \
 	$(PRIVATE_SYSTEM_ASSEMBLE_VINTF_ENV_VARS) \
 	$(HOST_OUT_EXECUTABLES)/assemble_vintf \
+	    $(PRIVATE_FLAGS) \
 	    -c $(BUILT_SYSTEM_MATRIX) \
 	    -i $(BUILT_VENDOR_MANIFEST) \
 	    $$([ -d $(TARGET_OUT_VENDOR)/etc/vintf/manifest ] && \
@@ -2855,6 +3065,12 @@
 BOARD_AVB_SYSTEM_OTHER_ALGORITHM := $(BOARD_AVB_ALGORITHM)
 endif
 
+$(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)
 endif
@@ -2871,6 +3087,33 @@
   $(error BOARD_AVB_VBMETA_SYSTEM and BOARD_AVB_VBMETA_VENDOR cannot have duplicates)
 endif
 
+# Appends security patch level as a AVB property descriptor
+
+BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.system.security_patch:$(PLATFORM_SECURITY_PATCH)
+
+BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.product.security_patch:$(PLATFORM_SECURITY_PATCH)
+
+BOARD_AVB_PRODUCT_SERVICES_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.product_services.security_patch:$(PLATFORM_SECURITY_PATCH)
+
+# The following vendor- and odm-specific images needs explicitly set per board.
+ifdef BOOT_SECURITY_PATCH
+BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.boot.security_patch:$(BOOT_SECURITY_PATCH)
+endif
+
+ifdef VENDOR_SECURITY_PATCH
+BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.vendor.security_patch:$(VENDOR_SECURITY_PATCH)
+endif
+
+ifdef ODM_SECURITY_PATCH
+BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.odm.security_patch:$(ODM_SECURITY_PATCH)
+endif
+
 BOOT_FOOTER_ARGS := BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS
 DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS
 SYSTEM_FOOTER_ARGS := BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS
@@ -2981,8 +3224,6 @@
 BOARD_AVB_MAKE_VBMETA_SYSTEM_IMAGE_ARGS += --padding_size 4096
 BOARD_AVB_MAKE_VBMETA_VENDOR_IMAGE_ARGS += --padding_size 4096
 
-BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += --prop system_security_patch:$(PLATFORM_SECURITY_PATCH)
-
 ifeq (eng,$(filter eng, $(TARGET_BUILD_VARIANT)))
 # We only need the flag in top-level vbmeta.img.
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --set_hashtree_disabled_flag
@@ -3125,6 +3366,18 @@
 $(foreach p,$(1),$(call read-image-prop-dictionary,$($(p)image_intermediates)/generated_$(p)_image_info.txt,$(p)_size))
 endef
 
+# round result to BOARD_SUPER_PARTITION_ALIGNMENT
+#$(1): the calculated size
+ifeq (,$(BOARD_SUPER_PARTITION_ALIGNMENT))
+define round-partition-size
+$(1)
+endef
+else
+define round-partition-size
+$$((($(1)+$(BOARD_SUPER_PARTITION_ALIGNMENT)-1)/$(BOARD_SUPER_PARTITION_ALIGNMENT)*$(BOARD_SUPER_PARTITION_ALIGNMENT)))
+endef
+endif
+
 define super-slot-suffix
 $(if $(filter true,$(AB_OTA_UPDATER)),$(if $(filter true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)),,_a))
 endef
@@ -3158,8 +3411,10 @@
 # $(2): max size expression
 # $(3): list of partition names
 define check-sum-of-partition-sizes
-  partition_size_list="$(call read-size-of-partitions,$(3))"; \
-  sum_sizes_expr=$$(sed -e 's/ /+/g' <<< "$${partition_size_list}"); \
+  partition_size_list="$$(for i in $(call read-size-of-partitions,$(3)); do \
+    echo $(call round-partition-size,$${i}); \
+  done)"; \
+  sum_sizes_expr=$$(tr '\n' '+' <<< "$${partition_size_list}" | sed 's/+$$//'); \
   if [ $$(( $${sum_sizes_expr} )) -gt $$(( $(2) )) ]; then \
     echo "The sum of sizes of [$(strip $(3))] is larger than $(strip $(1)):"; \
     echo $${sum_sizes_expr} '==' $$(( $${sum_sizes_expr} )) '>' "$(2)" '==' $$(( $(2) )); \
@@ -3285,6 +3540,8 @@
   $(HOST_OUT_EXECUTABLES)/lib/shflags/shflags \
   $(HOST_OUT_EXECUTABLES)/delta_generator \
   $(HOST_OUT_EXECUTABLES)/care_map_generator \
+  $(HOST_OUT_EXECUTABLES)/fc_sort \
+  $(HOST_OUT_EXECUTABLES)/sefcontext_compile \
   $(LPMAKE) \
   $(AVBTOOL) \
   $(BLK_ALLOC_TO_BASE_FS) \
@@ -3292,7 +3549,7 @@
   $(BUILD_VERITY_METADATA) \
   $(BUILD_VERITY_TREE)
 
-ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
+ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
 OTATOOLS += \
   $(FUTILITY) \
   $(VBOOT_SIGNER)
@@ -3362,7 +3619,7 @@
 OTATOOLS_RELEASETOOLS := \
   $(sort $(shell find build/make/tools/releasetools -name "*.pyc" -prune -o -type f))
 
-ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
+ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
 OTATOOLS_DEPS += \
   $(sort $(shell find external/vboot_reference/tests/devkeys -type f))
 endif
@@ -3372,6 +3629,7 @@
 	$(hide) rm -rf $@ $(zip_root)
 	$(hide) mkdir -p $(dir $@) $(zip_root)/bin $(zip_root)/framework $(zip_root)/releasetools
 	$(call copy-files-with-structure,$(OTATOOLS),$(HOST_OUT)/,$(zip_root))
+	$(hide) cp $(SOONG_ZIP) $(zip_root)/bin/
 	$(hide) cp -r -d -p build/make/tools/releasetools/* $(zip_root)/releasetools
 	$(hide) rm -rf $@ $(zip_root)/releasetools/*.pyc
 	$(hide) $(SOONG_ZIP) -o $@ -C $(zip_root) -D $(zip_root) \
@@ -3509,15 +3767,17 @@
 	    $(INSTALLED_KERNEL_TARGET) \
 	    $(INSTALLED_2NDBOOTLOADER_TARGET) \
 	    $(BOARD_PREBUILT_DTBOIMAGE) \
+	    $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE) \
 	    $(BOARD_RECOVERY_ACPIO) \
-	    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH) \
-	    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH) \
-	    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH) \
-	    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH) \
-	    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH) \
+	    $(PRODUCT_SYSTEM_BASE_FS_PATH) \
+	    $(PRODUCT_VENDOR_BASE_FS_PATH) \
+	    $(PRODUCT_PRODUCT_BASE_FS_PATH) \
+	    $(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH) \
+	    $(PRODUCT_ODM_BASE_FS_PATH) \
 	    $(LPMAKE) \
 	    $(SELINUX_FC) \
 	    $(APKCERTS_FILE) \
+	    $(SOONG_APEX_KEYS_FILE) \
 	    $(SOONG_ZIP) \
 	    $(HOST_OUT_EXECUTABLES)/fs_config \
 	    $(HOST_OUT_EXECUTABLES)/imgdiff \
@@ -3548,8 +3808,12 @@
 	$(hide) cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
 endif
 ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
+	$(hide) cp $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
+else
 	$(hide) cp $(BOARD_PREBUILT_DTBOIMAGE) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
 endif
+endif
 ifdef BOARD_INCLUDE_RECOVERY_ACPIO
 	$(hide) cp $(BOARD_RECOVERY_ACPIO) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_acpio
 endif
@@ -3647,6 +3911,7 @@
 	@# build them.
 	$(hide) mkdir -p $(zip_root)/META
 	$(hide) cp $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
+	$(hide) cp $(SOONG_APEX_KEYS_FILE) $(zip_root)/META/apexkeys.txt
 ifneq ($(tool_extension),)
 	$(hide) cp $(PRIVATE_TOOL_EXTENSION) $(zip_root)/META/
 endif
@@ -3691,25 +3956,25 @@
 	# OTA scripts are only interested in fingerprint related properties
 	$(hide) echo "oem_fingerprint_properties=$(OEM_THUMBPRINT_PROPERTIES)" >> $(zip_root)/META/misc_info.txt
 endif
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH),)
-	$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH) \
-	  $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH))
+ifneq ($(PRODUCT_SYSTEM_BASE_FS_PATH),)
+	$(hide) cp $(PRODUCT_SYSTEM_BASE_FS_PATH) \
+	  $(zip_root)/META/$(notdir $(PRODUCT_SYSTEM_BASE_FS_PATH))
 endif
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH),)
-	$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH) \
-	  $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH))
+ifneq ($(PRODUCT_VENDOR_BASE_FS_PATH),)
+	$(hide) cp $(PRODUCT_VENDOR_BASE_FS_PATH) \
+	  $(zip_root)/META/$(notdir $(PRODUCT_VENDOR_BASE_FS_PATH))
 endif
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH),)
-	$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH) \
-	  $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH))
+ifneq ($(PRODUCT_PRODUCT_BASE_FS_PATH),)
+	$(hide) cp $(PRODUCT_PRODUCT_BASE_FS_PATH) \
+	  $(zip_root)/META/$(notdir $(PRODUCT_PRODUCT_BASE_FS_PATH))
 endif
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH),)
-	$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH) \
-	  $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH))
+ifneq ($(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH),)
+	$(hide) cp $(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH) \
+	  $(zip_root)/META/$(notdir $(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH))
 endif
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH),)
-	$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH) \
-	  $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH))
+ifneq ($(PRODUCT_ODM_BASE_FS_PATH),)
+	$(hide) cp $(PRODUCT_ODM_BASE_FS_PATH) \
+	  $(zip_root)/META/$(notdir $(PRODUCT_ODM_BASE_FS_PATH))
 endif
 ifneq (,$(filter address, $(SANITIZE_TARGET)))
 	# We need to create userdata.img with real data because the instrumented libraries are in userdata.img.
@@ -3760,8 +4025,10 @@
 endif
 	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
+ifdef BUILDING_SYSTEM_IMAGE
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	    build/make/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
+endif # BUILDING_SYSTEM_IMAGE
 endif
 ifeq ($(AB_OTA_UPDATER),true)
 	@# When using the A/B updater, include the updater config files in the zip.
@@ -3929,6 +4196,8 @@
 
 INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
 
+INTERNAL_OTA_METADATA := $(PRODUCT_OUT)/ota_metadata
+
 $(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
 
 ifeq ($(AB_OTA_UPDATER),true)
@@ -3937,10 +4206,12 @@
 $(INTERNAL_OTA_PACKAGE_TARGET): $(BROTLI)
 endif
 
+$(INTERNAL_OTA_PACKAGE_TARGET): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_OTA_METADATA)
+
 $(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) \
 	    build/make/tools/releasetools/ota_from_target_files
 	@echo "Package OTA: $@"
-	$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR))
+	$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --output_metadata_path $(INTERNAL_OTA_METADATA))
 
 .PHONY: otapackage
 otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)
@@ -4044,7 +4315,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.
@@ -4147,14 +4418,36 @@
 # BOARD_SUPER_PARTITION_SIZE must be defined to build super image.
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 
+# Dump variables used by build_super_image.py.
+define dump-super-image-info
+  $(call dump-dynamic-partitions-info,$(1))
+  $(if $(filter true,$(AB_OTA_UPDATER)), \
+    echo "ab_update=true" >> $(1))
+endef
+
 ifneq (true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS))
-INSTALLED_SUPERIMAGE_TARGET := $(PRODUCT_OUT)/super.img
+INSTALLED_SUPERIMAGE_TARGET := $(call intermediates-dir-for,PACKAGING,super.img)/super.img
 $(INSTALLED_SUPERIMAGE_TARGET): extracted_input_target_files := $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE))
 $(INSTALLED_SUPERIMAGE_TARGET): $(LPMAKE) $(BUILT_TARGET_FILES_PACKAGE) $(BUILD_SUPER_IMAGE)
 	$(call pretty,"Target super fs image: $@")
 	PATH=$(dir $(LPMAKE)):$$PATH \
 	    $(BUILD_SUPER_IMAGE) -v $(extracted_input_target_files) $@
-endif
+
+# supernod uses images in the $(PRODUCT_OUT) directory instead of images from target files package.
+.PHONY: superimage-nodeps supernod
+superimage-nodeps supernod: intermediates := $(call intermediates-dir-for,PACKAGING,superimage-nodeps)
+superimage-nodeps supernod: | $(LPMAKE) $(BUILD_SUPER_IMAGE) \
+    $(foreach p, $(BOARD_SUPER_PARTITION_PARTITION_LIST), $(INSTALLED_$(call to-upper,$(p))IMAGE_TARGET))
+	$(call pretty,"make $(INSTALLED_SUPERIMAGE_TARGET): ignoring dependencies")
+	mkdir -p $(intermediates)
+	rm -rf $(intermediates)/misc_info.txt
+	$(call dump-super-image-info,$(intermediates)/misc_info.txt)
+	$(foreach p,$(BOARD_SUPER_PARTITION_PARTITION_LIST), \
+	  echo "$(p)_image=$(INSTALLED_$(call to-upper,$(p))IMAGE_TARGET)" >> $(intermediates)/misc_info.txt;)
+	PATH=$(dir $(LPMAKE)):$$PATH \
+	  $(BUILD_SUPER_IMAGE) -v $(intermediates)/misc_info.txt $(INSTALLED_SUPERIMAGE_TARGET)
+
+endif # PRODUCT_RETROFIT_DYNAMIC_PARTITIONS != "true"
 
 $(call dist-for-goals,dist_files,$(INSTALLED_SUPERIMAGE_TARGET))
 
@@ -4164,10 +4457,7 @@
 	$(call pretty,"Target empty super fs image: $@")
 	mkdir -p $(intermediates)
 	rm -rf $(intermediates)/misc_info.txt
-	$(call dump-dynamic-partitions-info,$(intermediates)/misc_info.txt)
-ifeq ($(AB_OTA_UPDATER),true)
-	echo "ab_update=true" >> $(intermediates)/misc_info.txt
-endif
+	$(call dump-super-image-info,$(intermediates)/misc_info.txt)
 	PATH=$(dir $(LPMAKE)):$$PATH \
 	    $(BUILD_SUPER_IMAGE) -v $(intermediates)/misc_info.txt $@
 
@@ -4182,20 +4472,23 @@
 dalvikfiles: $(INTERNAL_DALVIK_MODULES)
 
 ifeq ($(BUILD_QEMU_IMAGES),true)
-INSTALLED_QEMU_SYSTEMIMAGE := $(PRODUCT_OUT)/system-qemu.img
 MK_QEMU_IMAGE_SH := device/generic/goldfish/tools/mk_qemu_image.sh
 SGDISK_HOST := $(HOST_OUT_EXECUTABLES)/sgdisk
+
+ifdef INSTALLED_SYSTEMIMAGE_TARGET
+INSTALLED_QEMU_SYSTEMIMAGE := $(PRODUCT_OUT)/system-qemu.img
 $(INSTALLED_QEMU_SYSTEMIMAGE): $(INSTALLED_SYSTEMIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) $(SIMG2IMG)
 	@echo Create system-qemu.img
-	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) ${PRODUCT_OUT}/system.img)
+	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) $(INSTALLED_SYSTEMIMAGE_TARGET))
 
 systemimage: $(INSTALLED_QEMU_SYSTEMIMAGE)
 droidcore: $(INSTALLED_QEMU_SYSTEMIMAGE)
+endif
 ifdef INSTALLED_VENDORIMAGE_TARGET
 INSTALLED_QEMU_VENDORIMAGE := $(PRODUCT_OUT)/vendor-qemu.img
 $(INSTALLED_QEMU_VENDORIMAGE): $(INSTALLED_VENDORIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) $(SIMG2IMG)
 	@echo Create vendor-qemu.img
-	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) ${PRODUCT_OUT}/vendor.img)
+	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) $(INSTALLED_VENDORIMAGE_TARGET))
 
 vendorimage: $(INSTALLED_QEMU_VENDORIMAGE)
 droidcore: $(INSTALLED_QEMU_VENDORIMAGE)
@@ -4204,7 +4497,7 @@
 INSTALLED_QEMU_PRODUCTIMAGE := $(PRODUCT_OUT)/product-qemu.img
 $(INSTALLED_QEMU_PRODUCTIMAGE): $(INSTALLED_PRODUCTIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) $(SIMG2IMG)
 	@echo Create product-qemu.img
-	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) ${PRODUCT_OUT}/product.img)
+	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) $(INSTALLED_PRODUCTIMAGE_TARGET))
 
 productimage: $(INSTALLED_QEMU_PRODUCTIMAGE)
 droidcore: $(INSTALLED_QEMU_PRODUCTIMAGE)
@@ -4213,7 +4506,7 @@
 INSTALLED_QEMU_PRODUCT_SERVICESIMAGE := $(PRODUCT_OUT)/product_services-qemu.img
 $(INSTALLED_QEMU_PRODUCT_SERVICESIMAGE): $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) $(SIMG2IMG)
 	@echo Create product_services-qemu.img
-	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) ${PRODUCT_OUT}/product_services.img)
+	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET))
 
 productservicesimage: $(INSTALLED_QEMU_PRODUCT_SERVICESIMAGE)
 droidcore: $(INSTALLED_QEMU_PRODUCT_SERVICESIMAGE)
@@ -4222,7 +4515,7 @@
 INSTALLED_QEMU_ODMIMAGE := $(PRODUCT_OUT)/odm-qemu.img
 $(INSTALLED_QEMU_ODMIMAGE): $(INSTALLED_ODMIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST)
 	@echo Create odm-qemu.img
-	(export SGDISK=$(SGDISK_HOST); $(MK_QEMU_IMAGE_SH) ${PRODUCT_OUT}/odm.img)
+	(export SGDISK=$(SGDISK_HOST); $(MK_QEMU_IMAGE_SH) $(INSTALLED_ODMIMAGE_TARGET))
 
 odmimage: $(INSTALLED_QEMU_ODMIMAGE)
 droidcore: $(INSTALLED_QEMU_ODMIMAGE)
@@ -4321,8 +4614,8 @@
   sdk_atree_files += $(atree_dir)/sdk-android-$(TARGET_CPU_ABI).atree
 endif
 
-ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ATREE_FILES),)
-sdk_atree_files += $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ATREE_FILES)
+ifneq ($(PRODUCT_SDK_ATREE_FILES),)
+sdk_atree_files += $(PRODUCT_SDK_ATREE_FILES)
 else
 sdk_atree_files += $(atree_dir)/sdk.atree
 endif
@@ -4448,9 +4741,3 @@
 ifneq ($(sdk_repo_goal),)
 include $(TOPDIR)development/build/tools/sdk_repo.mk
 endif
-
-#------------------------------------------------------------------
-# Find lsdump paths
-FIND_LSDUMPS_FILE := $(PRODUCT_OUT)/lsdump_paths.txt
-$(FIND_LSDUMPS_FILE) : $(LSDUMP_PATHS)
-	$(hide) rm -rf $@ && echo "$^" | sed -e 's/ /\n/g' > $@
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index 560ed72..931b1b1 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -1,5 +1,6 @@
 # Handle AndroidManifest.xmls
-# Input: LOCAL_MANIFEST_FILE, LOCAL_FULL_MANIFEST_FILE, LOCAL_FULL_LIBS_MANIFEST_FILES
+# Input: LOCAL_MANIFEST_FILE, LOCAL_FULL_MANIFEST_FILE, LOCAL_FULL_LIBS_MANIFEST_FILES,
+#        LOCAL_USE_EMBEDDED_NATIVE_LIBS
 # Output: full_android_manifest
 
 ifeq ($(strip $(LOCAL_MANIFEST_FILE)),)
@@ -35,7 +36,7 @@
   fixed_android_manifest := $(intermediates.COMMON)/manifest/AndroidManifest.xml.fixed
 
   $(full_android_manifest): PRIVATE_LIBS_MANIFESTS := $(my_full_libs_manifest_files)
-  $(full_android_manifest): $(ANDROID_MANIFEST_MERGER_DEPS)
+  $(full_android_manifest): $(ANDROID_MANIFEST_MERGER)
   $(full_android_manifest) : $(fixed_android_manifest) $(my_full_libs_manifest_files)
 	@echo "Merge android manifest files: $@ <-- $< $(PRIVATE_LIBS_MANIFESTS)"
 	@mkdir -p $(dir $@)
@@ -46,19 +47,8 @@
   fixed_android_manifest := $(full_android_manifest)
 endif
 
-ifdef LOCAL_MIN_SDK_VERSION
-  $(fixed_android_manifest): PRIVATE_MIN_SDK_VERSION := $(LOCAL_MIN_SDK_VERSION)
-else ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
-  $(fixed_android_manifest): PRIVATE_MIN_SDK_VERSION := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-else
-  $(fixed_android_manifest): PRIVATE_MIN_SDK_VERSION := $(DEFAULT_APP_TARGET_SDK)
-endif
-
-ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
-  $(fixed_android_manifest): PRIVATE_TARGET_SDK_VERSION := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-else
-  $(fixed_android_manifest): PRIVATE_TARGET_SDK_VERSION := $(DEFAULT_APP_TARGET_SDK)
-endif
+$(fixed_android_manifest): PRIVATE_MIN_SDK_VERSION := $(call module-min-sdk-version)
+$(fixed_android_manifest): PRIVATE_TARGET_SDK_VERSION := $(call module-target-sdk-version)
 
 my_exported_sdk_libs_file := $(call local-intermediates-dir,COMMON)/exported-sdk-libs
 $(fixed_android_manifest): PRIVATE_EXPORTED_SDK_LIBS_FILE := $(my_exported_sdk_libs_file)
@@ -76,6 +66,18 @@
     my_manifest_fixer_flags += --use-embedded-dex
 endif
 
+ifeq ($(LOCAL_MODULE_CLASS),APPS)
+  ifeq (true,$(call math_gt_or_eq,$(patsubst $(PLATFORM_VERSION_CODENAME),100,$(call module-min-sdk-version)),23))
+    ifeq (true,$(LOCAL_USE_EMBEDDED_NATIVE_LIBS))
+      my_manifest_fixer_flags += --extract-native-libs=false
+    else
+      my_manifest_fixer_flags += --extract-native-libs=true
+    endif
+  else ifeq (true,$(LOCAL_USE_EMBEDDED_NATIVE_LIBS))
+    $(call pretty-error,LOCAL_USE_EMBEDDED_NATIVE_LIBS is set but minSdkVersion $(call module-min-sdk-version) does not support it)
+  endif
+endif
+
 $(fixed_android_manifest): PRIVATE_MANIFEST_FIXER_FLAGS := $(my_manifest_fixer_flags)
 # These two libs are added as optional dependencies (<uses-library> with
 # android:required set to false). This is because they haven't existed in pre-P
diff --git a/target/board/generic_x86_a/BoardConfig.mk b/core/android_vts_host_config.mk
similarity index 60%
rename from target/board/generic_x86_a/BoardConfig.mk
rename to core/android_vts_host_config.mk
index e3e8a3a..38ba19d 100644
--- a/target/board/generic_x86_a/BoardConfig.mk
+++ b/core/android_vts_host_config.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2017 The Android Open-Source Project
+# Copyright (C) 2016 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,14 +14,13 @@
 # limitations under the License.
 #
 
-include build/make/target/board/BoardConfigGsiCommon.mk
+LOCAL_MODULE_CLASS := FAKE
+LOCAL_IS_HOST_MODULE := true
+LOCAL_COMPATIBILITY_SUITE := vts
 
-TARGET_CPU_ABI := x86
-TARGET_ARCH := x86
-TARGET_ARCH_VARIANT := x86
+include $(BUILD_SYSTEM)/base_rules.mk
 
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
+$(LOCAL_BUILT_MODULE):
+	@echo "VTS host-driven test target: $(PRIVATE_MODULE)"
+	$(hide) touch $@
 
-# This is a non-system-as-root Legacy GSI build target
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := false
diff --git a/core/app_certificate_validate.mk b/core/app_certificate_validate.mk
index 6d3fdc8..c01526a 100644
--- a/core/app_certificate_validate.mk
+++ b/core/app_certificate_validate.mk
@@ -2,9 +2,9 @@
 ifeq (true,$(non_system_module))
   ifneq (,$(filter $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))%,$(LOCAL_CERTIFICATE)))
     CERTIFICATE_VIOLATION_MODULES += $(LOCAL_MODULE)
-    ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT))
-      $(if $(filter $(LOCAL_MODULE),$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST)),,\
+    ifeq (true,$(PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT))
+      $(if $(filter $(LOCAL_MODULE),$(PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST)),,\
         $(call pretty-error,The module in product partition cannot be signed with certificate in system.))
     endif
   endif
-endif
\ No newline at end of file
+endif
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/autogen_test_config.mk b/core/autogen_test_config.mk
index a01d80f..6d75132 100644
--- a/core/autogen_test_config.mk
+++ b/core/autogen_test_config.mk
@@ -36,7 +36,7 @@
 $(autogen_test_config_file): PRIVATE_MODULE_NAME := $(LOCAL_MODULE)
 $(autogen_test_config_file) : $(autogen_test_config_template)
 	@echo "Auto generating test config $(notdir $@)"
-	$(hide) sed 's&{MODULE}&$(PRIVATE_MODULE_NAME)&g' $< > $@
+	$(hide) sed 's&{MODULE}&$(PRIVATE_MODULE_NAME)&g;s&{EXTRA_OPTIONS}&&g' $< > $@
 my_auto_generate_config := true
 else
 # Auto generating test config file for instrumentation test
diff --git a/core/aux_config.mk b/core/aux_config.mk
index d382ff5..a508a2d 100644
--- a/core/aux_config.mk
+++ b/core/aux_config.mk
@@ -181,5 +181,3 @@
 endif
 
 INSTALLED_AUX_TARGETS :=
-
-droidcore: auxiliary
diff --git a/core/base_rules.mk b/core/base_rules.mk
index fd369f2..d5055d4 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -162,6 +162,19 @@
   $(error user tag detected on module.)
 endif
 
+my_bad_module_tags := $(filter eng debug,$(my_module_tags))
+ifdef my_bad_module_tags
+  ifeq (true,$(LOCAL_UNINSTALLABLE_MODULE))
+    $(call pretty-warning,LOCAL_MODULE_TAGS := $(my_bad_module_tags) does not do anything for uninstallable modules)
+  endif
+  ifneq ($(BUILD_BROKEN_ENG_DEBUG_TAGS),true)
+    $(call pretty-error,LOCAL_MODULE_TAGS := $(my_bad_module_tags) is obsolete. See $(CHANGES_URL)#LOCAL_MODULE_TAGS)
+  else
+    $(call pretty-warning,LOCAL_MODULE_TAGS := $(my_bad_module_tags) is deprecated. See $(CHANGES_URL)#LOCAL_MODULE_TAGS)
+  endif
+  my_bad_module_tags :=
+endif
+
 # Only the tags mentioned in this test are expected to be set by module
 # makefiles. Anything else is either a typo or a source of unexpected
 # behaviors.
@@ -211,15 +224,15 @@
 ifdef LOCAL_IS_HOST_MODULE
   partition_tag :=
 else
-ifeq (true,$(LOCAL_VENDOR_MODULE))
+ifeq (true,$(strip $(LOCAL_VENDOR_MODULE)))
   partition_tag := _VENDOR
-else ifeq (true,$(LOCAL_OEM_MODULE))
+else ifeq (true,$(strip $(LOCAL_OEM_MODULE)))
   partition_tag := _OEM
-else ifeq (true,$(LOCAL_ODM_MODULE))
+else ifeq (true,$(strip $(LOCAL_ODM_MODULE)))
   partition_tag := _ODM
-else ifeq (true,$(LOCAL_PRODUCT_MODULE))
+else ifeq (true,$(strip $(LOCAL_PRODUCT_MODULE)))
   partition_tag := _PRODUCT
-else ifeq (true,$(LOCAL_PRODUCT_SERVICES_MODULE))
+else ifeq (true,$(strip $(LOCAL_PRODUCT_SERVICES_MODULE)))
   partition_tag := _PRODUCT_SERVICES
 else ifeq (NATIVE_TESTS,$(LOCAL_MODULE_CLASS))
   partition_tag := _DATA
@@ -229,6 +242,31 @@
   partition_tag := $(if $(call should-install-to-system,$(my_module_tags)),,_DATA)
 endif
 endif
+# For test modules that lack a suite tag, set null-suite as the default.
+# We only support adding a default suite to native tests, native benchmarks, and instrumentation tests.
+# This is because they are the only tests we currently auto-generate test configs for.
+ifndef LOCAL_COMPATIBILITY_SUITE
+  ifneq ($(filter NATIVE_TESTS NATIVE_BENCHMARK, $(LOCAL_MODULE_CLASS)),)
+    LOCAL_COMPATIBILITY_SUITE := null-suite
+  endif
+  ifneq ($(filter APPS, $(LOCAL_MODULE_CLASS)),)
+    ifneq ($(filter $(my_module_tags),tests),)
+      LOCAL_COMPATIBILITY_SUITE := null-suite
+    endif
+  endif
+endif
+
+use_testcase_folder :=
+ifeq ($(my_module_path),)
+  ifneq ($(LOCAL_MODULE),$(filter $(LOCAL_MODULE),$(DEFAULT_DATA_OUT_MODULES)))
+    ifdef LOCAL_COMPATIBILITY_SUITE
+      ifneq (true, $(LOCAL_IS_HOST_MODULE))
+        use_testcase_folder := true
+      endif
+    endif
+  endif
+endif
+
 ifeq ($(my_module_path),)
   install_path_var := $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS)
   ifeq (true,$(LOCAL_PRIVILEGED_MODULE))
@@ -236,6 +274,16 @@
   endif
 
   my_module_path := $($(install_path_var))
+
+  # If use_testcase_folder be set, and LOCAL_MODULE_PATH not set,
+  # overwrite the default path under testcase.
+  ifeq ($(use_testcase_folder),true)
+    arch_dir := $($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+    testcase_folder := $($(my_prefix)OUT_TESTCASES)/$(LOCAL_MODULE)/$(arch_dir)
+    my_module_path := $(testcase_folder)
+    arch_dir :=
+  endif
+
   ifeq ($(strip $(my_module_path)),)
     $(error $(LOCAL_PATH): unhandled install path "$(install_path_var) for $(LOCAL_MODULE)")
   endif
@@ -311,7 +359,9 @@
   # Neither do Runtime Resource Overlay apks, which contain just the overlaid resources.
   else ifeq ($(LOCAL_IS_RUNTIME_RESOURCE_OVERLAY),true)
   else
-    my_module_path := $(my_module_path)/$(LOCAL_MODULE)
+    ifneq ($(use_testcase_folder),true)
+      my_module_path := $(my_module_path)/$(LOCAL_MODULE)
+    endif
   endif
   endif
   LOCAL_INSTALLED_MODULE := $(my_module_path)/$(my_installed_module_stem)
@@ -416,12 +466,21 @@
 my_init_rc_installed :=
 my_init_rc_pairs :=
 my_installed_symlinks :=
+my_default_test_module :=
+ifeq ($(use_testcase_folder),true)
+arch_dir := $($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+my_default_test_module := $($(my_prefix)OUT_TESTCASES)/$(LOCAL_MODULE)/$(arch_dir)/$(my_installed_module_stem)
+arch_dir :=
+endif
+
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
+ifneq ($(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: $@"
 	$(copy-file-to-new-target)
 	$(PRIVATE_POST_INSTALL_CMD)
+endif
 
 ifndef LOCAL_IS_HOST_MODULE
 # Rule to install the module's companion init.rc.
@@ -531,20 +590,6 @@
 endif
 endif
 
-# For test modules that lack a suite tag, set null-suite as the default.
-# We only support adding a default suite to native tests, native benchmarks, and instrumentation tests.
-# This is because they are the only tests we currently auto-generate test configs for.
-ifndef LOCAL_COMPATIBILITY_SUITE
-ifneq ($(filter NATIVE_TESTS NATIVE_BENCHMARK, $(LOCAL_MODULE_CLASS)),)
-LOCAL_COMPATIBILITY_SUITE := null-suite
-endif
-ifneq ($(filter APPS, $(LOCAL_MODULE_CLASS)),)
-ifneq ($(filter $(my_module_tags),tests),)
-LOCAL_COMPATIBILITY_SUITE := null-suite
-endif
-endif
-endif
-
 ###########################################################
 ## Compatibility suite files.
 ###########################################################
@@ -562,11 +607,24 @@
 ifdef LOCAL_MULTILIB
   multi_arch := true
 endif
+
 ifdef multi_arch
+arch_dir := /$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+else
+ifeq ($(use_testcase_folder),true)
   arch_dir := /$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
 endif
+endif
+
 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)), \
@@ -658,6 +716,17 @@
 endif
 
 
+ifeq ($(use_testcase_folder),true)
+ifneq ($(my_test_data_file_pairs),)
+$(foreach pair, $(my_test_data_file_pairs), \
+  $(eval parts := $(subst :,$(space),$(pair))) \
+  $(eval src_path := $(word 1,$(parts))) \
+  $(eval file := $(word 2,$(parts))) \
+  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+    $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
+      $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data))))))
+endif
+else
 ifneq ($(my_test_data_file_pairs),)
 $(foreach pair, $(my_test_data_file_pairs), \
   $(eval parts := $(subst :,$(space),$(pair))) \
@@ -667,6 +736,9 @@
     $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
       $(src_path):$(call append-path,$(dir),$(file))))))
 endif
+endif
+
+
 
 arch_dir :=
 is_native :=
@@ -702,6 +774,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 c17f052..43063a8 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -257,6 +257,14 @@
   else # LOCAL_NDK_STL_VARIANT must be none
     # Do nothing.
   endif
+
+  # Clang's coverage/profile runtime needs symbols like 'stderr' that were not
+  # exported from libc prior to API level 23
+  ifneq ($(my_ndk_api),current)
+    ifeq ($(call math_lt, $(my_ndk_api),23),true)
+      my_native_coverage := false
+    endif
+  endif
 endif
 
 ifneq ($(LOCAL_USE_VNDK),)
@@ -290,11 +298,9 @@
 else # LOCAL_IS_HOST_MODULE
   # Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of
   # device builds
-  ifneq ($($(my_prefix)OS),windows)
-    my_ldlibs += -ldl -lpthread -lm
-    ifneq ($(HOST_OS),darwin)
-      my_ldlibs += -lrt
-    endif
+  my_ldlibs += -ldl -lpthread -lm
+  ifneq ($(HOST_OS),darwin)
+    my_ldlibs += -lrt
   endif
 endif
 
@@ -315,17 +321,15 @@
 # all code is position independent, and then those warnings get promoted to
 # errors.
 ifneq ($(LOCAL_NO_PIC),true)
-  ifneq ($($(my_prefix)OS),windows)
-    ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
-      my_cflags += -fPIE
-      ifndef BUILD_HOST_static
-        ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
-          my_ldflags += -pie
-        endif
+  ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+    my_cflags += -fPIE
+    ifndef BUILD_HOST_static
+      ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+        my_ldflags += -pie
       endif
-    else
-      my_cflags += -fPIC
     endif
+  else
+    my_cflags += -fPIC
   endif
 endif
 
@@ -430,20 +434,12 @@
 
 include $(BUILD_SYSTEM)/config_sanitizers.mk
 
-# Statically link libwinpthread when cross compiling win32.
-ifeq ($($(my_prefix)OS),windows)
-  my_static_libraries += libwinpthread
-endif
-
 ifneq ($(filter ../%,$(my_src_files)),)
 my_soong_problems += dotdot_srcs
 endif
 ifneq ($(foreach i,$(my_c_includes),$(filter %/..,$(i))$(findstring /../,$(i))),)
 my_soong_problems += dotdot_incs
 endif
-ifneq ($(filter %.arm,$(my_src_files)),)
-my_soong_problems += srcs_dotarm
-endif
 
 ####################################################
 ## Add FDO flags if FDO is turned on and supported
@@ -507,19 +503,15 @@
 ###########################################################
 LOCAL_ARM_MODE := $(strip $(LOCAL_ARM_MODE))
 ifeq ($($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH),arm)
-arm_objects_mode := $(if $(LOCAL_ARM_MODE),$(LOCAL_ARM_MODE),arm)
 normal_objects_mode := $(if $(LOCAL_ARM_MODE),$(LOCAL_ARM_MODE),thumb)
 
 # Read the values from something like TARGET_arm_CFLAGS or
 # TARGET_thumb_CFLAGS.  HOST_(arm|thumb)_CFLAGS values aren't
 # actually used (although they are usually empty).
-arm_objects_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)$(arm_objects_mode)_CFLAGS)
 normal_objects_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)$(normal_objects_mode)_CFLAGS)
 
 else
-arm_objects_mode :=
 normal_objects_mode :=
-arm_objects_cflags :=
 normal_objects_cflags :=
 endif
 
@@ -658,7 +650,7 @@
 proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
 
 my_rename_cpp_ext :=
-ifneq (,$(filter nanopb-c nanopb-c-enable_malloc, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
+ifneq (,$(filter nanopb-c nanopb-c-enable_malloc nanopb-c-16bit nanopb-c-enable_malloc-16bit nanopb-c-32bit nanopb-c-enable_malloc-32bit, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
 my_proto_source_suffix := .c
 my_proto_c_includes := external/nanopb-c
 my_protoc_flags := --nanopb_out=$(proto_gen_dir) \
@@ -713,6 +705,14 @@
     my_static_libraries += libprotobuf-c-nano-enable_malloc
 else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c)
     my_static_libraries += libprotobuf-c-nano
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-enable_malloc-16bit)
+    my_static_libraries += libprotobuf-c-nano-enable_malloc-16bit
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-16bit)
+    my_static_libraries += libprotobuf-c-nano-16bit
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-enable_malloc-32bit)
+    my_static_libraries += libprotobuf-c-nano-enable_malloc-32bit
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-32bit)
+    my_static_libraries += libprotobuf-c-nano-32bit
 else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),full)
     ifdef LOCAL_SDK_VERSION
         my_static_libraries += libprotobuf-cpp-full-ndk
@@ -854,22 +854,9 @@
 ## C++: Compile .cpp files to .o.
 ###########################################################
 
-# we also do this on host modules, even though
-# it's not really arm, because there are files that are shared.
-cpp_arm_sources := $(patsubst %$(LOCAL_CPP_EXTENSION).arm,%$(LOCAL_CPP_EXTENSION),$(filter %$(LOCAL_CPP_EXTENSION).arm,$(my_src_files)))
-dotdot_arm_sources := $(filter ../%,$(cpp_arm_sources))
-cpp_arm_sources := $(filter-out ../%,$(cpp_arm_sources))
-cpp_arm_objects := $(addprefix $(intermediates)/,$(cpp_arm_sources:$(LOCAL_CPP_EXTENSION)=.o))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(cpp_arm_sources)),$(cpp_arm_objects))
-
-# For source files starting with ../, we remove all the ../ in the object file path,
-# to avoid object file escaping the intermediate directory.
-dotdot_arm_objects :=
-$(foreach s,$(dotdot_arm_sources),\
-  $(eval $(call compile-dotdot-cpp-file,$(s),\
-  $(my_additional_dependencies),\
-  dotdot_arm_objects)))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
+ifneq ($(filter %$(LOCAL_CPP_EXTENSION).arm,$(my_src_files)),)
+$(call pretty-error,Files ending in $(LOCAL_CPP_EXTENSION).arm are deprecated. See $(CHANGES_URL)#file_arm)
+endif
 
 dotdot_sources := $(filter ../%$(LOCAL_CPP_EXTENSION),$(my_src_files))
 dotdot_objects :=
@@ -880,15 +867,11 @@
 $(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
 
 cpp_normal_sources := $(filter-out ../%,$(filter %$(LOCAL_CPP_EXTENSION),$(my_src_files)))
-cpp_normal_objects := $(addprefix $(intermediates)/,$(cpp_normal_sources:$(LOCAL_CPP_EXTENSION)=.o))
-$(call track-src-file-obj,$(cpp_normal_sources),$(cpp_normal_objects))
+cpp_objects := $(addprefix $(intermediates)/,$(cpp_normal_sources:$(LOCAL_CPP_EXTENSION)=.o))
+$(call track-src-file-obj,$(cpp_normal_sources),$(cpp_objects))
 
-$(dotdot_arm_objects) $(cpp_arm_objects): PRIVATE_ARM_MODE := $(arm_objects_mode)
-$(dotdot_arm_objects) $(cpp_arm_objects): PRIVATE_ARM_CFLAGS := $(arm_objects_cflags)
-$(dotdot_objects) $(cpp_normal_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
-$(dotdot_objects) $(cpp_normal_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-
-cpp_objects        := $(cpp_arm_objects) $(cpp_normal_objects)
+$(dotdot_objects) $(cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
+$(dotdot_objects) $(cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 
 ifneq ($(strip $(cpp_objects)),)
 $(cpp_objects): $(intermediates)/%.o: \
@@ -898,7 +881,7 @@
 $(call include-depfiles-for-objs, $(cpp_objects))
 endif
 
-cpp_objects += $(dotdot_arm_objects) $(dotdot_objects)
+cpp_objects += $(dotdot_objects)
 
 ###########################################################
 ## C++: Compile generated .cpp files to .o.
@@ -910,7 +893,6 @@
 
 ifneq ($(strip $(gen_cpp_objects)),)
 # Compile all generated files as thumb.
-# TODO: support compiling certain generated files as arm.
 $(gen_cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(gen_cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(gen_cpp_objects): $(intermediates)/%.o: \
@@ -958,20 +940,9 @@
 ## C: Compile .c files to .o.
 ###########################################################
 
-c_arm_sources := $(patsubst %.c.arm,%.c,$(filter %.c.arm,$(my_src_files)))
-dotdot_arm_sources := $(filter ../%,$(c_arm_sources))
-c_arm_sources := $(filter-out ../%,$(c_arm_sources))
-c_arm_objects := $(addprefix $(intermediates)/,$(c_arm_sources:.c=.o))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(c_arm_sources)),$(c_arm_objects))
-
-# For source files starting with ../, we remove all the ../ in the object file path,
-# to avoid object file escaping the intermediate directory.
-dotdot_arm_objects :=
-$(foreach s,$(dotdot_arm_sources),\
-  $(eval $(call compile-dotdot-c-file,$(s),\
-    $(my_additional_dependencies),\
-    dotdot_arm_objects)))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
+ifneq ($(filter %.c.arm,$(my_src_files)),)
+$(call pretty-error,Files ending in .c.arm are deprecated. See $(CHANGES_URL)#file_arm)
+endif
 
 dotdot_sources := $(filter ../%.c, $(my_src_files))
 dotdot_objects :=
@@ -982,15 +953,11 @@
 $(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
 
 c_normal_sources := $(filter-out ../%,$(filter %.c,$(my_src_files)))
-c_normal_objects := $(addprefix $(intermediates)/,$(c_normal_sources:.c=.o))
-$(call track-src-file-obj,$(c_normal_sources),$(c_normal_objects))
+c_objects := $(addprefix $(intermediates)/,$(c_normal_sources:.c=.o))
+$(call track-src-file-obj,$(c_normal_sources),$(c_objects))
 
-$(dotdot_arm_objects) $(c_arm_objects): PRIVATE_ARM_MODE := $(arm_objects_mode)
-$(dotdot_arm_objects) $(c_arm_objects): PRIVATE_ARM_CFLAGS := $(arm_objects_cflags)
-$(dotdot_objects) $(c_normal_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
-$(dotdot_objects) $(c_normal_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-
-c_objects        := $(c_arm_objects) $(c_normal_objects)
+$(dotdot_objects) $(c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
+$(dotdot_objects) $(c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 
 ifneq ($(strip $(c_objects)),)
 $(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c \
@@ -999,7 +966,7 @@
 $(call include-depfiles-for-objs, $(c_objects))
 endif
 
-c_objects += $(dotdot_arm_objects) $(dotdot_objects)
+c_objects += $(dotdot_objects)
 
 ###########################################################
 ## C: Compile generated .c files to .o.
@@ -1011,7 +978,6 @@
 
 ifneq ($(strip $(gen_c_objects)),)
 # Compile all generated files as thumb.
-# TODO: support compiling certain generated files as arm.
 $(gen_c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(gen_c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c \
@@ -1248,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/board_config.mk b/core/board_config.mk
new file mode 100644
index 0000000..ed741c3
--- /dev/null
+++ b/core/board_config.mk
@@ -0,0 +1,508 @@
+#
+# 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.
+#
+
+# ###############################################################
+# This file includes BoardConfig.mk for the device being built,
+# and sanity-checks the variable defined therein.
+# ###############################################################
+
+_board_strip_readonly_list := \
+  BOARD_EGL_CFG \
+  BOARD_HAVE_BLUETOOTH \
+  BOARD_INSTALLER_CMDLINE \
+  BOARD_KERNEL_CMDLINE \
+  BOARD_KERNEL_BASE \
+  BOARD_USES_GENERIC_AUDIO \
+  BOARD_VENDOR_USE_AKMD \
+  BOARD_WPA_SUPPLICANT_DRIVER \
+  BOARD_WLAN_DEVICE \
+  TARGET_ARCH \
+  TARGET_ARCH_VARIANT \
+  TARGET_CPU_ABI \
+  TARGET_CPU_ABI2 \
+  TARGET_CPU_VARIANT \
+  TARGET_CPU_VARIANT_RUNTIME \
+  TARGET_2ND_ARCH \
+  TARGET_2ND_ARCH_VARIANT \
+  TARGET_2ND_CPU_ABI \
+  TARGET_2ND_CPU_ABI2 \
+  TARGET_2ND_CPU_VARIANT \
+  TARGET_2ND_CPU_VARIANT_RUNTIME \
+  TARGET_BOARD_PLATFORM \
+  TARGET_BOARD_PLATFORM_GPU \
+  TARGET_BOOTLOADER_BOARD_NAME \
+  TARGET_NO_BOOTLOADER \
+  TARGET_NO_KERNEL \
+  TARGET_NO_RECOVERY \
+  TARGET_NO_RADIOIMAGE \
+  TARGET_HARDWARE_3D \
+  WITH_DEXPREOPT \
+
+# File system variables
+_board_strip_readonly_list += \
+  BOARD_FLASH_BLOCK_SIZE \
+  BOARD_BOOTIMAGE_PARTITION_SIZE \
+  BOARD_RECOVERYIMAGE_PARTITION_SIZE \
+  BOARD_SYSTEMIMAGE_PARTITION_SIZE \
+  BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_USERDATAIMAGE_PARTITION_SIZE \
+  BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_CACHEIMAGE_PARTITION_SIZE \
+  BOARD_VENDORIMAGE_PARTITION_SIZE \
+  BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_PRODUCTIMAGE_PARTITION_SIZE \
+  BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE \
+  BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_ODMIMAGE_PARTITION_SIZE \
+  BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \
+
+# Logical partitions related variables.
+_dynamic_partitions_var_list += \
+  BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_SUPER_PARTITION_SIZE \
+  BOARD_SUPER_PARTITION_GROUPS \
+
+_board_strip_readonly_list += $(_dynamic_partitions_var_list)
+
+_build_broken_var_list := \
+  BUILD_BROKEN_ANDROIDMK_EXPORTS \
+  BUILD_BROKEN_DUP_COPY_HEADERS \
+  BUILD_BROKEN_DUP_RULES \
+  BUILD_BROKEN_PHONY_TARGETS \
+  BUILD_BROKEN_ENG_DEBUG_TAGS \
+
+_board_true_false_vars := $(_build_broken_var_list)
+_board_strip_readonly_list += $(_build_broken_var_list)
+
+# Conditional to building on linux, as dex2oat currently does not work on darwin.
+ifeq ($(HOST_OS),linux)
+  WITH_DEXPREOPT := true
+endif
+
+# ###############################################################
+# Broken build defaults
+# ###############################################################
+BUILD_BROKEN_ANDROIDMK_EXPORTS :=
+BUILD_BROKEN_DUP_COPY_HEADERS :=
+BUILD_BROKEN_DUP_RULES :=
+BUILD_BROKEN_PHONY_TARGETS :=
+BUILD_BROKEN_ENG_DEBUG_TAGS :=
+
+# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
+# or under vendor/*/$(TARGET_DEVICE).  Search in both places, but
+# make sure only one exists.
+# Real boards should always be associated with an OEM vendor.
+ifdef TARGET_DEVICE_DIR
+  ifneq ($(origin TARGET_DEVICE_DIR),command line)
+    $(error TARGET_DEVICE_DIR may not be set manually)
+  endif
+  board_config_mk := $(TARGET_DEVICE_DIR)/BoardConfig.mk
+else
+  board_config_mk := \
+    $(strip $(sort $(wildcard \
+      $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
+      $(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
+      $(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
+    )))
+  ifeq ($(board_config_mk),)
+    $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))
+  endif
+  ifneq ($(words $(board_config_mk)),1)
+    $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))
+  endif
+  TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
+  .KATI_READONLY := TARGET_DEVICE_DIR
+endif
+include $(board_config_mk)
+ifeq ($(TARGET_ARCH),)
+  $(error TARGET_ARCH not defined by board config: $(board_config_mk))
+endif
+ifneq ($(MALLOC_IMPL),)
+  $(warning *** Unsupported option MALLOC_IMPL defined by board config: $(board_config_mk).)
+  $(error Use `MALLOC_SVELTE := true` to configure jemalloc for low-memory)
+endif
+board_config_mk :=
+
+# Clean up and verify BoardConfig variables
+$(foreach var,$(_board_strip_readonly_list),$(eval $(var) := $$(strip $$($(var)))))
+$(foreach var,$(_board_true_false_vars), \
+  $(if $(filter-out true false,$($(var))), \
+    $(error Valid values of $(var) are "true", "false", and "". Not "$($(var))")))
+
+# Default *_CPU_VARIANT_RUNTIME to CPU_VARIANT if unspecified.
+TARGET_CPU_VARIANT_RUNTIME := $(or $(TARGET_CPU_VARIANT_RUNTIME),$(TARGET_CPU_VARIANT))
+TARGET_2ND_CPU_VARIANT_RUNTIME := $(or $(TARGET_2ND_CPU_VARIANT_RUNTIME),$(TARGET_2ND_CPU_VARIANT))
+
+# The combo makefiles sanity-check and set defaults for various CPU configuration
+combo_target := TARGET_
+combo_2nd_arch_prefix :=
+include $(BUILD_SYSTEM)/combo/select.mk
+
+ifdef TARGET_2ND_ARCH
+  combo_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
+  include $(BUILD_SYSTEM)/combo/select.mk
+endif
+
+.KATI_READONLY := $(_board_strip_readonly_list)
+
+INTERNAL_KERNEL_CMDLINE := $(BOARD_KERNEL_CMDLINE)
+ifeq ($(TARGET_CPU_ABI),)
+  $(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
+endif
+ifneq ($(filter %64,$(TARGET_ARCH)),)
+  TARGET_IS_64_BIT := true
+endif
+
+ifeq (,$(filter true,$(TARGET_SUPPORTS_32_BIT_APPS) $(TARGET_SUPPORTS_64_BIT_APPS)))
+  TARGET_SUPPORTS_32_BIT_APPS := true
+endif
+
+# Sanity check to warn about likely cryptic errors later in the build.
+ifeq ($(TARGET_IS_64_BIT),true)
+  ifeq (,$(filter true false,$(TARGET_SUPPORTS_64_BIT_APPS)))
+    $(warning Building a 32-bit-app-only product on a 64-bit device. \
+      If this is intentional, set TARGET_SUPPORTS_64_BIT_APPS := false)
+  endif
+endif
+
+# "ro.product.cpu.abilist32" and "ro.product.cpu.abilist64" are
+# comma separated lists of the 32 and 64 bit ABIs (in order of
+# preference) that the target supports. If TARGET_CPU_ABI_LIST_{32,64}_BIT
+# are defined by the board config, we use them. Else, we construct
+# these lists based on whether TARGET_IS_64_BIT is set.
+#
+# Note that this assumes that the 2ND_CPU_ABI for a 64 bit target
+# is always 32 bits. If this isn't the case, these variables should
+# be overriden in the board configuration.
+ifeq (,$(TARGET_CPU_ABI_LIST_64_BIT))
+  ifeq (true|true,$(TARGET_IS_64_BIT)|$(TARGET_SUPPORTS_64_BIT_APPS))
+    TARGET_CPU_ABI_LIST_64_BIT := $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2)
+  endif
+endif
+
+ifeq (,$(TARGET_CPU_ABI_LIST_32_BIT))
+  ifneq (true,$(TARGET_IS_64_BIT))
+    TARGET_CPU_ABI_LIST_32_BIT := $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2)
+  else
+    ifeq (true,$(TARGET_SUPPORTS_32_BIT_APPS))
+      # For a 64 bit target, assume that the 2ND_CPU_ABI
+      # is a 32 bit ABI.
+      TARGET_CPU_ABI_LIST_32_BIT := $(TARGET_2ND_CPU_ABI) $(TARGET_2ND_CPU_ABI2)
+    endif
+  endif
+endif
+
+# "ro.product.cpu.abilist" is a comma separated list of ABIs (in order
+# of preference) that the target supports. If a TARGET_CPU_ABI_LIST
+# is specified by the board configuration, we use that. If not, we
+# build a list out of the TARGET_CPU_ABIs specified by the config.
+ifeq (,$(TARGET_CPU_ABI_LIST))
+  ifeq ($(TARGET_IS_64_BIT)|$(TARGET_PREFER_32_BIT_APPS),true|true)
+    TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_32_BIT) $(TARGET_CPU_ABI_LIST_64_BIT)
+  else
+    TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_64_BIT) $(TARGET_CPU_ABI_LIST_32_BIT)
+  endif
+endif
+
+# Strip whitespace from the ABI list string.
+TARGET_CPU_ABI_LIST := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST)))
+TARGET_CPU_ABI_LIST_32_BIT := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST_32_BIT)))
+TARGET_CPU_ABI_LIST_64_BIT := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST_64_BIT)))
+
+ifneq ($(BUILD_BROKEN_ANDROIDMK_EXPORTS),true)
+$(KATI_obsolete_export It is a global setting. See $(CHANGES_URL)#export_keyword)
+endif
+
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_RAMDISK
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+TARGET_COPY_OUT_RAMDISK := $(TARGET_COPY_OUT_ROOT)
+endif
+
+###########################################
+# Configure whether we're building the system image
+BUILDING_SYSTEM_IMAGE := true
+ifeq ($(PRODUCT_BUILD_SYSTEM_IMAGE),)
+  ifndef PRODUCT_USE_DYNAMIC_PARTITION_SIZE
+    ifndef BOARD_SYSTEMIMAGE_PARTITION_SIZE
+      BUILDING_SYSTEM_IMAGE :=
+    endif
+  endif
+else ifeq ($(PRODUCT_BUILD_SYSTEM_IMAGE),false)
+  BUILDING_SYSTEM_IMAGE :=
+endif
+.KATI_READONLY := BUILDING_SYSTEM_IMAGE
+
+# Are we building a system_other image
+BUILDING_SYSTEM_OTHER_IMAGE :=
+ifeq ($(PRODUCT_BUILD_SYSTEM_OTHER_IMAGE),)
+  ifdef BUILDING_SYSTEM_IMAGE
+    ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
+      BUILDING_SYSTEM_OTHER_IMAGE := true
+    endif
+  endif
+else ifeq ($(PRODUCT_BUILD_SYSTEM_OTHER_IMAGE),true)
+  BUILDING_SYSTEM_OTHER_IMAGE := true
+  ifndef BUILDING_SYSTEM_IMAGE
+    $(error PRODUCT_BUILD_SYSTEM_OTHER_IMAGE = true requires building the system image)
+  endif
+endif
+.KATI_READONLY := BUILDING_SYSTEM_OTHER_IMAGE
+
+# Are we building a cache image
+BUILDING_CACHE_IMAGE :=
+ifeq ($(PRODUCT_BUILD_CACHE_IMAGE),)
+  ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+    BUILDING_CACHE_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_CACHE_IMAGE),true)
+  BUILDING_CACHE_IMAGE := true
+  ifndef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+    $(error PRODUCT_BUILD_CACHE_IMAGE set to true, but BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE not defined)
+  endif
+endif
+.KATI_READONLY := BUILDING_CACHE_IMAGE
+
+# TODO: Add BUILDING_BOOT_IMAGE / BUILDING_RECOVERY_IMAGE
+# This gets complicated with BOARD_USES_RECOVERY_AS_BOOT, so skipping for now.
+
+# Are we building a ramdisk image
+BUILDING_RAMDISK_IMAGE := true
+ifeq ($(PRODUCT_BUILD_RAMDISK_IMAGE),)
+  # TODO: Be smarter about this. This probably only needs to happen when one of the follow is true:
+  #  BUILDING_BOOT_IMAGE
+  #  BUILDING_RECOVERY_IMAGE
+else ifeq ($(PRODUCT_BUILD_RAMDISK_IMAGE),false)
+  BUILDING_RAMDISK_IMAGE :=
+endif
+.KATI_READONLY := BUILDING_RAMDISK_IMAGE
+
+# Are we building a userdata image
+BUILDING_USERDATA_IMAGE :=
+ifeq ($(PRODUCT_BUILD_USERDATA_IMAGE),)
+  ifdef BOARD_USERDATAIMAGE_PARTITION_SIZE
+    BUILDING_USERDATA_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_USERDATA_IMAGE),true)
+  BUILDING_USERDATA_IMAGE := true
+endif
+.KATI_READONLY := BUILDING_USERDATA_IMAGE
+
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_VENDOR
+ifeq ($(TARGET_COPY_OUT_VENDOR),$(_vendor_path_placeholder))
+  TARGET_COPY_OUT_VENDOR := system/vendor
+else ifeq ($(filter vendor system/vendor,$(TARGET_COPY_OUT_VENDOR)),)
+  $(error TARGET_COPY_OUT_VENDOR must be either 'vendor' or 'system/vendor', seeing '$(TARGET_COPY_OUT_VENDOR)'.)
+endif
+PRODUCT_COPY_FILES := $(subst $(_vendor_path_placeholder),$(TARGET_COPY_OUT_VENDOR),$(PRODUCT_COPY_FILES))
+
+BOARD_USES_VENDORIMAGE :=
+ifdef BOARD_PREBUILT_VENDORIMAGE
+  BOARD_USES_VENDORIMAGE := true
+endif
+ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+  BOARD_USES_VENDORIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_VENDOR),vendor)
+  BOARD_USES_VENDORIMAGE := true
+else ifdef BOARD_USES_VENDORIMAGE
+  $(error TARGET_COPY_OUT_VENDOR must be set to 'vendor' to use a vendor image)
+endif
+.KATI_READONLY := BOARD_USES_VENDORIMAGE
+
+BUILDING_VENDOR_IMAGE :=
+ifeq ($(PRODUCT_BUILD_VENDOR_IMAGE),)
+  ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+    BUILDING_VENDOR_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_VENDOR_IMAGE),true)
+  BUILDING_VENDOR_IMAGE := true
+  ifndef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+    $(error PRODUCT_BUILD_VENDOR_IMAGE set to true, but BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE not defined)
+  endif
+endif
+ifdef BOARD_PREBUILT_VENDORIMAGE
+  BUILDING_VENDOR_IMAGE :=
+endif
+.KATI_READONLY := BUILDING_VENDOR_IMAGE
+
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT
+ifeq ($(TARGET_COPY_OUT_PRODUCT),$(_product_path_placeholder))
+TARGET_COPY_OUT_PRODUCT := system/product
+else ifeq ($(filter product system/product,$(TARGET_COPY_OUT_PRODUCT)),)
+$(error TARGET_COPY_OUT_PRODUCT must be either 'product' or 'system/product', seeing '$(TARGET_COPY_OUT_PRODUCT)'.)
+endif
+PRODUCT_COPY_FILES := $(subst $(_product_path_placeholder),$(TARGET_COPY_OUT_PRODUCT),$(PRODUCT_COPY_FILES))
+
+BOARD_USES_PRODUCTIMAGE :=
+ifdef BOARD_PREBUILT_PRODUCTIMAGE
+  BOARD_USES_PRODUCTIMAGE := true
+endif
+ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+  BOARD_USES_PRODUCTIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_PRODUCT),product)
+  BOARD_USES_PRODUCTIMAGE := true
+else ifdef BOARD_USES_PRODUCTIMAGE
+  $(error TARGET_COPY_OUT_PRODUCT must be set to 'product' to use a product image)
+endif
+.KATI_READONLY := BOARD_USES_PRODUCTIMAGE
+
+BUILDING_PRODUCT_IMAGE :=
+ifeq ($(PRODUCT_BUILD_PRODUCT_IMAGE),)
+  ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+    BUILDING_PRODUCT_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_PRODUCT_IMAGE),true)
+  BUILDING_PRODUCT_IMAGE := true
+  ifndef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+    $(error PRODUCT_BUILD_PRODUCT_IMAGE set to true, but BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE not defined)
+  endif
+endif
+ifdef BOARD_PREBUILT_PRODUCTIMAGE
+  BUILDING_PRODUCT_IMAGE :=
+endif
+.KATI_READONLY := BUILDING_PRODUCT_IMAGE
+
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT_SERVICES
+MERGE_PRODUCT_SERVICES_INTO_PRODUCT :=
+ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),$(_product_services_path_placeholder))
+  TARGET_COPY_OUT_PRODUCT_SERVICES := $(TARGET_COPY_OUT_PRODUCT)
+  MERGE_PRODUCT_SERVICES_INTO_PRODUCT := true
+else ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
+  MERGE_PRODUCT_SERVICES_INTO_PRODUCT := true
+else ifeq ($(filter product_services system/product_services,$(TARGET_COPY_OUT_PRODUCT_SERVICES)),)
+  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be either 'product_services',\
+    '$(TARGET_COPY_OUT_PRODUCT)' or 'system/product_services', seeing '$(TARGET_COPY_OUT_PRODUCT_SERVICES)'.)
+endif
+.KATI_READONLY := MERGE_PRODUCT_SERVICES_INTO_PRODUCT
+PRODUCT_COPY_FILES := $(subst $(_product_services_path_placeholder),$(TARGET_COPY_OUT_PRODUCT_SERVICES),$(PRODUCT_COPY_FILES))
+
+BOARD_USES_PRODUCT_SERVICESIMAGE :=
+ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
+  BOARD_USES_PRODUCT_SERVICESIMAGE := true
+endif
+ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+  BOARD_USES_PRODUCT_SERVICESIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),product_services)
+  BOARD_USES_PRODUCT_SERVICESIMAGE := true
+else ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
+  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be set to 'product_services' to use a product_services image)
+endif
+
+BUILDING_PRODUCT_SERVICES_IMAGE :=
+ifeq ($(PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE),)
+  ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+    BUILDING_PRODUCT_SERVICES_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE),true)
+  BUILDING_PRODUCT_SERVICES_IMAGE := true
+  ifndef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+    $(error PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE set to true, but BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE not defined)
+  endif
+endif
+ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
+  BUILDING_PRODUCT_SERVICES_IMAGE :=
+endif
+.KATI_READONLY := BUILDING_PRODUCT_SERVICES_IMAGE
+
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_ODM
+ifeq ($(TARGET_COPY_OUT_ODM),$(_odm_path_placeholder))
+  TARGET_COPY_OUT_ODM := vendor/odm
+else ifeq ($(filter odm vendor/odm,$(TARGET_COPY_OUT_ODM)),)
+  $(error TARGET_COPY_OUT_ODM must be either 'odm' or 'vendor/odm', seeing '$(TARGET_COPY_OUT_ODM)'.)
+endif
+PRODUCT_COPY_FILES := $(subst $(_odm_path_placeholder),$(TARGET_COPY_OUT_ODM),$(PRODUCT_COPY_FILES))
+
+BOARD_USES_ODMIMAGE :=
+ifdef BOARD_PREBUILT_ODMIMAGE
+  BOARD_USES_ODMIMAGE := true
+endif
+ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+  BOARD_USES_ODMIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_ODM),odm)
+  BOARD_USES_ODMIMAGE := true
+else ifdef BOARD_USES_ODMIMAGE
+  $(error TARGET_COPY_OUT_ODM must be set to 'odm' to use an odm image)
+endif
+
+BUILDING_ODM_IMAGE :=
+ifeq ($(ODM_BUILD_ODM_IMAGE),)
+  ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+    BUILDING_ODM_IMAGE := true
+  endif
+else ifeq ($(PRODUCT_BUILD_ODM_IMAGE),true)
+  BUILDING_ODM_IMAGE := true
+  ifndef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+    $(error PRODUCT_BUILD_ODM_IMAGE set to true, but BOARD_ODMIMAGE_FILE_SYSTEM_TYPE not defined)
+  endif
+endif
+ifdef BOARD_PREBUILT_ODMIMAGE
+  BUILDING_ODM_IMAGE :=
+endif
+.KATI_READONLY := BUILDING_ODM_IMAGE
+
+###########################################
+# Ensure that only TARGET_RECOVERY_UPDATER_LIBS *or* AB_OTA_UPDATER is set.
+TARGET_RECOVERY_UPDATER_LIBS ?=
+AB_OTA_UPDATER ?=
+.KATI_READONLY := TARGET_RECOVERY_UPDATER_LIBS AB_OTA_UPDATER
+ifeq ($(AB_OTA_UPDATER),true)
+  ifneq ($(strip $(TARGET_RECOVERY_UPDATER_LIBS)),)
+    $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using AB_OTA_UPDATER)
+  endif
+endif
+
+# Check BOARD_VNDK_VERSION
+define check_vndk_version
+  $(eval vndk_path := prebuilts/vndk/v$(1)) \
+  $(if $(wildcard $(vndk_path)/*/Android.bp),,$(error VNDK version $(1) not found))
+endef
+
+ifdef BOARD_VNDK_VERSION
+  ifneq ($(BOARD_VNDK_VERSION),current)
+    $(error BOARD_VNDK_VERSION: Only "current" is implemented)
+  endif
+
+  TARGET_VENDOR_TEST_SUFFIX := /vendor
+else
+  TARGET_VENDOR_TEST_SUFFIX :=
+endif
+
+ifeq (,$(TARGET_BUILD_APPS))
+ifdef PRODUCT_EXTRA_VNDK_VERSIONS
+  $(foreach v,$(PRODUCT_EXTRA_VNDK_VERSIONS),$(call check_vndk_version,$(v)))
+endif
+endif
+
+# Ensure that BOARD_SYSTEMSDK_VERSIONS are all within PLATFORM_SYSTEMSDK_VERSIONS
+_unsupported_systemsdk_versions := $(filter-out $(PLATFORM_SYSTEMSDK_VERSIONS),$(BOARD_SYSTEMSDK_VERSIONS))
+ifneq (,$(_unsupported_systemsdk_versions))
+  $(error System SDK versions '$(_unsupported_systemsdk_versions)' in BOARD_SYSTEMSDK_VERSIONS are not supported.\
+          Supported versions are $(PLATFORM_SYSTEMSDK_VERSIONS))
+endif
diff --git a/core/build_rro_package.mk b/core/build_rro_package.mk
index 0b4a0c4..a6921d5 100644
--- a/core/build_rro_package.mk
+++ b/core/build_rro_package.mk
@@ -16,14 +16,14 @@
 endif
 
 partition :=
-ifeq ($(LOCAL_ODM_MODULE),true)
+ifeq ($(strip $(LOCAL_ODM_MODULE)),true)
   partition := $(TARGET_OUT_ODM)
-else ifeq ($(LOCAL_PRODUCT_MODULE),true)
-  partition := $(TARGET_OUT_PRODUCT)
-else ifeq ($(LOCAL_PRODUCT_SERVICES_MODULE),true)
+else ifeq ($(strip $(LOCAL_VENDOR_MODULE)),true)
+  partition := $(TARGET_OUT_VENDOR)
+else ifeq ($(strip $(LOCAL_PRODUCT_SERVICES_MODULE)),true)
   partition := $(TARGET_OUT_PRODUCT_SERVICES)
 else
-  partition := $(TARGET_OUT_VENDOR)
+  partition := $(TARGET_OUT_PRODUCT)
 endif
 
 ifeq ($(LOCAL_RRO_THEME),)
diff --git a/core/check_elf_file.mk b/core/check_elf_file.mk
index 69d891c..0faaadd 100644
--- a/core/check_elf_file.mk
+++ b/core/check_elf_file.mk
@@ -13,14 +13,18 @@
 # - intermediates
 # - my_installed_module_stem
 # - my_prebuilt_src_file
+# - my_check_elf_file_shared_lib_files
 
 ifndef LOCAL_IS_HOST_MODULE
 ifneq ($(filter $(LOCAL_MODULE_CLASS),SHARED_LIBRARIES EXECUTABLES NATIVE_TESTS),)
 check_elf_files_stamp := $(intermediates)/check_elf_files.timestamp
 $(check_elf_files_stamp): PRIVATE_SONAME := $(if $(filter $(LOCAL_MODULE_CLASS),SHARED_LIBRARIES),$(my_installed_module_stem))
 $(check_elf_files_stamp): PRIVATE_ALLOW_UNDEFINED_SYMBOLS := $(LOCAL_ALLOW_UNDEFINED_SYMBOLS)
-$(check_elf_files_stamp): PRIVATE_SHARED_LIBRARY_FILES := # This variable will be set by `core/main.mk`
-$(check_elf_files_stamp): $(my_prebuilt_src_file) $(CHECK_ELF_FILE) $(LLVM_READOBJ)
+# PRIVATE_SHARED_LIBRARY_FILES are file paths to built shared libraries.
+# In addition to $(my_check_elf_file_shared_lib_files), some file paths are
+# added by `resolve-shared-libs-for-elf-file-check` from `core/main.mk`.
+$(check_elf_files_stamp): PRIVATE_SHARED_LIBRARY_FILES := $(my_check_elf_file_shared_lib_files)
+$(check_elf_files_stamp): $(my_prebuilt_src_file) $(my_check_elf_file_shared_lib_files) $(CHECK_ELF_FILE) $(LLVM_READOBJ)
 	@echo Check prebuilt ELF binary: $<
 	$(hide) mkdir -p $(dir $@)
 	$(hide) rm -f $@
@@ -35,7 +39,7 @@
 	$(hide) touch $@
 
 ifneq ($(PRODUCT_CHECK_ELF_FILES)$(CHECK_ELF_FILES),)
-ifneq ($(LOCAL_CHECK_ELF_FILES),false)
+ifneq ($(strip $(LOCAL_CHECK_ELF_FILES)),false)
 $(LOCAL_BUILT_MODULE): $(check_elf_files_stamp)
 check-elf-files: $(check_elf_files_stamp)
 endif  # LOCAL_CHECK_ELF_FILES
diff --git a/core/clang/HOST_CROSS_x86.mk b/core/clang/HOST_CROSS_x86.mk
deleted file mode 100644
index 7581353..0000000
--- a/core/clang/HOST_CROSS_x86.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-$(clang_2nd_arch_prefix)HOST_CROSS_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i386.a
-$(clang_2nd_arch_prefix)HOST_CROSS_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.bulitins-i386.a
diff --git a/core/clang/HOST_CROSS_x86_64.mk b/core/clang/HOST_CROSS_x86_64.mk
deleted file mode 100644
index 9a971c7..0000000
--- a/core/clang/HOST_CROSS_x86_64.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-$(clang_2nd_arch_prefix)HOST_CROSS_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-x86_64.a
-$(clang_2nd_arch_prefix)HOST_CROSS_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.builtins-x86_64.a
diff --git a/core/clang/TARGET_arm.mk b/core/clang/TARGET_arm.mk
index 6140d7c..f18747a 100644
--- a/core/clang/TARGET_arm.mk
+++ b/core/clang/TARGET_arm.mk
@@ -7,3 +7,4 @@
 
 # Address sanitizer clang config
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
+$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan
diff --git a/core/clang/TARGET_arm64.mk b/core/clang/TARGET_arm64.mk
index 9fe5530..42bed0a 100644
--- a/core/clang/TARGET_arm64.mk
+++ b/core/clang/TARGET_arm64.mk
@@ -7,3 +7,4 @@
 
 # Address sanitizer clang config
 ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
+ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64
diff --git a/core/clang/TARGET_mips.mk b/core/clang/TARGET_mips.mk
index dfd99b2..3e54a66 100644
--- a/core/clang/TARGET_mips.mk
+++ b/core/clang/TARGET_mips.mk
@@ -6,3 +6,4 @@
 
 # Address sanitizer clang config
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
+$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan
diff --git a/core/clang/TARGET_mips64.mk b/core/clang/TARGET_mips64.mk
index a3684cc..cb6a3cd 100644
--- a/core/clang/TARGET_mips64.mk
+++ b/core/clang/TARGET_mips64.mk
@@ -6,3 +6,4 @@
 
 # Address sanitizer clang config
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
+$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64
diff --git a/core/clang/TARGET_x86.mk b/core/clang/TARGET_x86.mk
index 5e2d57e..5491a05 100644
--- a/core/clang/TARGET_x86.mk
+++ b/core/clang/TARGET_x86.mk
@@ -7,3 +7,4 @@
 
 # Address sanitizer clang config
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
+$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan
diff --git a/core/clang/TARGET_x86_64.mk b/core/clang/TARGET_x86_64.mk
index 86b3798..167db72 100644
--- a/core/clang/TARGET_x86_64.mk
+++ b/core/clang/TARGET_x86_64.mk
@@ -7,3 +7,4 @@
 
 # Address sanitizer clang config
 ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
+ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64
diff --git a/core/clang/config.mk b/core/clang/config.mk
index 063fd34..28a75ec 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -44,15 +44,6 @@
 include $(BUILD_SYSTEM)/clang/HOST_$(HOST_2ND_ARCH).mk
 endif
 
-ifdef HOST_CROSS_ARCH
-clang_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/clang/HOST_CROSS_$(HOST_CROSS_ARCH).mk
-ifdef HOST_CROSS_2ND_ARCH
-clang_2nd_arch_prefix := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/clang/HOST_CROSS_$(HOST_CROSS_2ND_ARCH).mk
-endif
-endif
-
 # TARGET config
 clang_2nd_arch_prefix :=
 include $(BUILD_SYSTEM)/clang/TARGET_$(TARGET_ARCH).mk
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 0f1a937..d67c9f8 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -55,7 +55,6 @@
 LOCAL_DEX_PREOPT_APP_IMAGE:=
 LOCAL_DEX_PREOPT_FLAGS:=
 LOCAL_DEX_PREOPT_GENERATE_PROFILE:=
-LOCAL_DEX_PREOPT_IMAGE_LOCATION:=
 LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING:=
 LOCAL_DEX_PREOPT:= # '',true,false,nostripping
 LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG:=
@@ -160,7 +159,6 @@
 LOCAL_MODULE_HOST_ARCH:=
 LOCAL_MODULE_HOST_ARCH_WARN:=
 LOCAL_MODULE_HOST_CROSS_ARCH:=
-LOCAL_MODULE_HOST_CROSS_ARCH_WARN:=
 LOCAL_MODULE_HOST_OS:=
 LOCAL_MODULE_OWNER:=
 LOCAL_MODULE_PATH:=
@@ -173,8 +171,6 @@
 LOCAL_MODULE_TARGET_ARCH_WARN:=
 LOCAL_MODULE_UNSUPPORTED_HOST_ARCH:=
 LOCAL_MODULE_UNSUPPORTED_HOST_ARCH_WARN:=
-LOCAL_MODULE_UNSUPPORTED_HOST_CROSS_ARCH:=
-LOCAL_MODULE_UNSUPPORTED_HOST_CROSS_ARCH_WARN:=
 LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH:=
 LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN:=
 LOCAL_MULTILIB:=
@@ -214,6 +210,7 @@
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
 LOCAL_PREBUILT_STRIP_COMMENTS:=
 LOCAL_USE_EMBEDDED_DEX:=
+LOCAL_USE_EMBEDDED_NATIVE_LIBS:=
 LOCAL_PRESUBMIT_DISABLED:=
 LOCAL_PRIVATE_PLATFORM_APIS:=
 LOCAL_PRIVILEGED_MODULE:=
@@ -225,7 +222,7 @@
 LOCAL_PROGUARD_FLAGS:=
 LOCAL_PROPRIETARY_MODULE:=
 LOCAL_PROTOC_FLAGS:=
-# lite(default),micro,nano,stream,full,nanopb-c,nanopb-c-enable_malloc
+# lite(default),micro,nano,stream,full,nanopb-c,nanopb-c-enable_malloc,nanopb-c-16bit,nanopb-c-enable_malloc-16bit,nanopb-c-32bit,nanopb-c-enable_malloc-32bit
 LOCAL_PROTOC_OPTIMIZE_TYPE:=
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS:=
 LOCAL_R8_FLAG_FILES:=
@@ -266,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
@@ -298,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:=
@@ -408,31 +408,10 @@
 LOCAL_SRC_FILES_$(HOST_OS):=
 LOCAL_STATIC_LIBRARIES_$(HOST_OS):=
 
-ifdef HOST_CROSS_OS
-LOCAL_ASFLAGS_$(HOST_CROSS_OS):=
-LOCAL_CFLAGS_$(HOST_CROSS_OS):=
-LOCAL_C_INCLUDES_$(HOST_CROSS_OS):=
-LOCAL_CPPFLAGS_$(HOST_CROSS_OS):=
-LOCAL_GENERATED_SOURCES_$(HOST_CROSS_OS):=
-LOCAL_HEADER_LIBRARIES_$(HOST_CROSS_OS):=
-LOCAL_LDFLAGS_$(HOST_CROSS_OS):=
-LOCAL_LDLIBS_$(HOST_CROSS_OS):=
-LOCAL_REQUIRED_MODULES_$(HOST_CROSS_OS):=
-LOCAL_SHARED_LIBRARIES_$(HOST_CROSS_OS):=
-LOCAL_SRC_FILES_$(HOST_CROSS_OS):=
-LOCAL_STATIC_LIBRARIES_$(HOST_CROSS_OS):=
-endif
-
 LOCAL_SRC_FILES_$(HOST_OS)_$(HOST_ARCH):=
 ifdef HOST_2ND_ARCH
 LOCAL_SRC_FILES_$(HOST_OS)_$(HOST_2ND_ARCH):=
 endif
-ifdef HOST_CROSS_OS
-LOCAL_SRC_FILES_$(HOST_CROSS_OS)_$(HOST_CROSS_ARCH):=
-ifdef HOST_CROSS_2ND_ARCH
-LOCAL_SRC_FILES_$(HOST_CROSS_OS)_$(HOST_CROSS_2ND_ARCH):=
-endif
-endif
 
 LOCAL_ASFLAGS_32:=
 LOCAL_ASFLAGS_64:=
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 9514edb..cbca1fb 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -29,45 +29,38 @@
 # include defines, and compiler settings for the given architecture
 # version.
 #
-ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)),)
-TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT := generic
-endif
 
 KNOWN_ARMv8_CORES := cortex-a53 cortex-a53.a57 cortex-a55 cortex-a73 cortex-a75 cortex-a76
 KNOWN_ARMv8_CORES += kryo kryo385 exynos-m1 exynos-m2
 
 KNOWN_ARMv82a_CORES := cortex-a55 cortex-a75 kryo385
 
-# Check for cores that implement armv8-2a ISAs.
+ifeq (,$(strip $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)))
+  TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT := generic
+endif
+
+# This sanity checks TARGET_2ND_ARCH_VARIANT against the lists above.
 ifneq (,$(filter $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT), $(KNOWN_ARMv82a_CORES)))
-  ifneq ($(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT),armv8-2a)
-    $(warning $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT) is armv8-2a.)
-    ifneq (,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
-      $(warning TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT, $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT), ignored! Use armv8-2a instead.)
-    endif
-    # Overwrite TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT
+  ifeq (,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
     TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := armv8-2a
+  else ifneq (armv8-2a,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
+    $(error Incorrect TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT, $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT). Use armv8-2a instead.)
   endif
-# Many devices (incorrectly) use armv7-a-neon as the 2nd architecture variant
-# for cores that implement armv8-a ISAs. The following sets it to armv8-a.
 else ifneq (,$(filter $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT), $(KNOWN_ARMv8_CORES)))
-  ifneq ($(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT),armv8-a)
-    $(warning $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT) is armv8-a.)
-    ifneq (,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
-      $(warning TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT, $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT), ignored! Use armv8-a instead.)
-    endif
-    # Overwrite TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT
+  ifeq (,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
     TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := armv8-a
+  else ifneq ($(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT),armv8-a)
+    $(error Incorrect TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT, $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT). Use armv8-a instead.)
   endif
 endif
 
 ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT)),)
-$(error TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT must be set)
+  $(error TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT must be set)
 endif
 
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_$(combo_2nd_arch_prefix)ARCH)/$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
-$(error Unknown ARM architecture version: $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
+  $(error Unknown ARM architecture version: $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
 endif
 
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
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/stoneyridge.mk b/core/combo/arch/x86/stoneyridge.mk
new file mode 100644
index 0000000..30405a1
--- /dev/null
+++ b/core/combo/arch/x86/stoneyridge.mk
@@ -0,0 +1,12 @@
+# Configuration for Linux on x86.
+# Generating binaries for Stoney Ridge processors.
+#
+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_AES_NI := 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/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/stoneyridge.mk b/core/combo/arch/x86_64/stoneyridge.mk
new file mode 100644
index 0000000..f7d9583
--- /dev/null
+++ b/core/combo/arch/x86_64/stoneyridge.mk
@@ -0,0 +1,12 @@
+# Configuration for Linux on x86_64.
+# Generating binaries for Stoney Ridge processors.
+#
+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_AES_NI := 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/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 ab0ec6d..2e3e31f 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -34,6 +34,7 @@
 
 # Mark variables deprecated/obsolete
 CHANGES_URL := https://android.googlesource.com/platform/build/+/master/Changes.md
+.KATI_READONLY := CHANGES_URL
 $(KATI_obsolete_var PATH,Do not use PATH directly. See $(CHANGES_URL)#PATH)
 $(KATI_obsolete_var PYTHONPATH,Do not use PYTHONPATH directly. See $(CHANGES_URL)#PYTHONPATH)
 $(KATI_obsolete_var OUT,Use OUT_DIR instead. See $(CHANGES_URL)#OUT)
@@ -90,13 +91,12 @@
   GLOBAL_CFLAGS_NO_OVERRIDE GLOBAL_CPPFLAGS_NO_OVERRIDE \
   ,GCC support has been removed. Use Clang instead)
 $(KATI_obsolete_var DIST_DIR dist_goal,Use dist-for-goals instead. See $(CHANGES_URL)#dist)
+$(KATI_obsolete_var TARGET_ANDROID_FILESYSTEM_CONFIG_H,Use TARGET_FS_CONFIG_GEN instead)
 $(KATI_deprecated_var USER,Use BUILD_USERNAME instead. See $(CHANGES_URL)#USER)
 
 # This is marked as obsolete in envsetup.mk after reading the BoardConfig.mk
 $(KATI_deprecate_export It is a global setting. See $(CHANGES_URL)#export_keyword)
 
-CHANGES_URL :=
-
 # Used to force goals to build.  Only use for conditionally defined goals.
 .PHONY: FORCE
 FORCE:
@@ -207,19 +207,6 @@
 JAVA_TMPDIR_ARG :=
 endif
 
-# A list of the jars that provide information about usages of the hidden API.
-# The core-oj-hiddenapi provides information for the core-oj jar.
-HIDDENAPI_EXTRA_APP_USAGE_JARS := \
-    core-oj-hiddenapi \
-
-# ###############################################################
-# Broken build defaults
-# ###############################################################
-BUILD_BROKEN_ANDROIDMK_EXPORTS :=
-BUILD_BROKEN_DUP_COPY_HEADERS :=
-BUILD_BROKEN_DUP_RULES :=
-BUILD_BROKEN_PHONY_TARGETS :=
-
 # ###############################################################
 # Include sub-configuration files
 # ###############################################################
@@ -300,17 +287,7 @@
 TARGET_PRODUCT_KERNEL_HEADERS := $(strip $(wildcard $(PRODUCT_VENDOR_KERNEL_HEADERS)))
 TARGET_PRODUCT_KERNEL_HEADERS := $(patsubst %/,%,$(TARGET_PRODUCT_KERNEL_HEADERS))
 $(call validate-kernel-headers,$(TARGET_PRODUCT_KERNEL_HEADERS))
-
-# Clean up/verify variables defined by the board config file.
-TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))
-TARGET_CPU_ABI := $(strip $(TARGET_CPU_ABI))
-ifeq ($(TARGET_CPU_ABI),)
-  $(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
-endif
-TARGET_CPU_ABI2 := $(strip $(TARGET_CPU_ABI2))
-
-BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
-BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
+.KATI_READONLY := TARGET_DEVICE_KERNEL_HEADERS TARGET_BOARD_KERNEL_HEADERS TARGET_PRODUCT_KERNEL_HEADERS
 
 # Commands to generate .toc file common to ELF .so files.
 define _gen_toc_command_for_elf
@@ -324,44 +301,6 @@
 $(hide) $(HOST_NM) -gP $(1) | cut -f1-2 -d" " | (grep -v U$$ >> $(2) || true)
 endef
 
-combo_target := HOST_
-combo_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/combo/select.mk
-
-# Load the 2nd host arch if it's needed.
-ifdef HOST_2ND_ARCH
-combo_target := HOST_
-combo_2nd_arch_prefix := $(HOST_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/combo/select.mk
-endif
-
-# Load the windows cross compiler under Linux
-ifdef HOST_CROSS_OS
-combo_target := HOST_CROSS_
-combo_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/combo/select.mk
-
-ifdef HOST_CROSS_2ND_ARCH
-combo_target := HOST_CROSS_
-combo_2nd_arch_prefix := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/combo/select.mk
-endif
-endif
-
-# on windows, the tools have .exe at the end, and we depend on the
-# host config stuff being done first
-
-combo_target := TARGET_
-combo_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/combo/select.mk
-
-# Load the 2nd target arch if it's needed.
-ifdef TARGET_2ND_ARCH
-combo_target := TARGET_
-combo_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/combo/select.mk
-endif
-
 ifeq ($(CALLED_FROM_SETUP),true)
 include $(BUILD_SYSTEM)/ccache.mk
 include $(BUILD_SYSTEM)/goma.mk
@@ -372,62 +311,6 @@
 TARGET_PREFER_32_BIT_EXECUTABLES := true
 endif
 
-ifeq (,$(filter true,$(TARGET_SUPPORTS_32_BIT_APPS) $(TARGET_SUPPORTS_64_BIT_APPS)))
-  TARGET_SUPPORTS_32_BIT_APPS := true
-endif
-
-# Sanity check to warn about likely cryptic errors later in the build.
-ifeq ($(TARGET_IS_64_BIT),true)
-  ifeq (,$(filter true false,$(TARGET_SUPPORTS_64_BIT_APPS)))
-    $(warning Building a 32-bit-app-only product on a 64-bit device. \
-      If this is intentional, set TARGET_SUPPORTS_64_BIT_APPS := false)
-  endif
-endif
-
-# "ro.product.cpu.abilist32" and "ro.product.cpu.abilist64" are
-# comma separated lists of the 32 and 64 bit ABIs (in order of
-# preference) that the target supports. If TARGET_CPU_ABI_LIST_{32,64}_BIT
-# are defined by the board config, we use them. Else, we construct
-# these lists based on whether TARGET_IS_64_BIT is set.
-#
-# Note that this assumes that the 2ND_CPU_ABI for a 64 bit target
-# is always 32 bits. If this isn't the case, these variables should
-# be overriden in the board configuration.
-ifeq (,$(TARGET_CPU_ABI_LIST_64_BIT))
-  ifeq (true|true,$(TARGET_IS_64_BIT)|$(TARGET_SUPPORTS_64_BIT_APPS))
-    TARGET_CPU_ABI_LIST_64_BIT := $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2)
-  endif
-endif
-
-ifeq (,$(TARGET_CPU_ABI_LIST_32_BIT))
-  ifneq (true,$(TARGET_IS_64_BIT))
-    TARGET_CPU_ABI_LIST_32_BIT := $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2)
-  else
-    ifeq (true,$(TARGET_SUPPORTS_32_BIT_APPS))
-      # For a 64 bit target, assume that the 2ND_CPU_ABI
-      # is a 32 bit ABI.
-      TARGET_CPU_ABI_LIST_32_BIT := $(TARGET_2ND_CPU_ABI) $(TARGET_2ND_CPU_ABI2)
-    endif
-  endif
-endif
-
-# "ro.product.cpu.abilist" is a comma separated list of ABIs (in order
-# of preference) that the target supports. If a TARGET_CPU_ABI_LIST
-# is specified by the board configuration, we use that. If not, we
-# build a list out of the TARGET_CPU_ABIs specified by the config.
-ifeq (,$(TARGET_CPU_ABI_LIST))
-  ifeq ($(TARGET_IS_64_BIT)|$(TARGET_PREFER_32_BIT_APPS),true|true)
-    TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_32_BIT) $(TARGET_CPU_ABI_LIST_64_BIT)
-  else
-    TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_64_BIT) $(TARGET_CPU_ABI_LIST_32_BIT)
-  endif
-endif
-
-# Strip whitespace from the ABI list string.
-TARGET_CPU_ABI_LIST := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST)))
-TARGET_CPU_ABI_LIST_32_BIT := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST_32_BIT)))
-TARGET_CPU_ABI_LIST_64_BIT := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST_64_BIT)))
-
 # GCC version selection
 TARGET_GCC_VERSION := 4.9
 ifdef TARGET_2ND_ARCH
@@ -730,6 +613,8 @@
 
 JETIFIER := prebuilts/sdk/tools/jetifier/jetifier-standalone/bin/jetifier-standalone
 
+EXTRACT_KERNEL := build/make/tools/extract_kernel.py
+
 COLUMN:= column
 
 USE_OPENJDK9 := true
@@ -881,6 +766,7 @@
 else
   DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
 endif
+.KATI_READONLY := DEFAULT_SYSTEM_DEV_CERTIFICATE
 
 BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
 BUILD_DATETIME_FROM_FILE := $$(cat $(BUILD_DATETIME_FILE))
@@ -947,16 +833,21 @@
 endif
 
 ifeq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
-    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 :=
+    ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+        $(error BOARD_BUILD_SYSTEM_ROOT_IMAGE cannot be true for devices with dynamic partitions)
+    endif
+    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),)
@@ -996,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.
@@ -1007,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
@@ -1034,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)
 
@@ -1053,7 +952,7 @@
 endif
 
 # The metadata device must be supplied to init via the kernel command-line.
-BOARD_KERNEL_CMDLINE += androidboot.super_partition=$(BOARD_SUPER_PARTITION_METADATA_DEVICE)
+INTERNAL_KERNEL_CMDLINE += androidboot.super_partition=$(BOARD_SUPER_PARTITION_METADATA_DEVICE)
 
 BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE := true
 
@@ -1087,7 +986,7 @@
 endif
 
 ifneq ($(BOARD_SUPER_PARTITION_METADATA_DEVICE),super)
-BOARD_KERNEL_CMDLINE += androidboot.super_partition=$(BOARD_SUPER_PARTITION_METADATA_DEVICE)
+INTERNAL_KERNEL_CMDLINE += androidboot.super_partition=$(BOARD_SUPER_PARTITION_METADATA_DEVICE)
 endif
 BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE :=
 
@@ -1133,11 +1032,13 @@
 first_non_empty_of_three = $(if $(1),$(1),$(if $(2),$(2),$(3)))
 DEX2OAT_TARGET_ARCH := $(TARGET_ARCH)
 DEX2OAT_TARGET_CPU_VARIANT := $(call first_non_empty_of_three,$(TARGET_CPU_VARIANT),$(TARGET_ARCH_VARIANT),default)
+DEX2OAT_TARGET_CPU_VARIANT_RUNTIME := $(call first_non_empty_of_three,$(TARGET_CPU_VARIANT_RUNTIME),$(TARGET_ARCH_VARIANT),default)
 DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES := default
 
 ifdef TARGET_2ND_ARCH
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH := $(TARGET_2ND_ARCH)
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT := $(call first_non_empty_of_three,$(TARGET_2ND_CPU_VARIANT),$(TARGET_2ND_ARCH_VARIANT),default)
+$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME := $(call first_non_empty_of_three,$(TARGET_2ND_CPU_VARIANT_RUNTIME),$(TARGET_2ND_ARCH_VARIANT),default)
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES := default
 endif
 
@@ -1222,10 +1123,6 @@
 INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-private-dex.txt
 endif
 
-INTERNAL_PLATFORM_HIDDENAPI_FLAGS := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-flags.csv
-INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-stub-flags.txt
-INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-greylist.csv
-
 # Missing optional uses-libraries so that the platform doesn't create build rules that depend on
 # them. See setup_one_odex.mk.
 INTERNAL_PLATFORM_MISSING_USES_LIBRARIES := com.google.android.ble com.google.android.wearable
@@ -1286,4 +1183,9 @@
 include $(BUILD_SYSTEM)/soong_config.mk
 endif
 
+-include external/linux-kselftest/android/kselftest_test_list.mk
+-include external/ltp/android/ltp_package_list.mk
+DEFAULT_DATA_OUT_MODULES := ltp $(ltp_packages) $(kselftest_modules)
+.KATI_READONLY := DEFAULT_DATA_OUT_MODULES
+
 include $(BUILD_SYSTEM)/dumpvar.mk
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 6c9caa8..d3adee5 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -112,7 +112,6 @@
     ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_include_paths)),\
            $(filter $(dir)%,$(LOCAL_PATH)))),)
       my_sanitize := cfi $(my_sanitize)
-      my_sanitize_diag := cfi $(my_sanitize_diag)
     endif
   endif
 endif
@@ -213,6 +212,11 @@
   my_sanitize := $(filter-out scudo,$(my_sanitize))
 endif
 
+# Or if disabled globally.
+ifeq ($(PRODUCT_DISABLE_SCUDO),true)
+  my_sanitize := $(filter-out scudo,$(my_sanitize))
+endif
+
 # Undefined symbols can occur if a non-sanitized library links
 # sanitized static libraries. That's OK, because the executable
 # always depends on the ASan runtime library, which defines these
@@ -341,7 +345,7 @@
       ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
         my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
         # Make sure linker_asan get installed.
-        $(LOCAL_INSTALLED_MODULE) : | $(PRODUCT_OUT)$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
+        $(LOCAL_INSTALLED_MODULE) : | $(PRODUCT_OUT)$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER_FILE)
       endif
     endif
   endif
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index 25fd642..7d3ca5c 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -13,10 +13,6 @@
             ifneq (,$(BUILD_HOST_static))
                 my_cxx_stl := libc++_static
             endif
-
-            ifeq ($($(my_prefix)OS),windows)
-                my_cxx_stl := libc++_static
-            endif
         endif
     else
         my_cxx_stl := ndk
@@ -35,14 +31,6 @@
         # the two options use different names for the STLs.
         $(error $(LOCAL_PATH): $(LOCAL_MODULE): Must use LOCAL_NDK_STL_VARIANT rather than LOCAL_CXX_STL for NDK binaries)
     endif
-    ifdef LOCAL_IS_HOST_MODULE
-        ifeq ($($(my_prefix)OS),windows)
-            ifneq ($(filter $(my_cxx_stl),libc++),)
-                # only libc++_static is supported on mingw.
-                my_cxx_stl := libc++_static
-            endif
-        endif
-    endif
 endif
 
 # Yes, this is actually what the clang driver does.
@@ -50,11 +38,6 @@
 linux_static_gcclibs := -Wl,--start-group -lgcc -lgcc_eh -lc -Wl,--end-group
 darwin_dynamic_gcclibs := -lc -lSystem
 darwin_static_gcclibs := NO_STATIC_HOST_BINARIES_ON_DARWIN
-windows_dynamic_gcclibs := \
-    -Wl,--start-group -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex \
-    -lmsvcrt -lucrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lpsapi \
-    -Wl,--end-group
-windows_static_gcclibs := NO_STATIC_HOST_BINARIES_ON_WINDOWS
 
 my_link_type := dynamic
 ifdef LOCAL_IS_HOST_MODULE
@@ -100,20 +83,6 @@
         my_cppflags += -nostdinc++
         my_ldflags += -nodefaultlibs
         my_cxx_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
-
-        ifeq ($($(my_prefix)OS),windows)
-            # Use SjLj exceptions for 32-bit.  libgcc_eh implements SjLj
-            # exception model for 32-bit.
-            ifeq (x86,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
-                my_cppflags += -fsjlj-exceptions
-            endif
-            # Disable visibility annotations since we're using libc++ static
-            # library.
-            my_cppflags += -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
-            my_cppflags += -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS
-            # Use Win32 threads in libc++.
-            my_cppflags += -D_LIBCPP_HAS_THREAD_API_WIN32
-        endif
     else
         ifeq (arm,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
             my_static_libraries += libunwind_llvm
diff --git a/core/definitions.mk b/core/definitions.mk
index 9cec110..205a055 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
@@ -2195,13 +2207,37 @@
 $(if $(filter $(1),$(PLATFORM_VERSION_CODENAME)),10000,$(1))
 endef
 
+# Uses LOCAL_SDK_VERSION and PLATFORM_SDK_VERSION to determine a compileSdkVersion
+# in the form of a number or a codename (28 or P)
+define module-sdk-version
+$(strip \
+  $(if $(filter-out current system_current test_current core_current,$(LOCAL_SDK_VERSION)), \
+    $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION)), \
+    $(PLATFORM_SDK_VERSION)))
+endef
+
+# Uses LOCAL_SDK_VERSION and DEFAULT_APP_TARGET_SDK to determine
+# a targetSdkVersion in the form of a number or a codename (28 or P).
+define module-target-sdk-version
+$(strip \
+  $(if $(filter-out current system_current test_current core_current,$(LOCAL_SDK_VERSION)), \
+    $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION)), \
+    $(DEFAULT_APP_TARGET_SDK)))
+endef
+
+# Uses LOCAL_MIN_SDK_VERSION, LOCAL_SDK_VERSION and DEFAULT_APP_TARGET_SDK to determine
+# a minSdkVersion in the form of a number or a codename (28 or P).
+define module-min-sdk-version
+$(if $(LOCAL_MIN_SDK_VERSION),$(LOCAL_MIN_SDK_VERSION),$(call module-target-sdk-version))
+endef
+
 
 define transform-classes.jar-to-dex
 @echo "target Dex: $(PRIVATE_MODULE)"
 @mkdir -p $(dir $@)
 $(hide) rm -f $(dir $@)classes*.dex $(dir $@)d8_input.jar
 $(hide) $(ZIP2ZIP) -j -i $< -o $(dir $@)d8_input.jar "**/*.class"
-$(hide) $(DX_COMMAND) \
+$(hide) $(DX_COMMAND) $(DEX_FLAGS) \
     --output $(dir $@) \
     $(addprefix --lib ,$(PRIVATE_D8_LIBS)) \
     --min-api $(PRIVATE_MIN_SDK_VERSION) \
@@ -2251,24 +2287,15 @@
 
 endef
 
-# For apps_only build, don't uncompress/page-align the jni libraries,
-# because the apk may be run on older platforms that don't support loading jni directly from apk.
-ifdef TARGET_BUILD_APPS
-JNI_COMPRESS_FLAGS :=
-ZIPALIGN_PAGE_ALIGN_FLAGS :=
-else
-JNI_COMPRESS_FLAGS := -L 0
-ZIPALIGN_PAGE_ALIGN_FLAGS := -p
-endif
-
 # $(1): the package file
+# $(2): if true, uncompress jni libs
 define create-jni-shared-libs-package
 rm -rf $(dir $(1))lib
 mkdir -p $(addprefix $(dir $(1))lib/,$(PRIVATE_JNI_SHARED_LIBRARIES_ABI))
 $(foreach abi,$(PRIVATE_JNI_SHARED_LIBRARIES_ABI),\
   $(call _add-jni-shared-libs-to-package-per-abi,$(1),$(abi),\
     $(patsubst $(abi):%,%,$(filter $(abi):%,$(PRIVATE_JNI_SHARED_LIBRARIES)))))
-$(SOONG_ZIP) $(JNI_COMPRESS_FLAGS) -o $(1) -C $(dir $(1)) -D $(dir $(1))lib
+$(SOONG_ZIP) $(if $(2),-L 0) -o $(1) -C $(dir $(1)) -D $(dir $(1))lib
 rm -rf $(dir $(1))lib
 endef
 
@@ -2336,7 +2363,7 @@
   mv $@ $@.unaligned; \
   $(ZIPALIGN) \
     -f \
-    $(ZIPALIGN_PAGE_ALIGN_FLAGS) \
+    -p \
     4 \
     $@.unaligned $@.aligned; \
   mv $@.aligned $@; \
@@ -2373,7 +2400,7 @@
 define run-appcompat
 $(hide) \
   echo "appcompat.sh output:" >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log && \
-  PACKAGING=$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING ANDROID_LOG_TAGS="*:e" art/tools/veridex/appcompat.sh --dex-file=$@ 2>&1 >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log
+  PACKAGING=$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING ANDROID_LOG_TAGS="*:e" art/tools/veridex/appcompat.sh --dex-file=$@ --api-flags=$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS) 2>&1 >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log
 endef
 appcompat-files = \
   art/tools/veridex/appcompat.sh \
@@ -2463,14 +2490,36 @@
 	$$(align-package)
 endef
 
+# Create copy pair for compatibility suite
+# Filter out $(LOCAL_INSTALLED_MODULE) to prevent overriding target
+# $(1): source path
+# $(2): destination path
+# The format of copy pair is src:dst
+define compat-copy-pair
+$(if $(filter-out $(2), $(LOCAL_INSTALLED_MODULE)), $(1):$(2))
+endef
+
+# Create copy pair for $(1) $(2)
+# If $(2) is substring of $(3) do nothing.
+# $(1): source path
+# $(2): destination path
+# $(3): filter-out target
+# The format of copy pair is src:dst
+define filter-copy-pair
+$(if $(findstring $(2), $(3)),,$(1):$(2))
+endef
+
 # Copies many files.
 # $(1): The files to copy.  Each entry is a ':' separated src:dst pair
+# $(2): An optional directory to prepend to the destination
 # Evaluates to the list of the dst files (ie suitable for a dependency list)
 define copy-many-files
 $(foreach f, $(1), $(strip \
     $(eval _cmf_tuple := $(subst :, ,$(f))) \
     $(eval _cmf_src := $(word 1,$(_cmf_tuple))) \
     $(eval _cmf_dest := $(word 2,$(_cmf_tuple))) \
+    $(if $(strip $(2)), \
+      $(eval _cmf_dest := $(patsubst %/,%,$(strip $(2)))/$(patsubst /%,%,$(_cmf_dest)))) \
     $(if $(filter-out $(_cmf_src), $(_cmf_dest)), \
       $(eval $(call copy-one-file,$(_cmf_src),$(_cmf_dest)))) \
     $(_cmf_dest)))
@@ -2664,56 +2713,6 @@
 fi
 endef
 
-# Copy dex files, invoking $(HIDDENAPI) on them in the process.
-# Also make the source dex file an input of the hiddenapi singleton rule in dex_preopt.mk.
-# Users can set UNSAFE_DISABLE_HIDDENAPI_FLAGS=true to skip this step. This is
-# meant to speed up local incremental builds. Note that skipping this step changes
-# Java semantics of the result dex bytecode. Use at own risk.
-ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
-define hiddenapi-copy-dex-files
-$(2): $(1) $(HIDDENAPI) $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS)
-	@rm -rf $(dir $(2))
-	@mkdir -p $(dir $(2))
-	for INPUT_DEX in `find $(dir $(1)) -maxdepth 1 -name "classes*.dex" | sort`; do \
-	    echo "--input-dex=$$$${INPUT_DEX}"; \
-	    echo "--output-dex=$(dir $(2))/`basename $$$${INPUT_DEX}`"; \
-	done | xargs $(HIDDENAPI) encode --api-flags=$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS)
-
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): $(1)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): PRIVATE_DEX_INPUTS := $$(PRIVATE_DEX_INPUTS) $(1)
-endef
-else  # UNSAFE_DISABLE_HIDDENAPI_FLAGS
-define hiddenapi-copy-dex-files
-$(2): $(1)
-	echo "WARNING: skipping hiddenapi post-processing for $(1)" 1>&2
-	@rm -rf $(dir $(2))
-	@mkdir -p $(dir $(2))
-	find $(dir $(1)) -maxdepth 1 -name "classes*.dex" | xargs -I{} cp -f {} $(dir $(2))/
-endef
-endif  # UNSAFE_DISABLE_HIDDENAPI_FLAGS
-
-# Generate a greylist.txt from a classes.jar
-define hiddenapi-generate-csv
-ifneq (,$(wildcard frameworks/base))
-# Only generate this target if we're in a tree with frameworks/base present.
-$(2): $(1) $(CLASS2GREYLIST) $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS)
-	$(CLASS2GREYLIST) --stub-api-flags $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS) $(1) \
-	    --write-flags-csv $(2)
-
-$(3): $(1) $(CLASS2GREYLIST) $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS)
-	$(CLASS2GREYLIST) --stub-api-flags $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS) $(1) \
-	    --write-metadata-csv $(3)
-
-$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): $(2)
-$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): PRIVATE_FLAGS_INPUTS := $$(PRIVATE_FLAGS_INPUTS) $(2)
-
-$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): $(3)
-$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): \
-    PRIVATE_METADATA_INPUTS := $$(PRIVATE_METADATA_INPUTS) $(3)
-
-endif
-endef
-
 
 ###########################################################
 ## Commands to call R8
@@ -2729,7 +2728,8 @@
 define transform-jar-to-dex-r8
 @echo R8: $@
 $(hide) rm -f $(PRIVATE_PROGUARD_DICTIONARY)
-$(hide) $(R8_COMPAT_PROGUARD) -injars '$<' \
+$(hide) $(R8_COMPAT_PROGUARD) $(DEX_FLAGS) \
+    -injars '$<' \
     --min-api $(PRIVATE_MIN_SDK_VERSION) \
     --no-data-resources \
     --force-proguard-compatibility --output $(subst classes.dex,,$@) \
@@ -3312,10 +3312,12 @@
 #  $(4): Whether LOCAL_EXPORT_PACKAGE_RESOURCES is set or
 #        not for the source module.
 #  $(5): Resource overlay list.
+#  $(6): Target partition
 ###########################################################
 define append_enforce_rro_sources
   $(eval ENFORCE_RRO_SOURCES += \
-      $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||$(call normalize-path-list, $(strip $(5))))
+      $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||$(call normalize-path-list, $(strip $(5)))||$(strip $(6)) \
+  )
 endef
 
 ###########################################################
@@ -3330,9 +3332,9 @@
   $(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 enforce_rro_partition := $(word 6,$(_o))) \
   $(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
 
@@ -3399,3 +3401,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/dex_preopt.mk b/core/dex_preopt.mk
index f102662..d43158e 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -13,95 +13,24 @@
 install-on-system-other = $(filter-out $(PRODUCT_DEXPREOPT_SPEED_APPS) $(PRODUCT_SYSTEM_SERVER_APPS),$(basename $(notdir $(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(1)))))
 endif
 
-# Special rules for building stripped boot jars that override java_library.mk rules
+# Install boot images. Note that there can be multiple.
+DEFAULT_DEX_PREOPT_INSTALLED_IMAGE :=
+$(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE :=
+$(foreach my_boot_image_name,$(DEXPREOPT_IMAGE_NAMES),$(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk))
 
-# $(1): boot jar module name
-define _dexpreopt-boot-jar-remove-classes.dex
-_dbj_jar_no_dex := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(1)_nodex.jar
-_dbj_src_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,$(1),,COMMON)/javalib.jar
+boot_profile_jars_zip := $(PRODUCT_OUT)/boot_profile_jars.zip
+bootclasspath_jars := $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
+system_server_jars := $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(PRODUCT_OUT)/system/framework/$(m).jar)
 
-$(call dexpreopt-copy-jar,$$(_dbj_src_jar),$$(_dbj_jar_no_dex),$(filter-out nostripping,$(DEX_PREOPT_DEFAULT)))
-
-_dbj_jar_no_dex :=
-_dbj_src_jar :=
-endef
-
-$(foreach b,$(DEXPREOPT_BOOT_JARS_MODULES),$(eval $(call _dexpreopt-boot-jar-remove-classes.dex,$(b))))
-
-include $(BUILD_SYSTEM)/dex_preopt_libart.mk
-
-# === hiddenapi rules ===
-
-hiddenapi_stubs_jar = $(call intermediates-dir-for,JAVA_LIBRARIES,$(1),,COMMON)/javalib.jar
-
-# Public API stubs
-HIDDENAPI_STUBS := \
-    $(call hiddenapi_stubs_jar,android_stubs_current) \
-    $(call hiddenapi_stubs_jar,android.test.base.stubs)
-
-# System API stubs
-HIDDENAPI_STUBS_SYSTEM := \
-    $(call hiddenapi_stubs_jar,android_system_stubs_current)
-
-# Test API stubs
-HIDDENAPI_STUBS_TEST := \
-    $(call hiddenapi_stubs_jar,android_test_stubs_current)
-
-# Core Platform API stubs
-HIDDENAPI_STUBS_CORE_PLATFORM := \
-    $(call hiddenapi_stubs_jar,core.platform.api.stubs)
-
-# Allow products to define their own stubs for custom product jars that apps can use.
-ifdef PRODUCT_HIDDENAPI_STUBS
-  HIDDENAPI_STUBS += $(foreach stub,$(PRODUCT_HIDDENAPI_STUBS), $(call hiddenapi_stubs_jar,$(stub)))
-endif
-
-ifdef PRODUCT_HIDDENAPI_STUBS_SYSTEM
-  HIDDENAPI_STUBS_SYSTEM += $(foreach stub,$(PRODUCT_HIDDENAPI_STUBS_SYSTEM), $(call hiddenapi_stubs_jar,$(stub)))
-endif
-
-ifdef PRODUCT_HIDDENAPI_STUBS_TEST
-  HIDDENAPI_STUBS_TEST += $(foreach stub,$(PRODUCT_HIDDENAPI_STUBS_TEST), $(call hiddenapi_stubs_jar,$(stub)))
-endif
-
-# Singleton rule which applies $(HIDDENAPI) on all boot class path dex files.
-# Additional inputs are filled with `hiddenapi-copy-dex-files` rules.
-.KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): $(SOONG_HIDDENAPI_DEX_INPUTS)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): PRIVATE_DEX_INPUTS := $(SOONG_HIDDENAPI_DEX_INPUTS)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): PRIVATE_HIDDENAPI_STUBS := $(HIDDENAPI_STUBS)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): PRIVATE_HIDDENAPI_STUBS_SYSTEM := $(HIDDENAPI_STUBS_SYSTEM)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): PRIVATE_HIDDENAPI_STUBS_TEST := $(HIDDENAPI_STUBS_TEST)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): PRIVATE_HIDDENAPI_STUBS_CORE_PLATFORM := $(HIDDENAPI_STUBS_CORE_PLATFORM)
-$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS): $(HIDDENAPI) $(HIDDENAPI_STUBS) \
-                                           $(HIDDENAPI_STUBS_SYSTEM) $(HIDDENAPI_STUBS_TEST) \
-                                           $(HIDDENAPI_STUBS_CORE_PLATFORM)
-	$(HIDDENAPI) list $(addprefix --boot-dex=,$(PRIVATE_DEX_INPUTS)) \
-	    --public-stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS)) \
-	    --public-stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS_SYSTEM)) \
-	    --public-stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS_TEST)) \
-	    --core-platform-stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS_CORE_PLATFORM)) \
-	    --out-api-flags=$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS).tmp
-	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS))
-
-# Inputs to singleton rules located in frameworks/base
-# Additional inputs are filled with `hiddenapi-generate-csv`
-$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): $(SOONG_HIDDENAPI_GREYLIST_METADATA)
-$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): PRIVATE_METADATA_INPUTS := $(SOONG_HIDDENAPI_GREYLIST_METADATA)
+$(boot_profile_jars_zip): PRIVATE_BOOTCLASSPATH_JARS := $(bootclasspath_jars)
+$(boot_profile_jars_zip): PRIVATE_SYSTEM_SERVER_JARS := $(system_server_jars)
+$(boot_profile_jars_zip): $(bootclasspath_jars) $(system_server_jars) $(SOONG_ZIP)
+	@echo "Create boot profiles package: $@"
+	rm -f $@
+	$(SOONG_ZIP) -o $@ \
+	  -C $(dir $(firstword $(PRIVATE_BOOTCLASSPATH_JARS)))/.. $(addprefix -f ,$(PRIVATE_BOOTCLASSPATH_JARS)) \
+	  -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_SYSTEM_SERVER_JARS))
 
 ifeq ($(PRODUCT_DIST_BOOT_AND_SYSTEM_JARS),true)
-boot_profile_jars_zip := $(PRODUCT_OUT)/boot_profile_jars.zip
-all_boot_jars := \
-  $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES) \
-  $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(PRODUCT_OUT)/system/framework/$(m).jar)
-
-$(boot_profile_jars_zip): PRIVATE_JARS := $(all_boot_jars)
-$(boot_profile_jars_zip): $(all_boot_jars) $(SOONG_ZIP)
-	echo "Create boot profiles package: $@"
-	rm -f $@
-	$(SOONG_ZIP) -o $@ -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_JARS))
-
-droidcore: $(boot_profile_jars_zip)
-
 $(call dist-for-goals, droidcore, $(boot_profile_jars_zip))
 endif
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 2dc187d..13e4634 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -1,37 +1,5 @@
 DEX_PREOPT_CONFIG := $(PRODUCT_OUT)/dexpreopt.config
 
-RUNTIME_MODULES := $(filter-out $(PRODUCT_UPDATABLE_BOOT_MODULES), $(TARGET_CORE_JARS))
-FRAMEWORK_MODULES := $(filter-out $(PRODUCT_UPDATABLE_BOOT_MODULES) $(RUNTIME_MODULES), $(PRODUCT_BOOT_JARS))
-
-NON_UPDATABLE_BOOT_MODULES := $(RUNTIME_MODULES) $(FRAMEWORK_MODULES)
-NON_UPDATABLE_BOOT_LOCATIONS := $(foreach m,$(RUNTIME_MODULES),/apex/com.android.runtime/javalib/$(m).jar)
-NON_UPDATABLE_BOOT_LOCATIONS += $(foreach m,$(FRAMEWORK_MODULES),/system/framework/$(m).jar)
-ALL_BOOT_LOCATIONS := $(NON_UPDATABLE_BOOT_LOCATIONS) $(PRODUCT_UPDATABLE_BOOT_LOCATIONS)
-ALL_BOOT_MODULES := $(NON_UPDATABLE_BOOT_MODULES) $(PRODUCT_UPDATABLE_BOOT_MODULES)
-
-PRODUCT_BOOTCLASSPATH := $(subst $(space),:,$(ALL_BOOT_LOCATIONS))
-
-DEXPREOPT_BOOT_JARS_MODULES := $(NON_UPDATABLE_BOOT_MODULES)
-DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS := $(NON_UPDATABLE_BOOT_LOCATIONS)
-DEXPREOPT_BOOT_JARS_INPUT_PATH := $(PRODUCT_OUT)/dex_bootjars_input
-DEXPREOPT_BOOTCLASSPATH_DEX_FILES := $(foreach m,$(NON_UPDATABLE_BOOT_MODULES),$(DEXPREOPT_BOOT_JARS_INPUT_PATH)/$(m).jar)
-
-# Create paths for boot image.
-DEXPREOPT_BUILD_DIR := $(OUT_DIR)
-DEXPREOPT_PRODUCT_DIR_FULL_PATH := $(PRODUCT_OUT)/dex_bootjars
-DEXPREOPT_PRODUCT_DIR := $(patsubst $(DEXPREOPT_BUILD_DIR)/%,%,$(DEXPREOPT_PRODUCT_DIR_FULL_PATH))
-DEXPREOPT_BOOT_JAR_DIR := system/framework
-DEXPREOPT_BOOT_JAR_DIR_FULL_PATH := $(DEXPREOPT_PRODUCT_DIR_FULL_PATH)/$(DEXPREOPT_BOOT_JAR_DIR)
-DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/boot.art
-DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(DEX2OAT_TARGET_ARCH)/boot.art
-
-ifdef TARGET_2ND_ARCH
-  $(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/boot.art
-  $(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)/boot.art
-endif
-
-PRODUCT_SYSTEM_SERVER_CLASSPATH := $(subst $(space),:,$(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),/system/framework/$(m).jar))
-
 # The default value for LOCAL_DEX_PREOPT
 DEX_PREOPT_DEFAULT ?= true
 
@@ -45,10 +13,13 @@
     product/app/% \
     product/priv-app/% \
 
-# The default values for pre-opting: always preopt PIC.
+# The default values for pre-opting. To support the runtime module we ensure no dex files
+# get stripped.
+ifeq ($(PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING),)
+  PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING := true
+endif
 # Conditional to building on linux, as dex2oat currently does not work on darwin.
 ifeq ($(HOST_OS),linux)
-  WITH_DEXPREOPT ?= true
   ifeq (eng,$(TARGET_BUILD_VARIANT))
     # Don't strip for quick development turnarounds.
     DEX_PREOPT_DEFAULT := nostripping
@@ -75,9 +46,9 @@
 # Default to debug version to help find bugs.
 # Set USE_DEX2OAT_DEBUG to false for only building non-debug versions.
 ifeq ($(USE_DEX2OAT_DEBUG),false)
-DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oat$(HOST_EXECUTABLE_SUFFIX)
+DEX2OAT := $(SOONG_HOST_OUT_EXECUTABLES)/dex2oat$(HOST_EXECUTABLE_SUFFIX)
 else
-DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
+DEX2OAT := $(SOONG_HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
 endif
 
 DEX2OAT_DEPENDENCY += $(DEX2OAT)
@@ -116,17 +87,20 @@
   $(call json_start)
 
   $(call add_json_bool, DefaultNoStripping,                 $(filter nostripping,$(DEX_PREOPT_DEFAULT)))
+  $(call add_json_bool, DisablePreopt,                      $(call invert_bool,$(filter true,$(WITH_DEXPREOPT))))
   $(call add_json_list, DisablePreoptModules,               $(DEXPREOPT_DISABLED_MODULES))
   $(call add_json_bool, OnlyPreoptBootImageAndSystemServer, $(filter true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY)))
+  $(call add_json_bool, GenerateApexImage,                  $(filter true,$(DEXPREOPT_GENERATE_APEX_IMAGE)))
   $(call add_json_bool, DontUncompressPrivAppsDex,          $(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS)))
   $(call add_json_list, ModulesLoadedByPrivilegedModules,   $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
-  $(call add_json_list, PreoptBootClassPathDexFiles,        $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES))
   $(call add_json_bool, HasSystemOther,                     $(BOARD_USES_SYSTEM_OTHER_ODEX))
   $(call add_json_list, PatternsOnSystemOther,              $(SYSTEM_OTHER_ODEX_FILTER))
   $(call add_json_bool, DisableGenerateProfile,             $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE)))
-  $(call add_json_list, PreoptBootClassPathDexLocations,    $(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
+  $(call add_json_str,  ProfileDir,                         $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
   $(call add_json_list, BootJars,                           $(PRODUCT_BOOT_JARS))
-  $(call add_json_list, PreoptBootJars,                     $(DEXPREOPT_BOOT_JARS_MODULES))
+  $(call add_json_list, RuntimeApexJars,                    $(RUNTIME_APEX_JARS))
+  $(call add_json_list, ProductUpdatableBootModules,        $(PRODUCT_UPDATABLE_BOOT_MODULES))
+  $(call add_json_list, ProductUpdatableBootLocations,      $(PRODUCT_UPDATABLE_BOOT_LOCATIONS))
   $(call add_json_list, SystemServerJars,                   $(PRODUCT_SYSTEM_SERVER_JARS))
   $(call add_json_list, SystemServerApps,                   $(PRODUCT_SYSTEM_SERVER_APPS))
   $(call add_json_list, SpeedApps,                          $(PRODUCT_DEXPREOPT_SPEED_APPS))
@@ -134,6 +108,7 @@
   $(call add_json_str,  DefaultCompilerFilter,              $(PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER))
   $(call add_json_str,  SystemServerCompilerFilter,         $(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
   $(call add_json_bool, GenerateDmFiles,                    $(PRODUCT_DEX_PREOPT_GENERATE_DM_FILES))
+  $(call add_json_bool, NeverAllowStripping,                $(PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING))
   $(call add_json_bool, NoDebugInfo,                        $(filter false,$(WITH_DEXPREOPT_DEBUG_INFO)))
   $(call add_json_bool, AlwaysSystemServerDebugInfo,        $(filter true,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO)))
   $(call add_json_bool, NeverSystemServerDebugInfo,         $(filter false,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO)))
@@ -147,13 +122,6 @@
   $(call add_json_str,  Dex2oatXms,                         $(DEX2OAT_XMS))
   $(call add_json_str,  EmptyDirectory,                     $(OUT_DIR)/empty)
 
-  $(call add_json_map,  DefaultDexPreoptImageLocation)
-  $(call add_json_str,  $(TARGET_ARCH), $(DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION))
-  ifdef TARGET_2ND_ARCH
-    $(call add_json_str, $(TARGET_2ND_ARCH), $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION))
-  endif
-  $(call end_json_map)
-
   $(call add_json_map,  CpuVariant)
   $(call add_json_str,  $(TARGET_ARCH), $(DEX2OAT_TARGET_CPU_VARIANT))
   ifdef TARGET_2ND_ARCH
@@ -168,10 +136,18 @@
   endif
   $(call end_json_map)
 
+  $(call add_json_str,  DirtyImageObjects,                  $(DIRTY_IMAGE_OBJECTS))
+  $(call add_json_str,  PreloadedClasses,                   $(PRELOADED_CLASSES))
+  $(call add_json_list, BootImageProfiles,                  $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
+  $(call add_json_bool, UseProfileForBootImage,             $(call invert_bool,$(filter false,$(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))))
+  $(call add_json_str,  BootFlags,                          $(PRODUCT_DEX_PREOPT_BOOT_FLAGS))
+  $(call add_json_str,  Dex2oatImageXmx,                    $(DEX2OAT_IMAGE_XMX))
+  $(call add_json_str,  Dex2oatImageXms,                    $(DEX2OAT_IMAGE_XMS))
+
   $(call add_json_map,  Tools)
-  $(call add_json_str,  Profman,                            $(PROFMAN))
+  $(call add_json_str,  Profman,                            $(SOONG_HOST_OUT_EXECUTABLES)/profman)
   $(call add_json_str,  Dex2oat,                            $(DEX2OAT))
-  $(call add_json_str,  Aapt,                               $(AAPT))
+  $(call add_json_str,  Aapt,                               $(SOONG_HOST_OUT_EXECUTABLES)/aapt)
   $(call add_json_str,  SoongZip,                           $(SOONG_ZIP))
   $(call add_json_str,  Zip2zip,                            $(ZIP2ZIP))
   $(call add_json_str,  VerifyUsesLibraries,                $(BUILD_SYSTEM)/verify_uses_libraries.sh)
@@ -198,20 +174,13 @@
 	@#empty
 
 DEXPREOPT_GEN_DEPS := \
-  $(PROFMAN) \
+  $(SOONG_HOST_OUT_EXECUTABLES)/profman \
   $(DEX2OAT) \
-  $(AAPT) \
+  $(SOONG_HOST_OUT_EXECUTABLES)/aapt \
   $(SOONG_ZIP) \
   $(ZIP2ZIP) \
   $(BUILD_SYSTEM)/verify_uses_libraries.sh \
   $(BUILD_SYSTEM)/construct_context.sh \
 
-DEXPREOPT_GEN_DEPS += $(DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME)
-ifdef TARGET_2ND_ARCH
-  ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-    DEXPREOPT_GEN_DEPS += $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME)
-  endif
-endif
-
 DEXPREOPT_STRIP_DEPS := \
   $(ZIP2ZIP) \
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index de7dcdd..edd82df 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -1,101 +1,54 @@
 ####################################
-# dexpreopt support for ART
+# ART boot image installation
+# Input variable:
+#   my_boot_image_name: the boot image to install
 #
 ####################################
 
-########################################################################
-# The full system boot classpath
-
-LIBART_TARGET_BOOT_JARS := $(DEXPREOPT_BOOT_JARS_MODULES)
-LIBART_TARGET_BOOT_DEX_LOCATIONS := $(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS)
-LIBART_TARGET_BOOT_DEX_FILES := $(foreach mod,$(NON_UPDATABLE_BOOT_MODULES),$(call intermediates-dir-for,JAVA_LIBRARIES,$(mod),,COMMON)/javalib.jar)
-
-# Copy the files to a location Soong dex preopt will look at.
-$(foreach mod,$(LIBART_TARGET_BOOT_JARS),$(eval $(call copy-one-file,$(call intermediates-dir-for,JAVA_LIBRARIES,$(mod),,COMMON)/javalib.jar,$(DEXPREOPT_BOOT_JARS_INPUT_PATH)/$(mod).jar)))
-
-# dex preopt on the bootclasspath produces multiple files.  The first dex file
-# is converted into to boot.art (to match the legacy assumption that boot.art
-# exists), and the rest are converted to boot-<name>.art.
-# In addition, each .art file has an associated .oat file.
-LIBART_TARGET_BOOT_ART_EXTRA_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).art boot-$(jar).oat)
-LIBART_TARGET_BOOT_ART_EXTRA_FILES += boot.oat
-LIBART_TARGET_BOOT_ART_VDEX_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).vdex)
-LIBART_TARGET_BOOT_ART_VDEX_FILES += boot.vdex
-
-# If we use a boot image profile.
-my_use_profile_for_boot_image := $(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE)
-ifeq (,$(my_use_profile_for_boot_image))
-# If not set, set the default to true if we are not a PDK build. PDK builds
-# can't build the profile since they don't have frameworks/base.
-ifneq (true,$(TARGET_BUILD_PDK))
-my_use_profile_for_boot_image := true
-endif
-endif
-ifeq (,$(strip $(LIBART_TARGET_BOOT_DEX_FILES)))
-my_use_profile_for_boot_image := false
-endif
-
-ifeq (true,$(my_use_profile_for_boot_image))
-
-boot_image_profiles := $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION)
-
-ifeq (,$(boot_image_profiles))
-# If not set, use the default.
-boot_image_profiles := frameworks/base/config/boot-image-profile.txt
-endif
-
-# Location of text based profile for the boot image.
-my_boot_image_profile_location := $(PRODUCT_OUT)/dex_bootjars/boot-image-profile.txt
-
-$(my_boot_image_profile_location): $(boot_image_profiles)
-	@echo 'Generating $@ for profman'
-	@rm -rf $@
-	$(hide) cat $^ > $@
-
-# Code to create the boot image profile, not in dex_preopt_libart_boot.mk since the profile is the same for all archs.
-my_out_boot_image_profile_location := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/boot.prof
-$(my_out_boot_image_profile_location): PRIVATE_PROFILE_INPUT_LOCATION := $(my_boot_image_profile_location)
-$(my_out_boot_image_profile_location): $(PROFMAN) $(LIBART_TARGET_BOOT_DEX_FILES) $(my_boot_image_profile_location)
-	@echo "target profman: $@"
-	@mkdir -p $(dir $@)
-	ANDROID_LOG_TAGS="*:e" $(PROFMAN) \
-		--create-profile-from=$(PRIVATE_PROFILE_INPUT_LOCATION) \
-		$(addprefix --apk=,$(LIBART_TARGET_BOOT_DEX_FILES)) \
-		$(addprefix --dex-location=,$(LIBART_TARGET_BOOT_DEX_LOCATIONS)) \
-		--reference-profile-file=$@
-
 # We want to install the profile even if we are not using preopt since it is required to generate
 # the image on the device.
-my_installed_profile := $(TARGET_OUT)/etc/boot-image.prof
-$(eval $(call copy-one-file,$(my_out_boot_image_profile_location),$(my_installed_profile)))
-ALL_DEFAULT_INSTALLED_MODULES += $(my_installed_profile)
+my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED),$(PRODUCT_OUT))
+ALL_DEFAULT_INSTALLED_MODULES += $(my_installed)
 
-endif
+# Install primary arch vdex files into a shared location, and then symlink them to both the primary
+# and secondary arch directories.
+my_vdex_copy_pairs := $(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_ARCH))
+my_installed := $(foreach v,$(my_vdex_copy_pairs),$(PRODUCT_OUT)$(call word-colon,2,$(v)))
+$(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed))
 
-LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES := $(addprefix $(PRODUCT_OUT)/$(DEXPREOPT_BOOT_JAR_DIR)/,$(LIBART_TARGET_BOOT_ART_VDEX_FILES))
+my_built_vdex_dir := $(dir $(call word-colon,1,$(firstword $(my_vdex_copy_pairs))))
+my_installed_vdex_dir := $(PRODUCT_OUT)$(dir $(call word-colon,2,$(firstword $(my_vdex_copy_pairs))))
 
-my_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
-
-ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-ifdef TARGET_2ND_ARCH
-my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
-endif
-endif
-
-# Copy shared vdex to the directory and create corresponding symlinks in primary and secondary arch.
-$(LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES) : PRIMARY_ARCH_DIR := $(dir $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE))
-$(LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES) : SECOND_ARCH_DIR := $(dir $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE))
-$(LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES) : $(DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME)
+$(my_installed): $(my_installed_vdex_dir)% : $(my_built_vdex_dir)%
 	@echo "Install: $@"
-	@mkdir -p $(dir $@)
 	@rm -f $@
-	$(hide) cp "$(dir $<)$(notdir $@)" "$@"
-	# Make symlink for both the archs. In the case its single arch the symlink will just get overridden.
-	@mkdir -p $(PRIMARY_ARCH_DIR)
-	$(hide) ln -sf /$(DEXPREOPT_BOOT_JAR_DIR)/$(notdir $@) $(PRIMARY_ARCH_DIR)$(notdir $@)
-	@mkdir -p $(SECOND_ARCH_DIR)
-	$(hide) ln -sf /$(DEXPREOPT_BOOT_JAR_DIR)/$(notdir $@) $(SECOND_ARCH_DIR)$(notdir $@)
+	$(copy-file-to-target)
+	mkdir -p $(dir $@)/$(TARGET_ARCH)
+	ln -sfn ../$(notdir $@) $(dir $@)/$(TARGET_ARCH)
+ifdef TARGET_2ND_ARCH
+  ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+	mkdir -p $(dir $@)/$(TARGET_2ND_ARCH)
+	ln -sfn ../$(notdir $@) $(dir $@)/$(TARGET_2ND_ARCH)
+  endif
+endif
+
+my_dexpreopt_image_extra_deps := $(firstword $(my_installed))
 
 my_2nd_arch_prefix :=
+include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
+
+ifdef TARGET_2ND_ARCH
+  ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+    my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
+    include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
+  endif
+endif
+
+my_2nd_arch_prefix :=
+
+
+my_vdex_copy_pairs :=
+my_installed :=
+my_built_vdex_dir :=
+my_installed_vdex_dir :=
+my_dexpreopt_image_extra_deps :=
diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk
index 47a8de8..34b8526 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -1,119 +1,25 @@
-# Rules to build boot.art
+# Rules to install a boot image built by dexpreopt_bootjars.go
 # Input variables:
+#   my_boot_image_name: the boot image to install
 #   my_2nd_arch_prefix: indicates if this is to build for the 2nd arch.
+#   my_dexpreopt_image_extra_deps: extra dependencies to add on the installed boot.art
 
-# The image "location" is a symbolic path that with multiarchitecture
-# support doesn't really exist on the device. Typically it is
-# /system/framework/boot.art and should be the same for all supported
-# architectures on the device. The concrete architecture specific
-# content actually ends up in a "filename" that contains an
-# architecture specific directory name such as arm, arm64, mips,
-# mips64, x86, x86_64.
-#
-# Here are some example values for an x86_64 / x86 configuration:
-#
-# DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION=out/target/product/generic_x86_64/dex_bootjars/system/framework/boot.art
-# DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME=out/target/product/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art
-# LIBART_BOOT_IMAGE=/system/framework/x86_64/boot.art
-#
-# 2ND_DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION=out/target/product/generic_x86_64/dex_bootjars/system/framework/boot.art
-# 2ND_DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME=out/target/product/generic_x86_64/dex_bootjars/system/framework/x86/boot.art
-# 2ND_LIBART_BOOT_IMAGE=/system/framework/x86/boot.art
+# Install the boot images compiled by Soong
+# The first file (generally boot.art) is saved as DEFAULT_DEX_PREOPT_INSTALLED_IMAGE,
+# and the rest are added as dependencies of the first.
 
-$(my_2nd_arch_prefix)LIBART_BOOT_IMAGE_FILENAME := /$(DEXPREOPT_BOOT_JAR_DIR)/$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH)/boot.art
+my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(PRODUCT_OUT))
+$(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed))
+$(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE += $(firstword $(my_installed))
 
-# The .oat with symbols
-$(my_2nd_arch_prefix)LIBART_TARGET_BOOT_OAT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)$(patsubst %.art,%.oat,$($(my_2nd_arch_prefix)LIBART_BOOT_IMAGE_FILENAME))
+# Install the unstripped boot images compiled by Soong into the symbols directory
+# The first file (generally boot.art) made a dependency of DEFAULT_DEX_PREOPT_INSTALLED_IMAGE,
+# and the rest are added as dependencies of the first.
+my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(TARGET_OUT_UNSTRIPPED))
+$(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed))
+$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(firstword $(my_installed))
 
-$(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE := $(PRODUCT_OUT)$($(my_2nd_arch_prefix)LIBART_BOOT_IMAGE_FILENAME)
-$(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_EXTRA_INSTALLED_FILES := $(addprefix $(dir $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)),\
-    $(LIBART_TARGET_BOOT_ART_EXTRA_FILES))
-$(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_FILES := $(addprefix $(dir $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)),\
-    $(LIBART_TARGET_BOOT_ART_VDEX_FILES))
+$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(my_dexpreopt_image_extra_deps)
 
-# If we have a dirty-image-objects file, create a parameter.
-DIRTY_IMAGE_OBJECTS_FLAGS :=
-ifneq ($(DIRTY_IMAGE_OBJECTS),)
-  DIRTY_IMAGE_OBJECTS_FLAGS := --dirty-image-objects=$(DIRTY_IMAGE_OBJECTS)
-endif
-
-# The rule to install boot.art
-# Depends on installed boot.oat, boot-*.art, boot-*.oat
-$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) : $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) | $(ACP) $($(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_EXTRA_INSTALLED_FILES) $($(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES)
-	@echo "Install: $@"
-	$(copy-file-to-target)
-
-# The rule to install boot.oat, boot-*.art, boot-*.oat
-# Depends on built-but-not-installed boot.art
-$($(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_EXTRA_INSTALLED_FILES) : $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME)  | $(ACP)
-	@echo "Install: $@"
-	@mkdir -p $(dir $@)
-	$(hide) $(ACP) -fp $(dir $<)$(notdir $@) $@
-
-ifeq (,$(my_out_boot_image_profile_location))
-my_boot_image_flags := --image-classes=$(PRELOADED_CLASSES)
-else
-my_boot_image_flags := --compiler-filter=speed-profile
-my_boot_image_flags += --profile-file=$(my_out_boot_image_profile_location)
-endif
-my_boot_image_flags += $(DIRTY_IMAGE_OBJECTS_FLAGS)
-
-ifneq (addresstrue,$(SANITIZE_TARGET)$(SANITIZE_LITE))
-# Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
-# and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
-# Note: this is technically incorrect. Compiled code contains stack checks which may depend
-#       on ASAN settings.
-
-# Use ANDROID_LOG_TAGS to suppress most logging by default...
-ifeq (,$(ART_BOOT_IMAGE_EXTRA_ARGS))
-DEX2OAT_BOOT_IMAGE_LOG_TAGS := ANDROID_LOG_TAGS="*:e"
-else
-# ...unless the boot image is generated specifically for testing, then allow all logging.
-DEX2OAT_BOOT_IMAGE_LOG_TAGS := ANDROID_LOG_TAGS="*:v"
-endif
-
-# An additional message to print on dex2oat failure.
-DEX2OAT_FAILURE_MESSAGE := ERROR: Dex2oat failed to compile a boot image.
-DEX2OAT_FAILURE_MESSAGE += It is likely that the boot classpath is inconsistent.
-ifeq ($(ONE_SHOT_MAKEFILE),)
-  DEX2OAT_FAILURE_MESSAGE += Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.
-else
-  DEX2OAT_FAILURE_MESSAGE += Build with m, mma, or mmma instead of mm or mmm to remedy the situation.
-endif
-
-$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_BOOT_IMAGE_FLAGS := $(my_boot_image_flags)
-$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_2ND_ARCH_VAR_PREFIX := $(my_2nd_arch_prefix)
-# Use dex2oat debug version for better error reporting
-# Pass --avoid-storing-invocation to make the output deterministics between
-# different products that may have different paths on the command line.
-$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) : $(LIBART_TARGET_BOOT_DEX_FILES) $(PRELOADED_CLASSES) $(DIRTY_IMAGE_OBJECTS) $(DEX2OAT_DEPENDENCY) $(my_out_boot_image_profile_location)
-	@echo "target dex2oat: $@"
-	@mkdir -p $(dir $@)
-	@mkdir -p $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))
-	@rm -f $(dir $@)/*.art $(dir $@)/*.oat $(dir $@)/*.invocation
-	@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art
-	@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.oat
-	@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.invocation
-	$(hide) $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) $(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
-		--avoid-storing-invocation \
-		--write-invocation-to=$(patsubst %.art,%.invocation,$@) \
-		--runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
-		$(PRIVATE_BOOT_IMAGE_FLAGS) \
-		$(addprefix --dex-file=,$(LIBART_TARGET_BOOT_DEX_FILES)) \
-		$(addprefix --dex-location=,$(LIBART_TARGET_BOOT_DEX_LOCATIONS)) \
-		--generate-debug-info --generate-build-id \
-		--oat-symbols=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED) \
-		--strip \
-		--oat-file=$(patsubst %.art,%.oat,$@) \
-		--oat-location=$(patsubst %.art,%.oat,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_BOOT_IMAGE_FILENAME)) \
-		--image=$@ --base=$(LIBART_IMG_TARGET_BASE_ADDRESS) \
-		--instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
-		--instruction-set-variant=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT) \
-		--instruction-set-features=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
-		--android-root=$(PRODUCT_OUT)/system \
-		--no-inline-from=core-oj.jar \
-		--abort-on-hard-verifier-error \
-		$(PRODUCT_DEX_PREOPT_BOOT_FLAGS) $(ART_BOOT_IMAGE_EXTRA_ARGS) \
-		|| ( echo "$(DEX2OAT_FAILURE_MESSAGE)" ; false )
-
-endif
+my_installed :=
+my_built_installed :=
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index f32b7b5..85ddbfa 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -1,7 +1,6 @@
 # dexpreopt_odex_install.mk is used to define odex creation rules for JARs and APKs
 # This file depends on variables set in base_rules.mk
-# Output variables: LOCAL_DEX_PREOPT, LOCAL_UNCOMPRESS_DEX, built_odex,
-#                   dexpreopt_boot_jar_module
+# Output variables: LOCAL_DEX_PREOPT, LOCAL_UNCOMPRESS_DEX
 
 ifeq (true,$(LOCAL_USE_EMBEDDED_DEX))
   LOCAL_UNCOMPRESS_DEX := true
@@ -117,8 +116,24 @@
 endif
 
 my_dexpreopt_archs :=
+my_dexpreopt_images :=
+my_dexpreopt_infix := boot
+ifeq (true, $(DEXPREOPT_USE_APEX_IMAGE))
+  my_dexpreopt_infix := apex
+endif
 
 ifdef LOCAL_DEX_PREOPT
+  ifeq (,$(filter PRESIGNED,$(LOCAL_CERTIFICATE)))
+    # Store uncompressed dex files preopted in /system
+    ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
+      ifeq ($(call install-on-system-other, $(my_module_path)),)
+        LOCAL_UNCOMPRESS_DEX := true
+      endif  # install-on-system-other
+    else  # BOARD_USES_SYSTEM_OTHER_ODEX
+      LOCAL_UNCOMPRESS_DEX := true
+    endif
+  endif
+
   ifeq ($(LOCAL_MODULE_CLASS),JAVA_LIBRARIES)
     my_module_multilib := $(LOCAL_MULTILIB)
     # If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
@@ -139,11 +154,13 @@
     # #################################################
     # Odex for the 1st arch
     my_dexpreopt_archs += $(TARGET_ARCH)
+    my_dexpreopt_images += $(DEXPREOPT_IMAGE_$(my_dexpreopt_infix)_$(TARGET_ARCH))
     # Odex for the 2nd arch
     ifdef TARGET_2ND_ARCH
       ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
         ifneq (first,$(my_module_multilib))
           my_dexpreopt_archs += $(TARGET_2ND_ARCH)
+          my_dexpreopt_images += $(DEXPREOPT_IMAGE_$(my_dexpreopt_infix)_$(TARGET_2ND_ARCH))
         endif  # my_module_multilib is not first.
       endif  # TARGET_TRANSLATE_2ND_ARCH not true
     endif  # TARGET_2ND_ARCH
@@ -153,11 +170,15 @@
     # Save the module multilib since setup_one_odex modifies it.
     my_2nd_arch_prefix := $(LOCAL_2ND_ARCH_VAR_PREFIX)
     my_dexpreopt_archs += $(TARGET_$(my_2nd_arch_prefix)ARCH)
+    my_dexpreopt_images += \
+        $(DEXPREOPT_IMAGE_$(my_dexpreopt_infix)_$(TARGET_$(my_2nd_arch_prefix)ARCH))
     ifdef TARGET_2ND_ARCH
       ifeq ($(my_module_multilib),both)
         # The non-preferred arch
         my_2nd_arch_prefix := $(if $(LOCAL_2ND_ARCH_VAR_PREFIX),,$(TARGET_2ND_ARCH_VAR_PREFIX))
         my_dexpreopt_archs += $(TARGET_$(my_2nd_arch_prefix)ARCH)
+        my_dexpreopt_images += \
+            $(DEXPREOPT_IMAGE_$(my_dexpreopt_infix)_$(TARGET_$(my_2nd_arch_prefix)ARCH))
       endif  # LOCAL_MULTILIB is both
     endif  # TARGET_2ND_ARCH
   endif  # LOCAL_MODULE_CLASS
@@ -175,35 +196,36 @@
 
   $(call json_start)
 
-  $(call add_json_str,  Name,                          $(LOCAL_MODULE))
-  $(call add_json_str,  DexLocation,                   $(patsubst $(PRODUCT_OUT)%,%,$(LOCAL_INSTALLED_MODULE)))
-  $(call add_json_str,  BuildPath,                     $(LOCAL_BUILT_MODULE))
-  $(call add_json_str,  DexPath,                       $$1)
-  $(call add_json_str,  ExtrasOutputPath,              $$2)
-  $(call add_json_bool, UseEmbeddedDex,                $(filter true,$(LOCAL_USE_EMBEDDED_DEX)))
-  $(call add_json_bool, Privileged,                    $(filter true,$(LOCAL_PRIVILEGED_MODULE)))
-  $(call add_json_bool, UncompressedDex,               $(filter true,$(LOCAL_UNCOMPRESS_DEX)))
-  $(call add_json_bool, HasApkLibraries,               $(LOCAL_APK_LIBRARIES))
-  $(call add_json_list, PreoptFlags,                   $(LOCAL_DEX_PREOPT_FLAGS))
-  $(call add_json_str,  ProfileClassListing,           $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE)))
-  $(call add_json_bool, ProfileIsTextListing,          $(my_profile_is_text_listing))
-  $(call add_json_bool, EnforceUsesLibraries,          $(LOCAL_ENFORCE_USES_LIBRARIES))
-  $(call add_json_list, OptionalUsesLibraries,         $(LOCAL_OPTIONAL_USES_LIBRARIES))
-  $(call add_json_list, UsesLibraries,                 $(LOCAL_USES_LIBRARIES))
+  # DexPath, StripInputPath, and StripOutputPath are not set, they will
+  # be filled in by dexpreopt_gen.
+
+  $(call add_json_str,  Name,                           $(LOCAL_MODULE))
+  $(call add_json_str,  DexLocation,                    $(patsubst $(PRODUCT_OUT)%,%,$(LOCAL_INSTALLED_MODULE)))
+  $(call add_json_str,  BuildPath,                      $(LOCAL_BUILT_MODULE))
+  $(call add_json_str,  ExtrasOutputPath,               $$2)
+  $(call add_json_bool, Privileged,                     $(filter true,$(LOCAL_PRIVILEGED_MODULE)))
+  $(call add_json_bool, UncompressedDex,                $(filter true,$(LOCAL_UNCOMPRESS_DEX)))
+  $(call add_json_bool, HasApkLibraries,                $(LOCAL_APK_LIBRARIES))
+  $(call add_json_list, PreoptFlags,                    $(LOCAL_DEX_PREOPT_FLAGS))
+  $(call add_json_str,  ProfileClassListing,            $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE)))
+  $(call add_json_bool, ProfileIsTextListing,           $(my_profile_is_text_listing))
+  $(call add_json_bool, EnforceUsesLibraries,           $(LOCAL_ENFORCE_USES_LIBRARIES))
+  $(call add_json_list, OptionalUsesLibraries,          $(LOCAL_OPTIONAL_USES_LIBRARIES))
+  $(call add_json_list, UsesLibraries,                  $(LOCAL_USES_LIBRARIES))
   $(call add_json_map,  LibraryPaths)
   $(foreach lib,$(sort $(LOCAL_USES_LIBRARIES) $(LOCAL_OPTIONAL_USES_LIBRARIES) org.apache.http.legacy android.hidl.base-V1.0-java android.hidl.manager-V1.0-java),\
     $(call add_json_str, $(lib), $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar))
   $(call end_json_map)
-  $(call add_json_list, Archs,                         $(my_dexpreopt_archs))
-  $(call add_json_str,  DexPreoptImageLocation,        $(LOCAL_DEX_PREOPT_IMAGE_LOCATION))
-  $(call add_json_bool, PreoptExtractedApk,            $(my_preopt_for_extracted_apk))
-  $(call add_json_bool, NoCreateAppImage,              $(filter false,$(LOCAL_DEX_PREOPT_APP_IMAGE)))
-  $(call add_json_bool, ForceCreateAppImage,           $(filter true,$(LOCAL_DEX_PREOPT_APP_IMAGE)))
-  $(call add_json_bool, PresignedPrebuilt,             $(filter PRESIGNED,$(LOCAL_CERTIFICATE)))
+  $(call add_json_list, Archs,                          $(my_dexpreopt_archs))
+  $(call add_json_list, DexPreoptImages,                $(my_dexpreopt_images))
+  $(call add_json_list, PreoptBootClassPathDexFiles,    $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES))
+  $(call add_json_list, PreoptBootClassPathDexLocations,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
+  $(call add_json_bool, PreoptExtractedApk,             $(my_preopt_for_extracted_apk))
+  $(call add_json_bool, NoCreateAppImage,               $(filter false,$(LOCAL_DEX_PREOPT_APP_IMAGE)))
+  $(call add_json_bool, ForceCreateAppImage,            $(filter true,$(LOCAL_DEX_PREOPT_APP_IMAGE)))
+  $(call add_json_bool, PresignedPrebuilt,              $(filter PRESIGNED,$(LOCAL_CERTIFICATE)))
 
-  $(call add_json_bool, NoStripping,                   $(filter nostripping,$(LOCAL_DEX_PREOPT)))
-  $(call add_json_str,  StripInputPath,                $$1)
-  $(call add_json_str,  StripOutputPath,               $$2)
+  $(call add_json_bool, NoStripping,                    $(filter nostripping,$(LOCAL_DEX_PREOPT)))
 
   $(call json_end)
 
@@ -228,15 +250,16 @@
   $(my_dexpreopt_script): $(my_dexpreopt_config) $(PRODUCT_OUT)/dexpreopt.config
 	@echo "$(PRIVATE_MODULE) dexpreopt gen"
 	$(DEXPREOPT_GEN) -global $(PRIVATE_GLOBAL_CONFIG) -module $(PRIVATE_MODULE_CONFIG) \
-	-dexpreopt_script $@ -strip_script $(PRIVATE_STRIP_SCRIPT)
+	-dexpreopt_script $@ -strip_script $(PRIVATE_STRIP_SCRIPT) \
+	-out_dir $(OUT_DIR)
 
   my_dexpreopt_deps := $(my_dex_jar)
   my_dexpreopt_deps += $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE))
   my_dexpreopt_deps += \
     $(foreach lib,$(sort $(LOCAL_USES_LIBRARIES) $(LOCAL_OPTIONAL_USES_LIBRARIES) org.apache.http.legacy android.hidl.base-V1.0-java android.hidl.manager-V1.0-java),\
       $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar)
-  my_dexpreopt_deps += $(LOCAL_DEX_PREOPT_IMAGE_LOCATION)
-  # TODO: default boot images
+  my_dexpreopt_deps += $(my_dexpreopt_images)
+  my_dexpreopt_deps += $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
 
   $(my_dexpreopt_zip): PRIVATE_MODULE := $(LOCAL_MODULE)
   $(my_dexpreopt_zip): $(my_dexpreopt_deps)
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index 88d2fe6..ad073c7 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -18,11 +18,7 @@
 $(built_dpi_apk): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
 $(built_dpi_apk): PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports)
 $(built_dpi_apk): PRIVATE_RESOURCE_LIST := $(all_res_assets)
-ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
-$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-else
-$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(DEFAULT_APP_TARGET_SDK)
-endif
+$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call module-target-sdk-version)
 $(built_dpi_apk): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
 $(built_dpi_apk): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_INSTRUMENTATION_FOR)
 $(built_dpi_apk): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
@@ -71,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/dynamic_binary.mk b/core/dynamic_binary.mk
index a42afe9..0accdc0 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -103,11 +103,9 @@
   endif
 endif
 
-ifeq ($(my_use_clang_lld),true)
-  # b/80093681: GNU strip and objcopy --{add,remove}-section have bug in handling
-  # GNU_RELRO segment of files lnked by clang lld; so they are replaced
-  # by llvm-strip and llvm-objcopy here.
-  my_strip_args += --use-llvm-strip
+ifeq ($($(my_prefix)OS),darwin)
+  # llvm-strip does not support Darwin Mach-O yet.
+  my_strip_args += --use-gnu-strip
 endif
 
 valid_strip := mini-debug-info keep_symbols true no_debuglink
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 17448f1..1704daf 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -152,6 +152,45 @@
   HOST_2ND_ARCH :=
 endif
 
+HOST_2ND_ARCH_VAR_PREFIX := 2ND_
+HOST_2ND_ARCH_MODULE_SUFFIX := _32
+HOST_CROSS_2ND_ARCH_VAR_PREFIX := 2ND_
+HOST_CROSS_2ND_ARCH_MODULE_SUFFIX := _64
+TARGET_2ND_ARCH_VAR_PREFIX := 2ND_
+.KATI_READONLY := \
+  HOST_ARCH \
+  HOST_2ND_ARCH \
+  HOST_IS_64_BIT \
+  HOST_2ND_ARCH_VAR_PREFIX \
+  HOST_2ND_ARCH_MODULE_SUFFIX \
+  HOST_CROSS_2ND_ARCH_VAR_PREFIX \
+  HOST_CROSS_2ND_ARCH_MODULE_SUFFIX \
+  TARGET_2ND_ARCH_VAR_PREFIX \
+
+combo_target := HOST_
+combo_2nd_arch_prefix :=
+include $(BUILD_COMBOS)/select.mk
+
+ifdef HOST_2ND_ARCH
+  combo_2nd_arch_prefix := $(HOST_2ND_ARCH_VAR_PREFIX)
+  include $(BUILD_SYSTEM)/combo/select.mk
+endif
+
+# Load the windows cross compiler under Linux
+ifdef HOST_CROSS_OS
+  combo_target := HOST_CROSS_
+  combo_2nd_arch_prefix :=
+  include $(BUILD_SYSTEM)/combo/select.mk
+
+  ifdef HOST_CROSS_2ND_ARCH
+    combo_2nd_arch_prefix := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
+    include $(BUILD_SYSTEM)/combo/select.mk
+  endif
+endif
+
+# on windows, the tools have .exe at the end, and we depend on the
+# host config stuff being done first
+
 BUILD_ARCH := $(HOST_ARCH)
 BUILD_2ND_ARCH := $(HOST_2ND_ARCH)
 
@@ -206,7 +245,10 @@
 #################################################################
 # Set up minimal BOOTCLASSPATH list of jars to build/execute
 # java code with dalvikvm/art.
-TARGET_CORE_JARS := core-oj core-libart conscrypt okhttp bouncycastle apache-xml
+# Jars present in the runtime apex. These should match exactly the list of
+# Java libraries in the runtime apex build rule.
+RUNTIME_APEX_JARS := core-oj core-libart okhttp bouncycastle apache-xml
+TARGET_CORE_JARS := $(RUNTIME_APEX_JARS) conscrypt
 ifeq ($(EMMA_INSTRUMENT),true)
   ifneq ($(EMMA_INSTRUMENT_STATIC),true)
     # For instrumented build, if Jacoco is not being included statically
@@ -229,351 +271,9 @@
 endif
 
 SDK_HOST_ARCH := x86
-
-# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
-# or under vendor/*/$(TARGET_DEVICE).  Search in both places, but
-# make sure only one exists.
-# Real boards should always be associated with an OEM vendor.
-ifdef TARGET_DEVICE_DIR
-  ifneq ($(origin TARGET_DEVICE_DIR),command line)
-    $(error TARGET_DEVICE_DIR may not be set manually)
-  endif
-  board_config_mk := $(TARGET_DEVICE_DIR)/BoardConfig.mk
-else
-  board_config_mk := \
-    $(strip $(sort $(wildcard \
-      $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
-      $(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
-      $(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
-    )))
-  ifeq ($(board_config_mk),)
-    $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))
-  endif
-  ifneq ($(words $(board_config_mk)),1)
-    $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))
-  endif
-  TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
-  .KATI_READONLY := TARGET_DEVICE_DIR
-endif
-include $(board_config_mk)
-ifeq ($(TARGET_ARCH),)
-  $(error TARGET_ARCH not defined by board config: $(board_config_mk))
-endif
-ifneq ($(MALLOC_IMPL),)
-  $(warning *** Unsupported option MALLOC_IMPL defined by board config: $(board_config_mk).)
-  $(error Use `MALLOC_SVELTE := true` to configure jemalloc for low-memory)
-endif
-board_config_mk :=
-
-###########################################
-# Handle BUILD_BROKEN_* settings
-vars := \
-  BUILD_BROKEN_ANDROIDMK_EXPORTS \
-  BUILD_BROKEN_DUP_COPY_HEADERS \
-  BUILD_BROKEN_DUP_RULES \
-  BUILD_BROKEN_PHONY_TARGETS
-
-$(foreach var,$(vars),$(eval $(var) := $$(strip $$($(var)))))
-
-$(foreach var,$(vars), \
-  $(if $(filter-out true false,$($(var))), \
-    $(error Valid values of $(var) are "true", "false", and "". Not "$($(var))")))
-
-.KATI_READONLY := $(vars)
-
-CHANGES_URL := https://android.googlesource.com/platform/build/+/master/Changes.md
-
-ifneq ($(BUILD_BROKEN_ANDROIDMK_EXPORTS),true)
-$(KATI_obsolete_export It is a global setting. See $(CHANGES_URL)#export_keyword)
-endif
-
-CHANGES_URL :=
-
-###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_RAMDISK
-ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
-TARGET_COPY_OUT_RAMDISK := $(TARGET_COPY_OUT_ROOT)
-endif
-
-###########################################
-# Configure whether we're building the system image
-BUILDING_SYSTEM_IMAGE := true
-ifeq ($(PRODUCT_BUILD_SYSTEM_IMAGE),)
-  ifndef PRODUCT_USE_DYNAMIC_PARTITION_SIZE
-    ifndef BOARD_SYSTEMIMAGE_PARTITION_SIZE
-      BUILDING_SYSTEM_IMAGE :=
-    endif
-  endif
-else ifeq ($(PRODUCT_BUILD_SYSTEM_IMAGE),false)
-  BUILDING_SYSTEM_IMAGE :=
-endif
-.KATI_READONLY := BUILDING_SYSTEM_IMAGE
-
-# Are we building a system_other image
-BUILDING_SYSTEM_OTHER_IMAGE :=
-ifeq ($(PRODUCT_BUILD_SYSTEM_OTHER_IMAGE),)
-  ifdef BUILDING_SYSTEM_IMAGE
-    ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
-      BUILDING_SYSTEM_OTHER_IMAGE := true
-    endif
-  endif
-else ifeq ($(PRODUCT_BUILD_SYSTEM_OTHER_IMAGE),true)
-  BUILDING_SYSTEM_OTHER_IMAGE := true
-  ifndef BUILDING_SYSTEM_IMAGE
-    $(error PRODUCT_BUILD_SYSTEM_OTHER_IMAGE = true requires building the system image)
-  endif
-endif
-.KATI_READONLY := BUILDING_SYSTEM_OTHER_IMAGE
-
-# Are we building a cache image
-BUILDING_CACHE_IMAGE :=
-ifeq ($(PRODUCT_BUILD_CACHE_IMAGE),)
-  ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
-    BUILDING_CACHE_IMAGE := true
-  endif
-else ifeq ($(PRODUCT_BUILD_CACHE_IMAGE),true)
-  BUILDING_CACHE_IMAGE := true
-  ifndef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
-    $(error PRODUCT_BUILD_CACHE_IMAGE set to true, but BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE not defined)
-  endif
-endif
-.KATI_READONLY := BUILDING_CACHE_IMAGE
-
-# TODO: Add BUILDING_BOOT_IMAGE / BUILDING_RECOVERY_IMAGE
-# This gets complicated with BOARD_USES_RECOVERY_AS_BOOT, so skipping for now.
-
-# Are we building a ramdisk image
-BUILDING_RAMDISK_IMAGE := true
-ifeq ($(PRODUCT_BUILD_RAMDISK_IMAGE),)
-  # TODO: Be smarter about this. This probably only needs to happen when one of the follow is true:
-  #  BUILDING_BOOT_IMAGE
-  #  BUILDING_RECOVERY_IMAGE
-else ifeq ($(PRODUCT_BUILD_RAMDISK_IMAGE),false)
-  BUILDING_RAMDISK_IMAGE :=
-endif
-.KATI_READONLY := BUILDING_RAMDISK_IMAGE
-
-# Are we building a userdata image
-BUILDING_USERDATA_IMAGE :=
-ifeq ($(PRODUCT_BUILD_USERDATA_IMAGE),)
-  ifdef BOARD_USERDATAIMAGE_PARTITION_SIZE
-    BUILDING_USERDATA_IMAGE := true
-  endif
-else ifeq ($(PRODUCT_BUILD_USERDATA_IMAGE),true)
-  BUILDING_USERDATA_IMAGE := true
-endif
-.KATI_READONLY := BUILDING_USERDATA_IMAGE
-
-###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_VENDOR
-ifeq ($(TARGET_COPY_OUT_VENDOR),$(_vendor_path_placeholder))
-  TARGET_COPY_OUT_VENDOR := system/vendor
-else ifeq ($(filter vendor system/vendor,$(TARGET_COPY_OUT_VENDOR)),)
-  $(error TARGET_COPY_OUT_VENDOR must be either 'vendor' or 'system/vendor', seeing '$(TARGET_COPY_OUT_VENDOR)'.)
-endif
-PRODUCT_COPY_FILES := $(subst $(_vendor_path_placeholder),$(TARGET_COPY_OUT_VENDOR),$(PRODUCT_COPY_FILES))
-
-BOARD_USES_VENDORIMAGE :=
-ifdef BOARD_PREBUILT_VENDORIMAGE
-  BOARD_USES_VENDORIMAGE := true
-endif
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
-  BOARD_USES_VENDORIMAGE := true
-endif
-ifeq ($(TARGET_COPY_OUT_VENDOR),vendor)
-  BOARD_USES_VENDORIMAGE := true
-else ifdef BOARD_USES_VENDORIMAGE
-  $(error TARGET_COPY_OUT_VENDOR must be set to 'vendor' to use a vendor image)
-endif
-.KATI_READONLY := BOARD_USES_VENDORIMAGE
-
-BUILDING_VENDOR_IMAGE :=
-ifeq ($(PRODUCT_BUILD_VENDOR_IMAGE),)
-  ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
-    BUILDING_VENDOR_IMAGE := true
-  endif
-else ifeq ($(PRODUCT_BUILD_VENDOR_IMAGE),true)
-  BUILDING_VENDOR_IMAGE := true
-  ifndef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
-    $(error PRODUCT_BUILD_VENDOR_IMAGE set to true, but BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE not defined)
-  endif
-endif
-ifdef BOARD_PREBUILT_VENDORIMAGE
-  BUILDING_VENDOR_IMAGE :=
-endif
-.KATI_READONLY := BUILDING_VENDOR_IMAGE
-
-###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT
-ifeq ($(TARGET_COPY_OUT_PRODUCT),$(_product_path_placeholder))
-TARGET_COPY_OUT_PRODUCT := system/product
-else ifeq ($(filter product system/product,$(TARGET_COPY_OUT_PRODUCT)),)
-$(error TARGET_COPY_OUT_PRODUCT must be either 'product' or 'system/product', seeing '$(TARGET_COPY_OUT_PRODUCT)'.)
-endif
-PRODUCT_COPY_FILES := $(subst $(_product_path_placeholder),$(TARGET_COPY_OUT_PRODUCT),$(PRODUCT_COPY_FILES))
-
-BOARD_USES_PRODUCTIMAGE :=
-ifdef BOARD_PREBUILT_PRODUCTIMAGE
-  BOARD_USES_PRODUCTIMAGE := true
-endif
-ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
-  BOARD_USES_PRODUCTIMAGE := true
-endif
-ifeq ($(TARGET_COPY_OUT_PRODUCT),product)
-  BOARD_USES_PRODUCTIMAGE := true
-else ifdef BOARD_USES_PRODUCTIMAGE
-  $(error TARGET_COPY_OUT_PRODUCT must be set to 'product' to use a product image)
-endif
-.KATI_READONLY := BOARD_USES_PRODUCTIMAGE
-
-BUILDING_PRODUCT_IMAGE :=
-ifeq ($(PRODUCT_BUILD_PRODUCT_IMAGE),)
-  ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
-    BUILDING_PRODUCT_IMAGE := true
-  endif
-else ifeq ($(PRODUCT_BUILD_PRODUCT_IMAGE),true)
-  BUILDING_PRODUCT_IMAGE := true
-  ifndef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
-    $(error PRODUCT_BUILD_PRODUCT_IMAGE set to true, but BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE not defined)
-  endif
-endif
-ifdef BOARD_PREBUILT_PRODUCTIMAGE
-  BUILDING_PRODUCT_IMAGE :=
-endif
-.KATI_READONLY := BUILDING_PRODUCT_IMAGE
-
-###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT_SERVICES
-MERGE_PRODUCT_SERVICES_INTO_PRODUCT :=
-ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),$(_product_services_path_placeholder))
-  TARGET_COPY_OUT_PRODUCT_SERVICES := system/product_services
-else ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
-  MERGE_PRODUCT_SERVICES_INTO_PRODUCT := true
-else ifeq ($(filter product_services system/product_services,$(TARGET_COPY_OUT_PRODUCT_SERVICES)),)
-  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be either 'product_services',\
-    '$(TARGET_COPY_OUT_PRODUCT)' or 'system/product_services', seeing '$(TARGET_COPY_OUT_PRODUCT_SERVICES)'.)
-endif
-.KATI_READONLY := MERGE_PRODUCT_SERVICES_INTO_PRODUCT
-PRODUCT_COPY_FILES := $(subst $(_product_services_path_placeholder),$(TARGET_COPY_OUT_PRODUCT_SERVICES),$(PRODUCT_COPY_FILES))
-
-BOARD_USES_PRODUCT_SERVICESIMAGE :=
-ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
-  BOARD_USES_PRODUCT_SERVICESIMAGE := true
-endif
-ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
-  BOARD_USES_PRODUCT_SERVICESIMAGE := true
-endif
-ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),product_services)
-  BOARD_USES_PRODUCT_SERVICESIMAGE := true
-else ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be set to 'product_services' to use a product_services image)
-endif
-
-BUILDING_PRODUCT_SERVICES_IMAGE :=
-ifeq ($(PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE),)
-  ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
-    BUILDING_PRODUCT_SERVICES_IMAGE := true
-  endif
-else ifeq ($(PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE),true)
-  BUILDING_PRODUCT_SERVICES_IMAGE := true
-  ifndef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
-    $(error PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE set to true, but BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE not defined)
-  endif
-endif
-ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
-  BUILDING_PRODUCT_SERVICES_IMAGE :=
-endif
-.KATI_READONLY := BUILDING_PRODUCT_SERVICES_IMAGE
-
-###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_ODM
-ifeq ($(TARGET_COPY_OUT_ODM),$(_odm_path_placeholder))
-  TARGET_COPY_OUT_ODM := vendor/odm
-else ifeq ($(filter odm vendor/odm,$(TARGET_COPY_OUT_ODM)),)
-  $(error TARGET_COPY_OUT_ODM must be either 'odm' or 'vendor/odm', seeing '$(TARGET_COPY_OUT_ODM)'.)
-endif
-PRODUCT_COPY_FILES := $(subst $(_odm_path_placeholder),$(TARGET_COPY_OUT_ODM),$(PRODUCT_COPY_FILES))
-
-BOARD_USES_ODMIMAGE :=
-ifdef BOARD_PREBUILT_ODMIMAGE
-  BOARD_USES_ODMIMAGE := true
-endif
-ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
-  BOARD_USES_ODMIMAGE := true
-endif
-ifeq ($(TARGET_COPY_OUT_ODM),odm)
-  BOARD_USES_ODMIMAGE := true
-else ifdef BOARD_USES_ODMIMAGE
-  $(error TARGET_COPY_OUT_ODM must be set to 'odm' to use an odm image)
-endif
-
-BUILDING_ODM_IMAGE :=
-ifeq ($(ODM_BUILD_ODM_IMAGE),)
-  ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
-    BUILDING_ODM_IMAGE := true
-  endif
-else ifeq ($(PRODUCT_BUILD_ODM_IMAGE),true)
-  BUILDING_ODM_IMAGE := true
-  ifndef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
-    $(error PRODUCT_BUILD_ODM_IMAGE set to true, but BOARD_ODMIMAGE_FILE_SYSTEM_TYPE not defined)
-  endif
-endif
-ifdef BOARD_PREBUILT_ODMIMAGE
-  BUILDING_ODM_IMAGE :=
-endif
-.KATI_READONLY := BUILDING_ODM_IMAGE
-
-###########################################
-# Ensure that only TARGET_RECOVERY_UPDATER_LIBS *or* AB_OTA_UPDATER is set.
-TARGET_RECOVERY_UPDATER_LIBS ?=
-AB_OTA_UPDATER ?=
-.KATI_READONLY := TARGET_RECOVERY_UPDATER_LIBS AB_OTA_UPDATER
-ifeq ($(AB_OTA_UPDATER),true)
-  ifneq ($(strip $(TARGET_RECOVERY_UPDATER_LIBS)),)
-    $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using AB_OTA_UPDATER)
-  endif
-endif
-
-# Check BOARD_VNDK_VERSION
-define check_vndk_version
-  $(eval vndk_path := prebuilts/vndk/v$(1)) \
-  $(if $(wildcard $(vndk_path)/*/Android.bp),,$(error VNDK version $(1) not found))
-endef
-
-ifdef BOARD_VNDK_VERSION
-  ifneq ($(BOARD_VNDK_VERSION),current)
-    $(error BOARD_VNDK_VERSION: Only "current" is implemented)
-  endif
-
-  TARGET_VENDOR_TEST_SUFFIX := /vendor
-else
-  TARGET_VENDOR_TEST_SUFFIX :=
-endif
-
-ifeq (,$(TARGET_BUILD_APPS))
-ifdef PRODUCT_EXTRA_VNDK_VERSIONS
-  $(foreach v,$(PRODUCT_EXTRA_VNDK_VERSIONS),$(call check_vndk_version,$(v)))
-endif
-endif
-
-# Ensure that BOARD_SYSTEMSDK_VERSIONS are all within PLATFORM_SYSTEMSDK_VERSIONS
-_unsupported_systemsdk_versions := $(filter-out $(PLATFORM_SYSTEMSDK_VERSIONS),$(BOARD_SYSTEMSDK_VERSIONS))
-ifneq (,$(_unsupported_systemsdk_versions))
-  $(error System SDK versions '$(_unsupported_systemsdk_versions)' in BOARD_SYSTEMSDK_VERSIONS are not supported.\
-          Supported versions are $(PLATFORM_SYSTEMSDK_VERSIONS))
-endif
-
-# ---------------------------------------------------------------
-# Set up configuration for target machine.
-# The following must be set:
-# 		TARGET_OS = { linux }
-# 		TARGET_ARCH = { arm | x86 | mips }
-
 TARGET_OS := linux
-# TARGET_ARCH should be set by BoardConfig.mk and will be checked later
-ifneq ($(filter %64,$(TARGET_ARCH)),)
-TARGET_IS_64_BIT := true
-endif
+
+include $(BUILD_SYSTEM)/board_config.mk
 
 # the target build type defaults to release
 ifneq ($(TARGET_BUILD_TYPE),debug)
@@ -680,8 +380,6 @@
 .KATI_READONLY := HOST_OUT_TEST_CONFIG
 
 # Out for HOST_2ND_ARCH
-HOST_2ND_ARCH_VAR_PREFIX := 2ND_
-HOST_2ND_ARCH_MODULE_SUFFIX := _32
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj32
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_EXECUTABLES := $(HOST_OUT_EXECUTABLES)
@@ -689,8 +387,6 @@
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_NATIVE_TESTS := $(HOST_OUT)/nativetest
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_TESTCASES := $(HOST_OUT_TESTCASES)
 .KATI_READONLY := \
-  HOST_2ND_ARCH_VAR_PREFIX \
-  HOST_2ND_ARCH_MODULE_SUFFIX \
   $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATES \
   $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES \
   $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_EXECUTABLES \
@@ -704,15 +400,11 @@
 .KATI_READONLY := HOST_LIBRARY_PATH
 
 # Out for HOST_CROSS_2ND_ARCH
-HOST_CROSS_2ND_ARCH_VAR_PREFIX := 2ND_
-HOST_CROSS_2ND_ARCH_MODULE_SUFFIX := _64
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATES := $(HOST_CROSS_OUT)/obj64
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_SHARED_LIBRARIES := $(HOST_CROSS_OUT)/lib64
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_EXECUTABLES := $(HOST_CROSS_OUT_EXECUTABLES)
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_NATIVE_TESTS := $(HOST_CROSS_OUT)/nativetest64
 .KATI_READONLY := \
-  HOST_CROSS_2ND_ARCH_VAR_PREFIX \
-  HOST_CROSS_2ND_ARCH_MODULE_SUFFIX \
   $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATES \
   $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_SHARED_LIBRARIES \
   $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_EXECUTABLES \
@@ -799,14 +491,13 @@
 .KATI_READONLY := TARGET_OUT_SYSTEM_OTHER
 
 # Out for TARGET_2ND_ARCH
-TARGET_2ND_ARCH_VAR_PREFIX := $(HOST_2ND_ARCH_VAR_PREFIX)
 ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
 # With this you can reference the arm binary translation library with libfoo_arm in PRODUCT_PACKAGES.
 TARGET_2ND_ARCH_MODULE_SUFFIX := _$(TARGET_2ND_ARCH)
 else
 TARGET_2ND_ARCH_MODULE_SUFFIX := $(HOST_2ND_ARCH_MODULE_SUFFIX)
 endif
-.KATI_READONLY := TARGET_2ND_ARCH_VAR_PREFIX TARGET_2ND_ARCH_MODULE_SUFFIX
+.KATI_READONLY := TARGET_2ND_ARCH_MODULE_SUFFIX
 
 ifneq ($(filter address,$(SANITIZE_TARGET)),)
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj_$(TARGET_2ND_ARCH)_asan
@@ -832,6 +523,11 @@
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_APPS_PRIVILEGED \
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_TESTCASES
 
+MODULE_CLASS_APPS := app
+MODULE_CLASS_EXECUTABLES := bin
+MODULE_CLASS_JAVA_LIBRARIES := framework
+MODULE_CLASS_NATIVE_TESTS := nativetest
+MODULE_CLASS_METRIC_TESTS := benchmarktest
 TARGET_OUT_DATA := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DATA)
 TARGET_OUT_DATA_EXECUTABLES := $(TARGET_OUT_EXECUTABLES)
 TARGET_OUT_DATA_SHARED_LIBRARIES := $(TARGET_OUT_SHARED_LIBRARIES)
@@ -851,6 +547,7 @@
 TARGET_OUT_VENDOR_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest$(TARGET_VENDOR_TEST_SUFFIX)
 TARGET_OUT_VENDOR_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest$(TARGET_VENDOR_TEST_SUFFIX)
 endif
+MODULE_CLASS_FAKE := fake_packages
 TARGET_OUT_DATA_FAKE := $(TARGET_OUT_DATA)/fake_packages
 .KATI_READONLY := \
   TARGET_OUT_DATA \
@@ -865,7 +562,13 @@
   TARGET_OUT_DATA_METRIC_TESTS \
   TARGET_OUT_VENDOR_NATIVE_TESTS \
   TARGET_OUT_VENDOR_METRIC_TESTS \
-  TARGET_OUT_DATA_FAKE
+  TARGET_OUT_DATA_FAKE \
+  MODULE_CLASS_APPS \
+  MODULE_CLASS_EXECUTABLES \
+  MODULE_CLASS_JAVA_LIBRARIES \
+  MODULE_CLASS_NATIVE_TESTS \
+  MODULE_CLASS_METRIC_TESTS \
+  MODULE_CLASS_FAKE
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_EXECUTABLES := $(TARGET_OUT_DATA_EXECUTABLES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_SHARED_LIBRARIES := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES)
diff --git a/core/force_aapt2.mk b/core/force_aapt2.mk
index ede6fd4..db2e60f 100644
--- a/core/force_aapt2.mk
+++ b/core/force_aapt2.mk
@@ -48,15 +48,7 @@
       ifeq (,$(wildcard $(LOCAL_PATH)/AndroidManifest.xml))
         # work around missing manifests by creating a default one
         LOCAL_FULL_MANIFEST_FILE := $(call local-intermediates-dir,COMMON)/DefaultManifest.xml
-        ifdef LOCAL_MIN_SDK_VERSION
-          my_manifest_min_sdk_version := $(LOCAL_MIN_SDK_VERSION)
-        else ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
-          my_manifest_min_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-        else
-          my_manifest_min_sdk_version := $(DEFAULT_APP_TARGET_SDK)
-        endif
-        $(call create-default-manifest-file,$(LOCAL_FULL_MANIFEST_FILE),$(my_manifest_min_sdk_version))
-        my_manifest_min_sdk_version :=
+        $(call create-default-manifest-file,$(LOCAL_FULL_MANIFEST_FILE),$(call module-min-sdk-version))
       endif
     endif
   endif
diff --git a/core/generate_enforce_rro.mk b/core/generate_enforce_rro.mk
index c88c779..f7877f2 100644
--- a/core/generate_enforce_rro.mk
+++ b/core/generate_enforce_rro.mk
@@ -1,24 +1,36 @@
 include $(CLEAR_VARS)
 
+enforce_rro_module := $(enforce_rro_source_module)__auto_generated_rro_$(enforce_rro_partition)
 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): PRIVATE_USE_PACKAGE_NAME := $(use_package_name_arg)
+$(rro_android_manifest_file): PRIVATE_PARTITION := $(enforce_rro_partition)
+# There should be no duplicate overrides, but just in case, set the priority of
+# /product overlays to be higher than /vendor, to at least get deterministic results.
+$(rro_android_manifest_file): PRIVATE_PRIORITY := $(if $(filter product,$(enforce_rro_partition)),1,0)
+$(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) \
+	    $(PRIVATE_USE_PACKAGE_NAME) \
+	    --partition $(PRIVATE_PARTITION) \
+	    --priority $(PRIVATE_PRIORITY) \
+	    -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)
@@ -27,10 +39,22 @@
 LOCAL_AAPT_FLAGS += --auto-add-overlay
 LOCAL_RESOURCE_DIR := $(enforce_rro_source_overlays)
 
-ifeq (framework-res__auto_generated_rro,$(enforce_rro_module))
-LOCAL_PRIVATE_PLATFORM_APIS := true
+ifeq (product,$(enforce_rro_partition))
+  LOCAL_PRODUCT_MODULE := true
+else ifeq (vendor,$(enforce_rro_partition))
+  LOCAL_VENDOR_MODULE := true
 else
-LOCAL_SDK_VERSION := current
+  $(error Unsupported partition. Want: [vendor/product] Got: [$(enforce_rro_partition)])
+endif
+
+ifneq (,$(LOCAL_RES_LIBRARIES))
+  # 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,$(enforce_rro_source_module))
+  LOCAL_PRIVATE_PLATFORM_APIS := true
+else
+  LOCAL_SDK_VERSION := current
 endif
 
 include $(BUILD_RRO_PACKAGE)
diff --git a/core/header_library.mk b/core/header_library.mk
index 3f2730e..ee65111 100644
--- a/core/header_library.mk
+++ b/core/header_library.mk
@@ -33,37 +33,4 @@
   LOCAL_2ND_ARCH_VAR_PREFIX :=
 endif # 2ND_ARCH
 
-ifdef LOCAL_IS_HOST_MODULE
-  ifdef HOST_CROSS_OS
-    my_prefix := HOST_CROSS_
-    LOCAL_HOST_PREFIX := $(my_prefix)
-
-    include $(BUILD_SYSTEM)/module_arch_supported.mk
-
-    ifeq ($(my_module_arch_supported),true)
-      # Build for 2ND_ARCH
-      LOCAL_BUILT_MODULE :=
-      LOCAL_INSTALLED_MODULE :=
-      LOCAL_INTERMEDIATE_TARGETS :=
-      include $(BUILD_SYSTEM)/header_library_internal.mk
-    endif
-
-    ifdef HOST_CROSS_2ND_ARCH
-      LOCAL_2ND_ARCH_VAR_PREFIX := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
-      include $(BUILD_SYSTEM)/module_arch_supported.mk
-
-      ifeq ($(my_module_arch_supported),true)
-        # Build for HOST_CROSS_2ND_ARCH
-        LOCAL_BUILT_MODULE :=
-        LOCAL_INSTALLED_MODULE :=
-        LOCAL_INTERMEDIATE_TARGETS :=
-        include $(BUILD_SYSTEM)/header_library_internal.mk
-      endif
-      LOCAL_2ND_ARCH_VAR_PREFIX :=
-    endif
-
-    LOCAL_HOST_PREFIX :=
-  endif
-endif
-
 my_module_arch_supported :=
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index 6a32ff9..2a251e8 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -183,23 +183,9 @@
 
 endif # !LOCAL_IS_STATIC_JAVA_LIBRARY
 
-ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
-  my_default_app_target_sdk := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-  my_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-else
-  my_default_app_target_sdk := $(DEFAULT_APP_TARGET_SDK)
-  my_sdk_version := $(PLATFORM_SDK_VERSION)
-endif
-
-ifdef LOCAL_MIN_SDK_VERSION
-  my_min_sdk_version := $(LOCAL_MIN_SDK_VERSION)
-else
-  my_min_sdk_version := $(call codename-or-sdk-to-sdk,$(my_default_app_target_sdk))
-endif
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(my_default_app_target_sdk)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(my_sdk_version)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MIN_SDK_VERSION := $(my_min_sdk_version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call module-target-sdk-version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(call module-sdk-version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MIN_SDK_VERSION := $(call codename-or-sdk-to-sdk,$(call module-min-sdk-version))
 
 USE_CORE_LIB_BOOTCLASSPATH :=
 
diff --git a/core/host_executable.mk b/core/host_executable.mk
index a2111a1..8d1026c 100644
--- a/core/host_executable.mk
+++ b/core/host_executable.mk
@@ -45,47 +45,5 @@
 LOCAL_2ND_ARCH_VAR_PREFIX :=
 endif  # HOST_2ND_ARCH
 
-ifdef HOST_CROSS_OS
-my_prefix := HOST_CROSS_
-LOCAL_HOST_PREFIX := $(my_prefix)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# Build for Windows
-# we don't want others using the cross compiled version
-saved_LOCAL_BUILT_MODULE := $(LOCAL_BUILT_MODULE)
-saved_LOCAL_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
-saved_LOCAL_LDFLAGS := $(LOCAL_LDFLAGS)
-LOCAL_BUILT_MODULE :=
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-
-include $(BUILD_SYSTEM)/host_executable_internal.mk
-LOCAL_LDFLAGS := $(saved_LOCAL_LDFLAGS)
-LOCAL_BUILT_MODULE := $(saved_LOCAL_BUILT_MODULE)
-LOCAL_INSTALLED_MODULE := $(saved_LOCAL_INSTALLED_MODULE)
-endif
-
-ifdef HOST_CROSS_2ND_ARCH
-LOCAL_2ND_ARCH_VAR_PREFIX := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# we don't want others using the cross compiled version
-saved_LOCAL_BUILT_MODULE := $(LOCAL_BUILT_MODULE)
-saved_LOCAL_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
-saved_LOCAL_LDFLAGS := $(LOCAL_LDFLAGS)
-LOCAL_BUILT_MODULE :=
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-
-include $(BUILD_SYSTEM)/host_executable_internal.mk
-LOCAL_LDFLAGS := $(saved_LOCAL_LDFLAGS)
-LOCAL_BUILT_MODULE := $(saved_LOCAL_BUILT_MODULE)
-LOCAL_INSTALLED_MODULE := $(saved_LOCAL_INSTALLED_MODULE)
-endif
-LOCAL_2ND_ARCH_VAR_PREFIX :=
-endif
-LOCAL_HOST_PREFIX :=
-endif
-
 LOCAL_NO_2ND_ARCH_MODULE_SUFFIX :=
 my_module_arch_supported :=
diff --git a/core/host_shared_library.mk b/core/host_shared_library.mk
index e9b3dad..81236d1 100644
--- a/core/host_shared_library.mk
+++ b/core/host_shared_library.mk
@@ -32,43 +32,6 @@
 LOCAL_2ND_ARCH_VAR_PREFIX :=
 endif  # HOST_2ND_ARCH
 
-ifdef HOST_CROSS_OS
-my_prefix := HOST_CROSS_
-LOCAL_HOST_PREFIX := $(my_prefix)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# Build for Windows
-LOCAL_BUILT_MODULE :=
-LOCAL_MODULE_SUFFIX :=
-# We don't want makefiles using the cross-compiled host tool
-saved_LOCAL_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-
-include $(BUILD_SYSTEM)/host_shared_library_internal.mk
-LOCAL_INSTALLED_MODULE := $(saved_LOCAL_INSTALLED_MODULE)
-endif
-
-ifdef HOST_CROSS_2ND_ARCH
-LOCAL_2ND_ARCH_VAR_PREFIX := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# Build for HOST_CROSS_2ND_ARCH
-LOCAL_BUILT_MODULE :=
-LOCAL_MODULE_SUFFIX :=
-# We don't want makefiles using the cross-compiled host tool
-saved_LOCAL_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-
-include $(BUILD_SYSTEM)/host_shared_library_internal.mk
-LOCAL_INSTALLED_MODULE := $(saved_LOCAL_INSTALLED_MODULE)
-endif
-LOCAL_2ND_ARCH_VAR_PREFIX :=
-endif
-LOCAL_HOST_PREFIX :=
-endif
-
 my_module_arch_supported :=
 
 ###########################################################
diff --git a/core/host_static_library.mk b/core/host_static_library.mk
index 71f4fd9..469da29 100644
--- a/core/host_static_library.mk
+++ b/core/host_static_library.mk
@@ -32,35 +32,6 @@
 LOCAL_2ND_ARCH_VAR_PREFIX :=
 endif  # HOST_2ND_ARCH
 
-ifdef HOST_CROSS_OS
-my_prefix := HOST_CROSS_
-LOCAL_HOST_PREFIX := $(my_prefix)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# Build for Windows
-LOCAL_BUILT_MODULE :=
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-
-include $(BUILD_SYSTEM)/host_static_library_internal.mk
-endif
-
-ifdef HOST_CROSS_2ND_ARCH
-LOCAL_2ND_ARCH_VAR_PREFIX := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# Build for HOST_CROSS_2ND_ARCH
-LOCAL_BUILT_MODULE :=
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-
-include $(BUILD_SYSTEM)/host_static_library_internal.mk
-endif
-LOCAL_2ND_ARCH_VAR_PREFIX :=
-endif
-LOCAL_HOST_PREFIX :=
-endif
-
 my_module_arch_supported :=
 
 ###########################################################
diff --git a/core/host_test_internal.mk b/core/host_test_internal.mk
index 42e01e1..dfe8cf1 100644
--- a/core/host_test_internal.mk
+++ b/core/host_test_internal.mk
@@ -3,7 +3,6 @@
 #####################################################
 
 ifeq ($(LOCAL_GTEST),true)
-  LOCAL_CFLAGS_windows += -DGTEST_OS_WINDOWS
   LOCAL_CFLAGS_linux += -DGTEST_OS_LINUX
   LOCAL_CFLAGS_darwin += -DGTEST_OS_MAC
 
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/java.mk b/core/java.mk
index e564db2..fc5a8bc 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -71,11 +71,8 @@
 full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
 full_classes_combined_jar := $(intermediates.COMMON)/classes-combined.jar
 built_dex_intermediate := $(intermediates.COMMON)/dex/classes.dex
-built_dex_hiddenapi := $(intermediates.COMMON)/dex-hiddenapi/classes.dex
 full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
 java_source_list_file := $(intermediates.COMMON)/java-source-list
-hiddenapi_flags_csv := $(intermediates.COMMON)/hiddenapi/flags.csv
-hiddenapi_metadata_csv := $(intermediates.COMMON)/hiddenapi/greylist.csv
 
 ifeq ($(LOCAL_MODULE_CLASS)$(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),APPS)
 # If this is an apk without any Java code (e.g. framework-res), we should skip compiling Java.
@@ -127,7 +124,7 @@
 
 $(aidl_java_sources) : $(LOCAL_ADDITIONAL_DEPENDENCIES) $(aidl_preprocess_import)
 
-$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b $(addprefix -p,$(aidl_preprocess_import)) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
+$(aidl_java_sources): PRIVATE_AIDL_FLAGS := $(addprefix -p,$(aidl_preprocess_import)) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
 $(aidl_java_sources): PRIVATE_MODULE := $(LOCAL_MODULE)
 
 endif
@@ -500,21 +497,11 @@
 	$(transform-classes.jar-to-dex)
 endif
 
-ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) # is_boot_jar
-  # Derive API greylist from the classes jar.
-  # We use full_classes_pre_proguard_jar here, as that is what is converted to
-  # dex later on. The difference is academic currently, as we don't proguard any
-  # bootclasspath code at the moment. If we were to do that, we should add keep
-  # rules for all members with the @UnsupportedAppUsage annotation.
-  $(eval $(call hiddenapi-generate-csv, $(full_classes_pre_proguard_jar),$(hiddenapi_flags_csv),$(hiddenapi_metadata_csv)))
-  LOCAL_INTERMEDIATE_TARGETS += $(hiddenapi_flags_csv) $(hiddenapi_metadata_csv)
-  $(eval $(call hiddenapi-copy-dex-files,$(built_dex_intermediate),$(built_dex_hiddenapi)))
-  built_dex_copy_from := $(built_dex_hiddenapi)
-else # !is_boot_jar
-  built_dex_copy_from := $(built_dex_intermediate)
-endif # is_boot_jar
+ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),)
+  $(call pretty-error,Modules in PRODUCT_BOOT_JARS must be defined in Android.bp files)
+endif
 
-$(built_dex): $(built_dex_copy_from)
+$(built_dex): $(built_dex_intermediate)
 	@echo Copying: $@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) rm -f $(dir $@)/classes*.dex
@@ -551,20 +538,6 @@
 
 endif  # full_classes_jar is defined
 
-ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
-  my_default_app_target_sdk := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-  my_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
-else
-  my_default_app_target_sdk := $(DEFAULT_APP_TARGET_SDK)
-  my_sdk_version := $(PLATFORM_SDK_VERSION)
-endif
-
-ifdef LOCAL_MIN_SDK_VERSION
-  my_min_sdk_version := $(LOCAL_MIN_SDK_VERSION)
-else
-  my_min_sdk_version := $(call codename-or-sdk-to-sdk,$(my_default_app_target_sdk))
-endif
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(my_default_app_target_sdk)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(my_sdk_version)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MIN_SDK_VERSION := $(my_min_sdk_version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call module-target-sdk-version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(call module-sdk-version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MIN_SDK_VERSION := $(call codename-or-sdk-to-sdk,$(call module-min-sdk-version))
diff --git a/core/java_library.mk b/core/java_library.mk
index 766fff5..c706cea 100644
--- a/core/java_library.mk
+++ b/core/java_library.mk
@@ -85,13 +85,6 @@
 .KATI_RESTAT: $(common_javalib.jar)
 
 ifdef LOCAL_DEX_PREOPT
-ifneq ($(dexpreopt_boot_jar_module),) # boot jar
-# boot jar's rules are defined in dex_preopt.mk
-dexpreopted_boot_jar := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(dexpreopt_boot_jar_module)_nodex.jar
-$(eval $(call copy-one-file,$(dexpreopted_boot_jar),$(LOCAL_BUILT_MODULE)))
-
-# For libart boot jars, we don't have .odex files.
-else # ! boot jar
 
 $(LOCAL_BUILT_MODULE): PRIVATE_STRIP_SCRIPT := $(intermediates)/strip.sh
 $(LOCAL_BUILT_MODULE): $(intermediates)/strip.sh
@@ -100,8 +93,6 @@
 $(LOCAL_BUILT_MODULE): $(common_javalib.jar)
 	$(PRIVATE_STRIP_SCRIPT) $< $@
 
-endif # ! boot jar
-
 else # LOCAL_DEX_PREOPT
 $(eval $(call copy-one-file,$(common_javalib.jar),$(LOCAL_BUILT_MODULE)))
 
diff --git a/core/local_systemsdk.mk b/core/local_systemsdk.mk
index 7acb57a..6c022f2 100644
--- a/core/local_systemsdk.mk
+++ b/core/local_systemsdk.mk
@@ -25,9 +25,8 @@
   ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
     ifndef LOCAL_SDK_VERSION
       ifeq ($(_is_vendor_app),true)
-        ifeq (,$(filter framework-res__auto_generated_rro,$(LOCAL_MODULE)))
-          # Runtime resource overlay for framework-res is exempted from building
-          # against System SDK.
+        ifeq (,$(filter %__auto_generated_rro_vendor,$(LOCAL_MODULE)))
+          # Runtime resource overlays are exempted from building against System SDK.
           # TODO(b/35859726): remove this exception
           LOCAL_SDK_VERSION := system_current
         endif
diff --git a/core/main.mk b/core/main.mk
index 67cd3ac..990d255 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -252,6 +252,20 @@
 ADDITIONAL_PRODUCT_PROPERTIES += ro.boot.dynamic_partitions_retrofit=true
 endif
 
+# Add the system server compiler filter if they are specified for the product.
+ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
+ADDITIONAL_PRODUCT_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)
+endif
+
+# Sets the default value of ro.postinstall.fstab.prefix to /system.
+# Device board config should override the value to /product when needed by:
+#
+#     PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product
+#
+# It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to
+# mount system_other partition.
+ADDITIONAL_DEFAULT_PROPERTIES += ro.postinstall.fstab.prefix=/system
+
 # -----------------------------------------------------------------
 ###
 ### In this section we set up the things that are different
@@ -264,26 +278,6 @@
 is_sdk_build := true
 endif
 
-# Add build properties for ART. These define system properties used by installd
-# to pass flags to dex2oat.
-ADDITIONAL_BUILD_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so
-ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT)
-ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
-  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
-endif
-
-ifdef TARGET_2ND_ARCH
-  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT)
-  ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
-    ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
-  endif
-endif
-
-# Add the system server compiler filter if they are specified for the product.
-ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
-ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)
-endif
-
 ## user/userdebug ##
 
 user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
@@ -410,12 +404,8 @@
 # Typical build; include any Android.mk files we can find.
 #
 
-# Before we go and include all of the module makefiles, strip values for easier
-# processing.
-$(call strip-product-vars)
-# Before we go and include all of the module makefiles, mark the PRODUCT_*
-# and ADDITIONAL*PROPERTIES values readonly so that they won't be modified.
-$(call readonly-product-vars)
+# Strip and readonly a few more variables so they won't be modified.
+$(readonly-final-product-vars)
 ADDITIONAL_DEFAULT_PROPERTIES := $(strip $(ADDITIONAL_DEFAULT_PROPERTIES))
 .KATI_READONLY := ADDITIONAL_DEFAULT_PROPERTIES
 ADDITIONAL_BUILD_PROPERTIES := $(strip $(ADDITIONAL_BUILD_PROPERTIES))
@@ -507,6 +497,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 ...)
 
 # -------------------------------------------------------------------
@@ -559,19 +553,15 @@
 define get-32-bit-modules
 $(sort $(foreach m,$(1),\
   $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\
-    $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX))\
-  $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\
-    $(m)$(HOST_2ND_ARCH_MODULE_SUFFIX))\
-    ))
+    $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX))))
 endef
 # Get a list of corresponding 32-bit module names, if one exists;
 # otherwise return the original module name
 define get-32-bit-modules-if-we-can
 $(sort $(foreach m,$(1),\
-  $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS)$(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\
-    $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX)) \
-    $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX)),\
-  $(m))))
+  $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\
+    $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX), \
+    $(m))))
 endef
 else  # TARGET_TRANSLATE_2ND_ARCH
 # For binary translation config, by default only install the first arch.
@@ -583,6 +573,22 @@
 endef
 endif  # TARGET_TRANSLATE_2ND_ARCH
 
+# TODO: we can probably check to see if these modules are actually host
+# modules
+define get-host-32-bit-modules
+$(sort $(foreach m,$(1),\
+  $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\
+    $(m)$(HOST_2ND_ARCH_MODULE_SUFFIX))))
+endef
+# Get a list of corresponding 32-bit module names, if one exists;
+# otherwise return the original module name
+define get-host-32-bit-modules-if-we-can
+$(sort $(foreach m,$(1),\
+  $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\
+    $(m)$(HOST_2ND_ARCH_MODULE_SUFFIX),\
+    $(m))))
+endef
+
 # If a module is for a cross host os, the required modules must be for
 # that OS too.
 # If a module is built for 32-bit, the required modules must be 32-bit too;
@@ -1030,6 +1036,16 @@
   $(call expand-required-modules,$(1),$(_erm_new_modules),$(_erm_all_overrides)))
 endef
 
+# Same as expand-required-modules above, but does not handle module overrides, as
+# we don't intend to support them on the host.
+define expand-required-host-modules
+$(eval _erm_req := $(foreach m,$(2),$(ALL_MODULES.$(m).REQUIRED))) \
+$(eval _erm_new_modules := $(sort $(filter-out $($(1)),$(_erm_req)))) \
+$(eval $(1) += $(_erm_new_modules)) \
+$(if $(_erm_new_modules),\
+  $(call expand-required-host-modules,$(1),$(_erm_new_modules)))
+endef
+
 # Transforms paths relative to PRODUCT_OUT to absolute paths.
 # $(1): list of relative paths
 # $(2): optional suffix to append to paths
@@ -1046,6 +1062,8 @@
 define auto-included-modules
   $(if $(BOARD_VNDK_VERSION),vndk_package) \
   $(if $(DEVICE_MANIFEST_FILE),device_manifest.xml) \
+  $(if $(ODM_MANIFEST_FILES),odm_manifest.xml) \
+  $(if $(ODM_MANIFEST_SKUS),$(foreach sku, $(ODM_MANIFEST_SKUS),odm_manifest_$(sku).xml)) \
 
 endef
 
@@ -1088,11 +1106,28 @@
   $(eval _pif_modules += $(call get-32-bit-modules, $(_pif_modules_rest))) \
   $(eval _pif_modules += $(_pif_modules_rest)) \
   $(call expand-required-modules,_pif_modules,$(_pif_modules),$(_pif_overrides)) \
-  $(call module-installed-files, $(_pif_modules)) \
+  $(filter-out $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(_pif_modules))) \
   $(call resolve-product-relative-paths,\
     $(foreach cf,$(PRODUCTS.$(_mk).PRODUCT_COPY_FILES),$(call word-colon,2,$(cf))))
 endef
 
+# Similar to product-installed-files above, but handles PRODUCT_HOST_PACKAGES instead
+# This does support the :32 / :64 syntax, but does not support module overrides.
+define host-installed-files
+  $(eval _hif_modules := $(PRODUCTS.$(strip $(1)).PRODUCT_HOST_PACKAGES)) \
+  $(eval ### Resolve the :32 :64 module name) \
+  $(eval _hif_modules_32 := $(patsubst %:32,%,$(filter %:32, $(_hif_modules)))) \
+  $(eval _hif_modules_64 := $(patsubst %:64,%,$(filter %:64, $(_hif_modules)))) \
+  $(eval _hif_modules_rest := $(filter-out %:32 %:64,$(_hif_modules))) \
+  $(eval _hif_modules := $(call get-host-32-bit-modules-if-we-can, $(_hif_modules_32))) \
+  $(eval _hif_modules += $(_hif_modules_64)) \
+  $(eval ### For the rest we add both) \
+  $(eval _hif_modules += $(call get-host-32-bit-modules, $(_hif_modules_rest))) \
+  $(eval _hif_modules += $(_hif_modules_rest)) \
+  $(call expand-required-host-modules,_hif_modules,$(_hif_modules)) \
+  $(filter $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(_hif_modules)))
+endef
+
 # Fails the build if the given list is non-empty, and prints it entries (stripping PRODUCT_OUT).
 # $(1): list of files to print
 # $(2): heading to print on failure
@@ -1105,22 +1140,52 @@
 )
 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
-  product_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
+  ifneq (true,$(ALLOW_MISSING_DEPENDENCIES))
+    # Check to ensure that all modules in PRODUCT_PACKAGES exist (opt in per product)
+    ifeq (true,$(PRODUCT_ENFORCE_PACKAGES_EXIST))
+      _whitelist := $(PRODUCT_ENFORCE_PACKAGES_EXIST_WHITELIST)
+      _modules := $(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 := $(PRODUCT_HOST_PACKAGES)
+      _nonexistant_modules := $(foreach m,$(_modules),\
+        $(if $(filter FAKE,$(ALL_MODULES.$(m).CLASS))$(filter $(HOST_OUT_ROOT)/%,$(ALL_MODULES.$(m).INSTALLED)),,$(m)))
+      $(call maybe-print-list-and-error,$(_nonexistant_modules),\
+        $(INTERNAL_PRODUCT) includes non-existant modules in PRODUCT_HOST_PACKAGES)
+    endif
+  endif
+
+  # Some modules produce only host installed files when building with TARGET_BUILD_APPS
+  ifeq ($(TARGET_BUILD_APPS),)
+    _modules := $(foreach m,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES) \
+                            $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG) \
+                            $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG_ASAN) \
+                            $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_ENG) \
+                            $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_TESTS),\
+                  $(if $(ALL_MODULES.$(m).INSTALLED),\
+                    $(if $(filter-out $(HOST_OUT_ROOT)/%,$(ALL_MODULES.$(m).INSTALLED)),,\
+                      $(m))))
+    $(call maybe-print-list-and-error,$(sort $(_modules)),\
+      Host modules should be in PRODUCT_HOST_PACKAGES$(comma) not PRODUCT_PACKAGES)
+  endif
+
+  product_host_FILES := $(call host-installed-files,$(INTERNAL_PRODUCT))
+  product_target_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
   # WARNING: The product_MODULES variable is depended on by external files.
   product_MODULES := $(_pif_modules)
 
@@ -1130,7 +1195,8 @@
   # Fakes don't get installed, host files are irrelevant, and NDK stubs aren't installed to device.
   static_whitelist_patterns := $(TARGET_OUT_FAKE)/% $(HOST_OUT)/% $(SOONG_OUT_DIR)/ndk/%
   # RROs become REQUIRED by the source module, but are always placed on the vendor partition.
-  static_whitelist_patterns += %__auto_generated_rro.apk
+  static_whitelist_patterns += %__auto_generated_rro_product.apk
+  static_whitelist_patterns += %__auto_generated_rro_vendor.apk
   # Auto-included targets are not considered
   static_whitelist_patterns += $(call module-installed-files,$(call auto-included-modules))
   # $(PRODUCT_OUT)/apex is where shared libraries in APEXes get installed.
@@ -1166,17 +1232,17 @@
     $(eval unused_whitelist := $(filter-out $(files),$(whitelist_patterns))) \
     $(call maybe-print-list-and-error,$(unused_whitelist),$(makefile) includes redundant whitelist entries in its artifact path requirement.) \
     $(eval ### Optionally verify that nothing else produces files inside this artifact path requirement.) \
-    $(eval extra_files := $(filter-out $(files) $(HOST_OUT)/%,$(product_FILES))) \
+    $(eval extra_files := $(filter-out $(files) $(HOST_OUT)/%,$(product_target_FILES))) \
     $(eval files_in_requirement := $(filter $(path_patterns),$(extra_files))) \
     $(eval all_offending_files += $(files_in_requirement)) \
-    $(eval whitelist := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST)) \
+    $(eval whitelist := $(PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST)) \
     $(eval whitelist_patterns := $(call resolve-product-relative-paths,$(whitelist))) \
     $(eval offending_files := $(filter-out $(whitelist_patterns),$(files_in_requirement))) \
-    $(eval enforcement := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS)) \
+    $(eval enforcement := $(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS)) \
     $(if $(enforcement),\
       $(call maybe-print-list-and-error,$(offending_files),\
         $(INTERNAL_PRODUCT) produces files inside $(makefile)s artifact path requirement. \
-        $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT)) \
+        $(PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT)) \
       $(eval unused_whitelist := $(if $(filter true strict,$(enforcement)),\
         $(foreach p,$(whitelist_patterns),$(if $(filter $(p),$(extra_files)),,$(p))))) \
       $(call maybe-print-list-and-error,$(unused_whitelist),$(INTERNAL_PRODUCT) includes redundant artifact path requirement whitelist entries.) \
@@ -1191,14 +1257,16 @@
   # a subset of the module makefiles.  Don't try to build any modules
   # requested by the product, because we probably won't have rules
   # to build them.
-  product_FILES :=
+  product_target_FILES :=
+  product_host_FILES :=
 endif
 
 # TODO: Remove the 3 places in the tree that use ALL_DEFAULT_INSTALLED_MODULES
 # and get rid of it from this list.
 modules_to_install := $(sort \
     $(ALL_DEFAULT_INSTALLED_MODULES) \
-    $(product_FILES) \
+    $(product_target_FILES) \
+    $(product_host_FILES) \
     $(call get-tagged-modules,$(tags_to_install)) \
     $(CUSTOM_MODULES) \
   )
@@ -1228,19 +1296,19 @@
   # Ensure every module listed in PRODUCT_PACKAGES* gets something installed
   # TODO: Should we do this for all builds and not just the sdk?
   dangling_modules :=
-  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES), \
+  $(foreach m, $(PRODUCT_PACKAGES), \
     $(if $(strip $(ALL_MODULES.$(m).INSTALLED) $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).INSTALLED)),,\
       $(eval dangling_modules += $(m))))
   ifneq ($(dangling_modules),)
     $(warning: Modules '$(dangling_modules)' in PRODUCT_PACKAGES have nothing to install!)
   endif
-  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG), \
+  $(foreach m, $(PRODUCT_PACKAGES_DEBUG), \
     $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
       $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_DEBUG has nothing to install!)))
-  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_ENG), \
+  $(foreach m, $(PRODUCT_PACKAGES_ENG), \
     $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
       $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_ENG has nothing to install!)))
-  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_TESTS), \
+  $(foreach m, $(PRODUCT_PACKAGES_TESTS), \
     $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
       $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_TESTS has nothing to install!)))
 endif
@@ -1388,6 +1456,7 @@
     $(INSTALLED_FILES_FILE_RECOVERY) \
     $(INSTALLED_FILES_JSON_RECOVERY) \
     $(INSTALLED_ANDROID_INFO_TXT_TARGET) \
+    auxiliary \
     soong_docs
 
 # dist_files only for putting your library into the dist directory with a full build.
@@ -1453,6 +1522,7 @@
   $(call dist-for-goals, droidcore, \
     $(INTERNAL_UPDATE_PACKAGE_TARGET) \
     $(INTERNAL_OTA_PACKAGE_TARGET) \
+    $(INTERNAL_OTA_METADATA) \
     $(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET) \
     $(BUILT_OTATOOLS_PACKAGE) \
     $(SYMBOLS_ZIP) \
@@ -1507,17 +1577,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.
-    api_xmls := $(addprefix $(TARGET_OUT_COMMON_INTERMEDIATES)/,api.xml system-api.xml test-api.xml)
-    $(api_xmls): $(TARGET_OUT_COMMON_INTERMEDIATES)/%api.xml : frameworks/base/api/%current.txt $(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):
 	$(hide) echo "Converting API file to XML: $@"
 	$(hide) mkdir -p $(dir $@)
-	$(hide) $(APICHECK_COMMAND) -convert2xml $< $@
+	$(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
@@ -1576,8 +1650,15 @@
 .PHONY: findbugs
 findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET)
 
+LSDUMP_PATHS_FILE := $(PRODUCT_OUT)/lsdump_paths.txt
+
 .PHONY: findlsdumps
-findlsdumps: $(FIND_LSDUMPS_FILE)
+findlsdumps: $(LSDUMP_PATHS_FILE) $(LSDUMP_PATHS)
+
+$(LSDUMP_PATHS_FILE): PRIVATE_LSDUMP_PATHS := $(LSDUMP_PATHS)
+$(LSDUMP_PATHS_FILE):
+	@echo "Generate $@"
+	@rm -rf $@ && echo "$(PRIVATE_LSDUMP_PATHS)" | sed -e 's/ /\n/g' > $@
 
 .PHONY: check-elf-files
 check-elf-files:
@@ -1589,15 +1670,10 @@
 	@echo "$(call module-names-for-tag-list,$(ALL_MODULE_TAGS))" | \
 	      tr -s ' ' '\n' | sort -u | $(COLUMN)
 
-.PHONY: dump-products
-dump-products:
-	$(dump-products)
-	@echo Successfully dumped products
-
 .PHONY: dump-files
 dump-files:
-	$(info product_FILES for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)
-	$(foreach p,$(sort $(product_FILES)),$(info :   $(p)))
+	$(info product_target_FILES for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)
+	$(foreach p,$(sort $(product_target_FILES)),$(info :   $(p)))
 	@echo Successfully dumped product file list
 
 .PHONY: nothing
diff --git a/core/module_arch_supported.mk b/core/module_arch_supported.mk
index 62e2643..7ebc8f9 100644
--- a/core/module_arch_supported.mk
+++ b/core/module_arch_supported.mk
@@ -62,11 +62,11 @@
 
 ifdef LOCAL_IS_HOST_MODULE
 ifneq (,$(LOCAL_MODULE_HOST_OS))
+  ifneq (,$(filter windows,$(LOCAL_MODULE_HOST_OS)))
+    $(call pretty-error,Windows is only supported in Android.bp files)
+  endif
   ifeq (,$(filter $($(my_prefix)OS),$(LOCAL_MODULE_HOST_OS)))
     my_module_arch_supported := false
   endif
-else ifeq ($($(my_prefix)OS),windows)
-  # If LOCAL_MODULE_HOST_OS is empty, only linux and darwin are supported
-  my_module_arch_supported := false
 endif
 endif
diff --git a/core/native_benchmark.mk b/core/native_benchmark.mk
index e73bcad..073d8dd 100644
--- a/core/native_benchmark.mk
+++ b/core/native_benchmark.mk
@@ -6,9 +6,6 @@
 
 LOCAL_STATIC_LIBRARIES += libgoogle-benchmark
 
-LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_METRIC_TESTS)/$(LOCAL_MODULE)
-LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_METRIC_TESTS)/$(LOCAL_MODULE)
-
 ifndef LOCAL_MULTILIB
 ifndef LOCAL_32_BIT_ONLY
 LOCAL_MULTILIB := both
diff --git a/core/native_test_config_template.xml b/core/native_test_config_template.xml
index a88d57c..f3d3231 100644
--- a/core/native_test_config_template.xml
+++ b/core/native_test_config_template.xml
@@ -17,6 +17,9 @@
 <configuration description="Runs {MODULE}.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
+
+    {EXTRA_OPTIONS}
+
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
diff --git a/core/ninja_config.mk b/core/ninja_config.mk
index 684ab9f..e9e89c3 100644
--- a/core/ninja_config.mk
+++ b/core/ninja_config.mk
@@ -50,7 +50,6 @@
 	user \
 	userdataimage \
 	userdebug \
-	valgrind-test-art% \
 	vts \
 	win_sdk \
 	winsdk-tools
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 9ddbd1b..e27f6ce 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -109,56 +109,55 @@
 # 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
+
+product_package_overlays := $(strip \
     $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
-      $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \
+      $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
+device_package_overlays := $(strip \
     $(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_product :=
+runtime_resource_overlays_vendor :=
 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
+    # The PRODUCT_ exclusion variable applies to both inclusion variables..
+    static_resource_overlays += $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(product_package_overlays))
+    static_resource_overlays += $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(device_package_overlays))
   endif
+  runtime_resource_overlays_product := $(filter-out $(static_resource_overlays),$(product_package_overlays))
+  runtime_resource_overlays_vendor := $(filter-out $(static_resource_overlays),$(device_package_overlays))
 else
-LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR)
+  static_resource_overlays := $(product_package_overlays) $(device_package_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)/, \
@@ -332,6 +331,12 @@
 LOCAL_DEX_PREOPT := false
 endif
 
+# Default to use uncompressed native libraries in APKs if minSdkVersion >= marshmallow
+ifndef LOCAL_USE_EMBEDDED_NATIVE_LIBS
+  LOCAL_USE_EMBEDDED_NATIVE_LIBS := $(call math_gt_or_eq, \
+    $(patsubst $(PLATFORM_VERSION_CODENAME),100,$(call module-min-sdk-version)),23)
+endif
+
 include $(BUILD_SYSTEM)/android_manifest.mk
 
 resource_export_package :=
@@ -576,9 +581,11 @@
 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
 
 ifeq ($(module_run_appcompat),true)
 $(LOCAL_BUILT_MODULE) : $(appcompat-files)
@@ -610,6 +617,7 @@
 $(LOCAL_BUILT_MODULE) : | $(DEXPREOPT_STRIP_DEPS)
 $(LOCAL_BUILT_MODULE): .KATI_DEPFILE := $(LOCAL_BUILT_MODULE).d
 endif
+$(LOCAL_BUILT_MODULE): PRIVATE_USE_EMBEDDED_NATIVE_LIBS := $(LOCAL_USE_EMBEDDED_NATIVE_LIBS)
 $(LOCAL_BUILT_MODULE):
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
 	rm -rf $@.parts
@@ -620,7 +628,7 @@
 	$(call create-assets-package,$@.parts/apk.zip)
 endif  # LOCAL_USE_AAPT2
 ifneq ($(jni_shared_libraries),)
-	$(call create-jni-shared-libs-package,$@.parts/jni.zip)
+	$(call create-jni-shared-libs-package,$@.parts/jni.zip,$(PRIVATE_USE_EMBEDDED_NATIVE_LIBS))
 endif
 ifeq ($(full_classes_jar),)
 # We don't build jar, need to add the Java resources here.
@@ -762,7 +770,7 @@
 $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
   $(eval my_compat_dist_$(suite) := $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
     $(foreach s,$(my_split_suffixes),\
-      $(intermediates)/package_$(s).apk:$(dir)/$(LOCAL_MODULE)_$(s).apk))))
+      $(call compat-copy-pair,$(intermediates)/package_$(s).apk,$(dir)/$(LOCAL_MODULE)_$(s).apk)))))
 
 $(call create-suite-dependencies)
 
@@ -780,7 +788,7 @@
 # Reset internal variables.
 all_res_assets :=
 
-ifdef enforce_rro_enabled
+ifneq (,$(runtime_resource_overlays_product)$(runtime_resource_overlays_vendor))
   ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
     enforce_rro_use_res_lib := true
   else
@@ -795,11 +803,24 @@
     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) \
+  ifdef runtime_resource_overlays_product
+    $(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_product), \
+        product \
     )
-endif  # enforce_rro_enabled
+  endif
+  ifdef runtime_resource_overlays_vendor
+    $(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_vendor), \
+        vendor \
+    )
+  endif
+endif
diff --git a/core/pdk_config.mk b/core/pdk_config.mk
index 383c11a..ce78ece 100644
--- a/core/pdk_config.mk
+++ b/core/pdk_config.mk
@@ -20,8 +20,6 @@
   target/common/obj/JAVA_LIBRARIES/conscrypt_intermediates \
   target/common/obj/JAVA_LIBRARIES/core-oj_intermediates \
   target/common/obj/JAVA_LIBRARIES/core-libart_intermediates \
-  target/common/obj/JAVA_LIBRARIES/legacy-test_intermediates \
-  target/common/obj/JAVA_LIBRARIES/legacy-android-test_intermediates \
   target/common/obj/JAVA_LIBRARIES/ext_intermediates \
   target/common/obj/JAVA_LIBRARIES/framework_intermediates \
   target/common/obj/JAVA_LIBRARIES/hwbinder_intermediates \
diff --git a/core/prebuilt.mk b/core/prebuilt.mk
index fb08625..9d284fb 100644
--- a/core/prebuilt.mk
+++ b/core/prebuilt.mk
@@ -57,37 +57,4 @@
 
 LOCAL_2ND_ARCH_VAR_PREFIX :=
 
-ifdef LOCAL_IS_HOST_MODULE
-ifdef HOST_CROSS_OS
-ifneq (,$(filter EXECUTABLES STATIC_LIBRARIES SHARED_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)))
-my_prefix := HOST_CROSS_
-LOCAL_HOST_PREFIX := $(my_prefix)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-# host cross compilation is supported
-LOCAL_BUILT_MODULE :=
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-include $(BUILD_SYSTEM)/prebuilt_internal.mk
-endif
-LOCAL_HOST_PREFIX :=
-endif
-
-ifdef HOST_CROSS_2ND_ARCH
-my_prefix := HOST_CROSS_
-LOCAL_2ND_ARCH_VAR_PREFIX := $($(my_prefix)2ND_ARCH_VAR_PREFIX)
-LOCAL_HOST_PREFIX := $(my_prefix)
-include $(BUILD_SYSTEM)/module_arch_supported.mk
-ifeq ($(my_module_arch_supported),true)
-LOCAL_BUILT_MODULE :=
-LOCAL_INSTALLED_MODULE :=
-LOCAL_INTERMEDIATE_TARGETS :=
-include $(BUILD_SYSTEM)/prebuilt_internal.mk
-endif
-LOCAL_HOST_PREFIX :=
-LOCAL_2ND_ARCH_VAR_PREFIX :=
-endif
-endif
-endif
-
 my_module_arch_supported :=
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 0b48a77..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,42 +76,11 @@
   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
-  module_run_appcompat := true
-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 :=
 
 ifneq ($(filter true keep_symbols no_debuglink mini-debug-info,$(my_strip_module)),)
   ifdef LOCAL_IS_HOST_MODULE
@@ -121,6 +97,12 @@
   include $(BUILD_SYSTEM)/dynamic_binary.mk
   built_module := $(linked_module)
 
+  ifneq ($(LOCAL_SDK_VERSION),)
+    # binary.mk filters out NDK_MIGRATED_LIBS from my_shared_libs, thus those NDK libs are not added
+    # to DEPENDENCIES_ON_SHARED_LIBRARIES. Assign $(my_ndk_shared_libraries_fullpath) to
+    # my_check_elf_file_shared_lib_files so that check_elf_file.py can see those NDK stub libs.
+    my_check_elf_file_shared_lib_files := $(my_ndk_shared_libraries_fullpath)
+  endif
 else  # my_strip_module not true
   include $(BUILD_SYSTEM)/base_rules.mk
   built_module := $(LOCAL_BUILT_MODULE)
@@ -168,14 +150,29 @@
 include $(BUILD_SYSTEM)/link_type.mk
 endif  # prebuilt_module_is_a_library
 
-# Check prebuilt ELF binaries.
-include $(BUILD_SYSTEM)/check_elf_file.mk
-
 # The real dependency will be added after all Android.mks are loaded and the install paths
 # of the shared libraries are determined.
 ifdef LOCAL_INSTALLED_MODULE
-ifdef LOCAL_SHARED_LIBRARIES
-my_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
+ifdef LOCAL_IS_HOST_MODULE
+    ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
+        my_system_shared_libraries :=
+    else
+        my_system_shared_libraries := $(LOCAL_SYSTEM_SHARED_LIBRARIES)
+    endif
+else
+    ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
+        my_system_shared_libraries := libc libm libdl
+    else
+        my_system_shared_libraries := $(LOCAL_SYSTEM_SHARED_LIBRARIES)
+        my_system_shared_libraries := $(patsubst libc,libc libdl,$(my_system_shared_libraries))
+    endif
+endif
+
+my_shared_libraries := \
+    $(filter-out $(my_system_shared_libraries),$(LOCAL_SHARED_LIBRARIES)) \
+    $(my_system_shared_libraries)
+
+ifdef my_shared_libraries
 # Extra shared libraries introduced by LOCAL_CXX_STL.
 include $(BUILD_SYSTEM)/cxx_stl_setup.mk
 ifdef LOCAL_USE_VNDK
@@ -185,12 +182,15 @@
 $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)DEPENDENCIES_ON_SHARED_LIBRARIES += \
   $(my_register_name):$(LOCAL_INSTALLED_MODULE):$(subst $(space),$(comma),$(my_shared_libraries))
 endif
-endif
+endif  # my_shared_libraries
 
 # We need to enclose the above export_includes and my_built_shared_libraries in
 # "my_strip_module not true" because otherwise the rules are defined in dynamic_binary.mk.
 endif  # my_strip_module not true
 
+# Check prebuilt ELF binaries.
+include $(BUILD_SYSTEM)/check_elf_file.mk
+
 ifeq ($(NATIVE_COVERAGE),true)
 ifneq (,$(strip $(LOCAL_PREBUILT_COVERAGE_ARCHIVE)))
   $(eval $(call copy-one-file,$(LOCAL_PREBUILT_COVERAGE_ARCHIVE),$(intermediates)/$(LOCAL_MODULE).gcnodir))
@@ -219,249 +219,19 @@
 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.
+
+ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),)
+  $(call pretty-error,Modules in PRODUCT_BOOT_JARS must be defined in Android.bp files)
+endif
+
 #######################################
 # defines built_odex along with rule to install odex
 include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
 #######################################
 ifdef LOCAL_DEX_PREOPT
-ifneq ($(dexpreopt_boot_jar_module),) # boot jar
-# boot jar's rules are defined in dex_preopt.mk
-dexpreopted_boot_jar := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(dexpreopt_boot_jar_module)_nodex.jar
-$(built_module) : $(dexpreopted_boot_jar)
-	$(call copy-file-to-target)
-
-# For libart boot jars, we don't have .odex files.
-else # ! boot jar
 
 $(built_module): PRIVATE_STRIP_SCRIPT := $(intermediates)/strip.sh
 $(built_module): $(intermediates)/strip.sh
@@ -470,7 +240,6 @@
 $(built_module): $(my_prebuilt_src_file)
 	$(PRIVATE_STRIP_SCRIPT) $< $@
 
-endif # boot jar
 else # ! LOCAL_DEX_PREOPT
 $(built_module) : $(my_prebuilt_src_file)
 	$(call copy-file-to-target)
@@ -677,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 c3cbb0c..29bd1d1 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -92,7 +92,7 @@
    ) \
   $(eval PRODUCT_MAKEFILES :=) \
   $(eval LOCAL_DIR :=) \
-  $(eval COMMON_LUNCH_CHOICES := $(sort $(_COMMON_LUNCH_CHOICES) $(LUNCH_MENU_CHOICES))) \
+  $(eval COMMON_LUNCH_CHOICES := $(sort $(_COMMON_LUNCH_CHOICES))) \
   $(eval _COMMON_LUNCH_CHOICES :=) \
  )
 endef
@@ -106,134 +106,248 @@
 $(call get-product-makefiles,$(_find-android-products-files))
 endef
 
-#
-# Functions for including product makefiles
-#
+_product_var_list :=
+_product_var_list += PRODUCT_NAME
+_product_var_list += PRODUCT_MODEL
 
-_product_var_list := \
-    PRODUCT_NAME \
-    PRODUCT_MODEL \
-    PRODUCT_LOCALES \
-    PRODUCT_AAPT_CONFIG \
-    PRODUCT_AAPT_PREF_CONFIG \
-    PRODUCT_AAPT_PREBUILT_DPI \
-    PRODUCT_PACKAGES \
-    PRODUCT_PACKAGES_DEBUG \
-    PRODUCT_PACKAGES_DEBUG_ASAN \
-    PRODUCT_PACKAGES_ENG \
-    PRODUCT_PACKAGES_TESTS \
-    PRODUCT_DEVICE \
-    PRODUCT_MANUFACTURER \
-    PRODUCT_BRAND \
-    PRODUCT_PROPERTY_OVERRIDES \
-    PRODUCT_DEFAULT_PROPERTY_OVERRIDES \
-    PRODUCT_PRODUCT_PROPERTIES \
-    PRODUCT_PRODUCT_SERVICES_PROPERTIES \
-    PRODUCT_ODM_PROPERTIES \
-    PRODUCT_CHARACTERISTICS \
-    PRODUCT_COPY_FILES \
-    PRODUCT_OTA_PUBLIC_KEYS \
-    PRODUCT_EXTRA_RECOVERY_KEYS \
-    PRODUCT_PACKAGE_OVERLAYS \
-    DEVICE_PACKAGE_OVERLAYS \
-    PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS \
-    PRODUCT_ENFORCE_RRO_TARGETS \
-    PRODUCT_SDK_ATREE_FILES \
-    PRODUCT_SDK_ADDON_NAME \
-    PRODUCT_SDK_ADDON_COPY_FILES \
-    PRODUCT_SDK_ADDON_COPY_MODULES \
-    PRODUCT_SDK_ADDON_DOC_MODULES \
-    PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP \
-    PRODUCT_SOONG_NAMESPACES \
-    PRODUCT_DEFAULT_WIFI_CHANNELS \
-    PRODUCT_DEFAULT_DEV_CERTIFICATE \
-    PRODUCT_RESTRICT_VENDOR_FILES \
-    PRODUCT_VENDOR_KERNEL_HEADERS \
-    PRODUCT_BOOT_JARS \
-    PRODUCT_SUPPORTS_BOOT_SIGNER \
-    PRODUCT_SUPPORTS_VBOOT \
-    PRODUCT_SUPPORTS_VERITY \
-    PRODUCT_SUPPORTS_VERITY_FEC \
-    PRODUCT_OEM_PROPERTIES \
-    PRODUCT_SYSTEM_DEFAULT_PROPERTIES \
-    PRODUCT_SYSTEM_PROPERTY_BLACKLIST \
-    PRODUCT_VENDOR_PROPERTY_BLACKLIST \
-    PRODUCT_SYSTEM_SERVER_APPS \
-    PRODUCT_SYSTEM_SERVER_JARS \
-    PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK \
-    PRODUCT_DEXPREOPT_SPEED_APPS \
-    PRODUCT_LOADED_BY_PRIVILEGED_MODULES \
-    PRODUCT_VBOOT_SIGNING_KEY \
-    PRODUCT_VBOOT_SIGNING_SUBKEY \
-    PRODUCT_VERITY_SIGNING_KEY \
-    PRODUCT_SYSTEM_VERITY_PARTITION \
-    PRODUCT_VENDOR_VERITY_PARTITION \
-    PRODUCT_PRODUCT_VERITY_PARTITION \
-    PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION \
-    PRODUCT_ODM_VERITY_PARTITION \
-    PRODUCT_SYSTEM_SERVER_DEBUG_INFO \
-    PRODUCT_OTHER_JAVA_DEBUG_INFO \
-    PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
-    PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER \
-    PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
-    PRODUCT_DEX_PREOPT_BOOT_FLAGS \
-    PRODUCT_DEX_PREOPT_PROFILE_DIR \
-    PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION \
-    PRODUCT_DEX_PREOPT_GENERATE_DM_FILES \
+# The resoure configuration options to use for this product.
+_product_var_list += PRODUCT_LOCALES
+_product_var_list += PRODUCT_AAPT_CONFIG
+_product_var_list += PRODUCT_AAPT_PREF_CONFIG
+_product_var_list += PRODUCT_AAPT_PREBUILT_DPI
+_product_var_list += PRODUCT_HOST_PACKAGES
+_product_var_list += PRODUCT_PACKAGES
+_product_var_list += PRODUCT_PACKAGES_DEBUG
+_product_var_list += PRODUCT_PACKAGES_DEBUG_ASAN
+_product_var_list += PRODUCT_PACKAGES_ENG
+_product_var_list += PRODUCT_PACKAGES_TESTS
+
+# The device that this product maps to.
+_product_var_list += PRODUCT_DEVICE
+_product_var_list += PRODUCT_MANUFACTURER
+_product_var_list += PRODUCT_BRAND
+
+# These PRODUCT_SYSTEM_* flags, if defined, are used in place of the
+# corresponding PRODUCT_* flags for the sysprops on /system.
+_product_var_list += \
+    PRODUCT_SYSTEM_NAME \
+    PRODUCT_SYSTEM_MODEL \
+    PRODUCT_SYSTEM_DEVICE \
+    PRODUCT_SYSTEM_BRAND \
+    PRODUCT_SYSTEM_MANUFACTURER \
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+_product_var_list += PRODUCT_PROPERTY_OVERRIDES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop
+_product_var_list += PRODUCT_DEFAULT_PROPERTY_OVERRIDES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to build.prop of product partition
+_product_var_list += PRODUCT_PRODUCT_PROPERTIES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to build.prop of product partition
+_product_var_list += PRODUCT_PRODUCT_SERVICES_PROPERTIES
+_product_var_list += PRODUCT_ODM_PROPERTIES
+_product_var_list += PRODUCT_CHARACTERISTICS
+
+# A list of words like <source path>:<destination path>[:<owner>].
+# The file at the source path should be copied to the destination path
+# when building  this product.  <destination path> is relative to
+# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".
+# The rules for these copy steps are defined in build/make/core/Makefile.
+# The optional :<owner> is used to indicate the owner of a vendor file.
+_product_var_list += PRODUCT_COPY_FILES
+
+# The OTA key(s) specified by the product config, if any.  The names
+# of these keys are stored in the target-files zip so that post-build
+# signing tools can substitute them for the test key embedded by
+# default.
+_product_var_list += PRODUCT_OTA_PUBLIC_KEYS
+_product_var_list += PRODUCT_EXTRA_RECOVERY_KEYS
+
+# Should we use the default resources or add any product specific overlays
+_product_var_list += PRODUCT_PACKAGE_OVERLAYS
+_product_var_list += DEVICE_PACKAGE_OVERLAYS
+
+# Resource overlay list which must be excluded from enforcing RRO.
+_product_var_list += PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS
+
+# Package list to apply enforcing RRO.
+_product_var_list += PRODUCT_ENFORCE_RRO_TARGETS
+
+_product_var_list += PRODUCT_SDK_ATREE_FILES
+_product_var_list += PRODUCT_SDK_ADDON_NAME
+_product_var_list += PRODUCT_SDK_ADDON_COPY_FILES
+_product_var_list += PRODUCT_SDK_ADDON_COPY_MODULES
+_product_var_list += PRODUCT_SDK_ADDON_DOC_MODULES
+_product_var_list += PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP
+
+# which Soong namespaces to export to Make
+_product_var_list += PRODUCT_SOONG_NAMESPACES
+
+_product_var_list += PRODUCT_DEFAULT_WIFI_CHANNELS
+_product_var_list += PRODUCT_DEFAULT_DEV_CERTIFICATE
+_product_var_list += PRODUCT_RESTRICT_VENDOR_FILES
+
+# The list of product-specific kernel header dirs
+_product_var_list += PRODUCT_VENDOR_KERNEL_HEADERS
+
+# A list of module names of BOOTCLASSPATH (jar files)
+_product_var_list += PRODUCT_BOOT_JARS
+_product_var_list += PRODUCT_SUPPORTS_BOOT_SIGNER
+_product_var_list += PRODUCT_SUPPORTS_VBOOT
+_product_var_list += PRODUCT_SUPPORTS_VERITY
+_product_var_list += PRODUCT_SUPPORTS_VERITY_FEC
+_product_var_list += PRODUCT_OEM_PROPERTIES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop of system partition
+_product_var_list += PRODUCT_SYSTEM_DEFAULT_PROPERTIES
+
+_product_var_list += PRODUCT_SYSTEM_PROPERTY_BLACKLIST
+_product_var_list += PRODUCT_VENDOR_PROPERTY_BLACKLIST
+_product_var_list += PRODUCT_SYSTEM_SERVER_APPS
+_product_var_list += PRODUCT_SYSTEM_SERVER_JARS
+
+# All of the apps that we force preopt, this overrides WITH_DEXPREOPT.
+_product_var_list += PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK
+_product_var_list += PRODUCT_DEXPREOPT_SPEED_APPS
+_product_var_list += PRODUCT_LOADED_BY_PRIVILEGED_MODULES
+_product_var_list += PRODUCT_VBOOT_SIGNING_KEY
+_product_var_list += PRODUCT_VBOOT_SIGNING_SUBKEY
+_product_var_list += PRODUCT_VERITY_SIGNING_KEY
+_product_var_list += PRODUCT_SYSTEM_VERITY_PARTITION
+_product_var_list += PRODUCT_VENDOR_VERITY_PARTITION
+_product_var_list += PRODUCT_PRODUCT_VERITY_PARTITION
+_product_var_list += PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION
+_product_var_list += PRODUCT_ODM_VERITY_PARTITION
+_product_var_list += PRODUCT_SYSTEM_SERVER_DEBUG_INFO
+_product_var_list += PRODUCT_OTHER_JAVA_DEBUG_INFO
+
+# Per-module dex-preopt configs.
+_product_var_list += PRODUCT_DEX_PREOPT_MODULE_CONFIGS
+_product_var_list += PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
+_product_var_list += PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
+_product_var_list += PRODUCT_DEX_PREOPT_BOOT_FLAGS
+_product_var_list += PRODUCT_DEX_PREOPT_PROFILE_DIR
+_product_var_list += PRODUCT_DEX_PREOPT_GENERATE_DM_FILES
+_product_var_list += PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING
+
+# Boot image options.
+_product_var_list += \
     PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE \
-    PRODUCT_SYSTEM_SERVER_COMPILER_FILTER \
-    PRODUCT_SANITIZER_MODULE_CONFIGS \
-    PRODUCT_SYSTEM_BASE_FS_PATH \
-    PRODUCT_VENDOR_BASE_FS_PATH \
-    PRODUCT_PRODUCT_BASE_FS_PATH \
-    PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH \
-    PRODUCT_ODM_BASE_FS_PATH \
-    PRODUCT_SHIPPING_API_LEVEL \
-    VENDOR_PRODUCT_RESTRICT_VENDOR_FILES \
-    VENDOR_EXCEPTION_MODULES \
-    VENDOR_EXCEPTION_PATHS \
-    PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD \
-    PRODUCT_ART_USE_READ_BARRIER \
-    PRODUCT_IOT \
-    PRODUCT_SYSTEM_HEADROOM \
-    PRODUCT_MINIMIZE_JAVA_DEBUG_INFO \
-    PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS \
-    PRODUCT_ADB_KEYS \
-    PRODUCT_CFI_INCLUDE_PATHS \
-    PRODUCT_CFI_EXCLUDE_PATHS \
-    PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE \
-    PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE \
-    PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS \
-    PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT \
-    PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST \
-    PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT \
-    PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST \
+    PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION \
+
+_product_var_list += PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
+# Per-module sanitizer configs
+_product_var_list += PRODUCT_SANITIZER_MODULE_CONFIGS
+_product_var_list += PRODUCT_SYSTEM_BASE_FS_PATH
+_product_var_list += PRODUCT_VENDOR_BASE_FS_PATH
+_product_var_list += PRODUCT_PRODUCT_BASE_FS_PATH
+_product_var_list += PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH
+_product_var_list += PRODUCT_ODM_BASE_FS_PATH
+_product_var_list += PRODUCT_SHIPPING_API_LEVEL
+_product_var_list += VENDOR_PRODUCT_RESTRICT_VENDOR_FILES
+_product_var_list += VENDOR_EXCEPTION_MODULES
+_product_var_list += VENDOR_EXCEPTION_PATHS
+
+# Whether the product wants to ship libartd. For rules and meaning, see art/Android.mk.
+_product_var_list += PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD
+
+# Make this art variable visible to soong_config.mk.
+_product_var_list += PRODUCT_ART_USE_READ_BARRIER
+
+# Whether the product is an Android Things variant.
+_product_var_list += PRODUCT_IOT
+
+# Add reserved headroom to a system image.
+_product_var_list += PRODUCT_SYSTEM_HEADROOM
+
+# Whether to save disk space by minimizing java debug info
+_product_var_list += PRODUCT_MINIMIZE_JAVA_DEBUG_INFO
+
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=integer_overflow
+_product_var_list += PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS
+
+_product_var_list += PRODUCT_ADB_KEYS
+
+# Whether any paths should have CFI enabled for components
+_product_var_list += PRODUCT_CFI_INCLUDE_PATHS
+
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=cfi
+_product_var_list += PRODUCT_CFI_EXCLUDE_PATHS
+
+# Whether the Scudo hardened allocator is disabled platform-wide
+_product_var_list += PRODUCT_DISABLE_SCUDO
+
+# A flag to override PRODUCT_COMPATIBLE_PROPERTY
+_product_var_list += PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE
+
+# Whether the whitelist of actionable compatible properties should be disabled or not
+_product_var_list += PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE
+_product_var_list += PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
+_product_var_list += PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT
+_product_var_list += PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST
+_product_var_list += PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT
+_product_var_list += PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST
+
+# List of modules that should be forcefully unmarked from being LOCAL_PRODUCT_MODULE, and hence
+# installed on /system directory by default.
+_product_var_list += PRODUCT_FORCE_PRODUCT_MODULES_TO_SYSTEM_PARTITION
+
+# When this is true, dynamic partitions is retrofitted on a device that has
+# already been launched without dynamic partitions. Otherwise, the device
+# is launched with dynamic partitions.
+# This flag implies PRODUCT_USE_DYNAMIC_PARTITIONS.
+_product_var_list += PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
+
+# Other dynamic partition feature flags.PRODUCT_USE_DYNAMIC_PARTITION_SIZE and
+# PRODUCT_BUILD_SUPER_PARTITION default to the value of PRODUCT_USE_DYNAMIC_PARTITIONS.
+_product_var_list += \
+    PRODUCT_USE_DYNAMIC_PARTITIONS \
     PRODUCT_USE_DYNAMIC_PARTITION_SIZE \
     PRODUCT_BUILD_SUPER_PARTITION \
-    PRODUCT_FORCE_PRODUCT_MODULES_TO_SYSTEM_PARTITION \
-    PRODUCT_USE_DYNAMIC_PARTITIONS \
-    PRODUCT_RETROFIT_DYNAMIC_PARTITIONS \
-    PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS \
-    PRODUCT_XOM_EXCLUDE_PATHS \
-    PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES \
-    PRODUCT_BUILD_SYSTEM_IMAGE \
-    PRODUCT_BUILD_SYSTEM_OTHER_IMAGE \
-    PRODUCT_BUILD_VENDOR_IMAGE \
-    PRODUCT_BUILD_PRODUCT_IMAGE \
-    PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE \
-    PRODUCT_BUILD_ODM_IMAGE \
-    PRODUCT_BUILD_CACHE_IMAGE \
-    PRODUCT_BUILD_RAMDISK_IMAGE \
-    PRODUCT_BUILD_USERDATA_IMAGE \
-    PRODUCT_UPDATABLE_BOOT_MODULES \
-    PRODUCT_UPDATABLE_BOOT_LOCATIONS \
-    PRODUCT_CHECK_ELF_FILES \
+
+# If set, kernel configuration requirements are present in OTA package (and will be enforced
+# during OTA). Otherwise, kernel configuration requirements are enforced in VTS.
+# Devices that checks the running kernel (instead of the kernel in OTA package) should not
+# set this variable to prevent OTA failures.
+_product_var_list += PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
+
+# Whether any paths are excluded from being set XOM when ENABLE_XOM=true
+_product_var_list += PRODUCT_XOM_EXCLUDE_PATHS
+_product_var_list += PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
+_product_var_list += PRODUCT_PACKAGE_NAME_OVERRIDES
+_product_var_list += PRODUCT_CERTIFICATE_OVERRIDES
+_product_var_list += PRODUCT_BUILD_SYSTEM_IMAGE
+_product_var_list += PRODUCT_BUILD_SYSTEM_OTHER_IMAGE
+_product_var_list += PRODUCT_BUILD_VENDOR_IMAGE
+_product_var_list += PRODUCT_BUILD_PRODUCT_IMAGE
+_product_var_list += PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE
+_product_var_list += PRODUCT_BUILD_ODM_IMAGE
+_product_var_list += PRODUCT_BUILD_CACHE_IMAGE
+_product_var_list += PRODUCT_BUILD_RAMDISK_IMAGE
+_product_var_list += PRODUCT_BUILD_USERDATA_IMAGE
+_product_var_list += PRODUCT_UPDATABLE_BOOT_MODULES
+_product_var_list += PRODUCT_UPDATABLE_BOOT_LOCATIONS
+
+# Whether the product would like to check prebuilt ELF files.
+_product_var_list += PRODUCT_CHECK_ELF_FILES
+.KATI_READONLY := _product_var_list
 
 define dump-product
-$(info ==== $(1) ====)\
+$(warning ==== $(1) ====)\
 $(foreach v,$(_product_var_list),\
-$(info PRODUCTS.$(1).$(v) := $(PRODUCTS.$(1).$(v))))\
-$(info --------)
+$(warning PRODUCTS.$(1).$(v) := $(PRODUCTS.$(1).$(v))))\
+$(warning --------)
 endef
 
 define dump-products
@@ -241,6 +355,10 @@
 endef
 
 #
+# Functions for including product makefiles
+#
+
+#
 # $(1): product to inherit
 #
 # To be called from product makefiles, and is later evaluated during the import-nodes
@@ -362,90 +480,44 @@
 $(strip $(call _resolve-short-product-name,$(1)))
 endef
 
+# BoardConfig variables that are also inherited in product mks. Should ideally
+# be cleaned up to not be product variables.
+_readonly_late_variables := \
+  DEVICE_PACKAGE_OVERLAYS \
+  WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY \
 
-_product_stash_var_list := $(_product_var_list) \
-	PRODUCT_BOOTCLASSPATH \
-	PRODUCT_SYSTEM_SERVER_CLASSPATH \
-	TARGET_ARCH \
-	TARGET_ARCH_VARIANT \
-	TARGET_CPU_VARIANT \
-	TARGET_BOARD_PLATFORM \
-	TARGET_BOARD_PLATFORM_GPU \
-	TARGET_BOARD_KERNEL_HEADERS \
-	TARGET_DEVICE_KERNEL_HEADERS \
-	TARGET_PRODUCT_KERNEL_HEADERS \
-	TARGET_BOOTLOADER_BOARD_NAME \
-	TARGET_NO_BOOTLOADER \
-	TARGET_NO_KERNEL \
-	TARGET_NO_RECOVERY \
-	TARGET_NO_RADIOIMAGE \
-	TARGET_HARDWARE_3D \
-	TARGET_CPU_ABI \
-	TARGET_CPU_ABI2 \
+# Modified internally in the build system
+_readonly_late_variables += \
+  PRODUCT_COPY_FILES \
+  PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING \
+  PRODUCT_DEX_PREOPT_BOOT_FLAGS \
 
-
-_product_stash_var_list += \
-	BOARD_WPA_SUPPLICANT_DRIVER \
-	BOARD_WLAN_DEVICE \
-	BOARD_USES_GENERIC_AUDIO \
-	BOARD_KERNEL_CMDLINE \
-	BOARD_KERNEL_BASE \
-	BOARD_HAVE_BLUETOOTH \
-	BOARD_VENDOR_USE_AKMD \
-	BOARD_EGL_CFG \
-	BOARD_BOOTIMAGE_PARTITION_SIZE \
-	BOARD_RECOVERYIMAGE_PARTITION_SIZE \
-	BOARD_SYSTEMIMAGE_PARTITION_SIZE \
-	BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_USERDATAIMAGE_PARTITION_SIZE \
-	BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_CACHEIMAGE_PARTITION_SIZE \
-	BOARD_FLASH_BLOCK_SIZE \
-	BOARD_VENDORIMAGE_PARTITION_SIZE \
-	BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_PRODUCTIMAGE_PARTITION_SIZE \
-	BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE \
-	BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_ODMIMAGE_PARTITION_SIZE \
-	BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_INSTALLER_CMDLINE \
-
-
-_product_stash_var_list += \
-	DEFAULT_SYSTEM_DEV_CERTIFICATE \
-	WITH_DEXPREOPT \
-	WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
-
-# Logical partitions related variables.
-_dynamic_partitions_var_list += \
-	BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_SUPER_PARTITION_SIZE \
-	BOARD_SUPER_PARTITION_GROUPS \
-
-_product_stash_var_list += $(_dynamic_partitions_var_list)
-_product_strip_var_list := $(_dynamic_partitions_var_list)
+_readonly_early_variables := $(filter-out $(_readonly_late_variables),$(_product_var_list))
 
 #
 # Mark the variables in _product_stash_var_list as readonly
 #
-define readonly-product-vars
-$(foreach v,$(_product_stash_var_list), \
-	$(eval $(v) ?=) \
-	$(eval .KATI_READONLY := $(v)) \
+define readonly-variables
+$(foreach v,$(1), \
+  $(eval $(v) ?=) \
+  $(eval .KATI_READONLY := $(v)) \
  )
 endef
+define readonly-product-vars
+$(call readonly-variables,$(_readonly_early_variables))
+endef
+
+define readonly-final-product-vars
+$(call readonly-variables,$(_readonly_late_variables))
+endef
 
 #
 # Strip the variables in _product_strip_var_list
 #
 define strip-product-vars
-$(foreach v,$(_product_strip_var_list),$(eval $(v) := $(strip $($(v)))))
+$(foreach v,$(_product_var_list), \
+  $(eval $(v) := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).$(v)))) \
+)
 endef
 
 define add-to-product-copy-files-if-exists
diff --git a/core/product_config.mk b/core/product_config.mk
index 1f44692..a088f06 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -237,6 +237,10 @@
 # Sanity check
 $(check-all-products)
 
+ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
+$(dump-products)
+endif
+
 # Convert a short name like "sooner" into the path to the product
 # file defining that product.
 #
@@ -248,29 +252,19 @@
 all_product_makefiles :=
 all_product_configs :=
 
+############################################################################
+# Strip and assign the PRODUCT_ variables.
+$(call strip-product-vars)
 
 #############################################################################
+# Sanity check and assign default values
 
-# A list of module names of BOOTCLASSPATH (jar files)
-PRODUCT_BOOT_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BOOT_JARS))
-PRODUCT_UPDATABLE_BOOT_MODULES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_UPDATABLE_BOOT_MODULES))
-PRODUCT_UPDATABLE_BOOT_LOCATIONS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_UPDATABLE_BOOT_LOCATIONS))
-PRODUCT_SYSTEM_SERVER_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_JARS))
-PRODUCT_SYSTEM_SERVER_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_APPS))
-PRODUCT_DEXPREOPT_SPEED_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEXPREOPT_SPEED_APPS))
-PRODUCT_LOADED_BY_PRIVILEGED_MODULES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
+TARGET_DEVICE := $(PRODUCT_DEVICE)
 
-# All of the apps that we force preopt, this overrides WITH_DEXPREOPT.
-PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK))
-
-# Find the device that this product maps to.
-TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)
+# TODO: also keep track of things like "port", "land" in product files.
 
 # Figure out which resoure configuration options to use for this
 # product.
-PRODUCT_LOCALES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOCALES))
-# TODO: also keep track of things like "port", "land" in product files.
-
 # If CUSTOM_LOCALES contains any locales not already included
 # in PRODUCT_LOCALES, add them to PRODUCT_LOCALES.
 extra_locales := $(filter-out $(PRODUCT_LOCALES),$(CUSTOM_LOCALES))
@@ -284,151 +278,55 @@
 endif
 
 # Add PRODUCT_LOCALES to PRODUCT_AAPT_CONFIG
-PRODUCT_AAPT_CONFIG := $(strip $(PRODUCT_LOCALES) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))
-PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))
-PRODUCT_AAPT_PREBUILT_DPI := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREBUILT_DPI))
+PRODUCT_AAPT_CONFIG := $(PRODUCT_LOCALES) $(PRODUCT_AAPT_CONFIG)
 
 # Keep a copy of the space-separated config
 PRODUCT_AAPT_CONFIG_SP := $(PRODUCT_AAPT_CONFIG)
+PRODUCT_AAPT_CONFIG := $(subst $(space),$(comma),$(PRODUCT_AAPT_CONFIG))
 
-# Convert spaces to commas.
-PRODUCT_AAPT_CONFIG := \
-    $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
-
-PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
-
-PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))
+ifndef PRODUCT_SYSTEM_NAME
+  PRODUCT_SYSTEM_NAME := $(PRODUCT_NAME)
+endif
+ifndef PRODUCT_SYSTEM_DEVICE
+  PRODUCT_SYSTEM_DEVICE := $(PRODUCT_DEVICE)
+endif
+ifndef PRODUCT_SYSTEM_BRAND
+  PRODUCT_SYSTEM_BRAND := $(PRODUCT_BRAND)
+endif
 ifndef PRODUCT_MODEL
-  PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))
+  PRODUCT_MODEL := $(PRODUCT_NAME)
+endif
+ifndef PRODUCT_SYSTEM_MODEL
+  PRODUCT_SYSTEM_MODEL := $(PRODUCT_MODEL)
 endif
 
-PRODUCT_MANUFACTURER := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
 ifndef PRODUCT_MANUFACTURER
   PRODUCT_MANUFACTURER := unknown
 endif
+ifndef PRODUCT_SYSTEM_MANUFACTURER
+  PRODUCT_SYSTEM_MANUFACTURER := $(PRODUCT_MANUFACTURER)
+endif
 
-ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)
+ifndef PRODUCT_CHARACTERISTICS
   TARGET_AAPT_CHARACTERISTICS := default
 else
-  TARGET_AAPT_CHARACTERISTICS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))
+  TARGET_AAPT_CHARACTERISTICS := $(PRODUCT_CHARACTERISTICS)
 endif
 
-PRODUCT_DEFAULT_WIFI_CHANNELS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
-
-PRODUCT_DEFAULT_DEV_CERTIFICATE := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))
 ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
-ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))
+  ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))
     $(error PRODUCT_DEFAULT_DEV_CERTIFICATE='$(PRODUCT_DEFAULT_DEV_CERTIFICATE)', \
       only 1 certificate is allowed.)
-endif
+  endif
 endif
 
-# A list of words like <source path>:<destination path>[:<owner>].
-# The file at the source path should be copied to the destination path
-# when building  this product.  <destination path> is relative to
-# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".
-# The rules for these copy steps are defined in build/make/core/Makefile.
-# The optional :<owner> is used to indicate the owner of a vendor file.
-PRODUCT_COPY_FILES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
+ENFORCE_SYSTEM_CERTIFICATE := $(PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT)
+ENFORCE_SYSTEM_CERTIFICATE_WHITELIST := $(PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST)
 
-# A list of property assignments, like "key = value", with zero or more
-# whitespace characters on either side of the '='.
-PRODUCT_PROPERTY_OVERRIDES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
-.KATI_READONLY := PRODUCT_PROPERTY_OVERRIDES
-
-PRODUCT_SHIPPING_API_LEVEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SHIPPING_API_LEVEL))
-
-# A list of property assignments, like "key = value", with zero or more
-# whitespace characters on either side of the '='.
-# used for adding properties to default.prop
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
-
-$(foreach rule,$(PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES),\
-    $(if $(filter 2,$(words $(subst :,$(space),$(rule)))),,\
-        $(error Rule "$(rule)" in PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDE is not <module_name>:<manifest_name>)))
-
-.KATI_READONLY := PRODUCT_DEFAULT_PROPERTY_OVERRIDES
-
-# A list of property assignments, like "key = value", with zero or more
-# whitespace characters on either side of the '='.
-# used for adding properties to default.prop of system partition
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
-.KATI_READONLY := PRODUCT_SYSTEM_DEFAULT_PROPERTIES
-
-# A list of property assignments, like "key = value", with zero or more
-# whitespace characters on either side of the '='.
-# used for adding properties to build.prop of product partition
-PRODUCT_PRODUCT_PROPERTIES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_PROPERTIES))
-.KATI_READONLY := PRODUCT_PRODUCT_PROPERTIES
-
-ENFORCE_SYSTEM_CERTIFICATE := \
-    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT)
-
-ENFORCE_SYSTEM_CERTIFICATE_WHITELIST := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST))
-
-# A list of property assignments, like "key = value", with zero or more
-# whitespace characters on either side of the '='.
-# used for adding properties to build.prop of product partition
-PRODUCT_PRODUCT_SERVICES_PROPERTIES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_SERVICES_PROPERTIES))
-.KATI_READONLY := PRODUCT_PRODUCT_SERVICES_PROPERTIES
-
-# Should we use the default resources or add any product specific overlays
-PRODUCT_PACKAGE_OVERLAYS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
-DEVICE_PACKAGE_OVERLAYS := \
-        $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).DEVICE_PACKAGE_OVERLAYS))
-
-# The list of product-specific kernel header dirs
-PRODUCT_VENDOR_KERNEL_HEADERS := \
-    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_KERNEL_HEADERS)
-
-# The OTA key(s) specified by the product config, if any.  The names
-# of these keys are stored in the target-files zip so that post-build
-# signing tools can substitute them for the test key embedded by
-# default.
-PRODUCT_OTA_PUBLIC_KEYS := $(sort \
-    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTA_PUBLIC_KEYS))
-
-PRODUCT_EXTRA_RECOVERY_KEYS := $(sort \
-    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_EXTRA_RECOVERY_KEYS))
-
-PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER))
-PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
-PRODUCT_DEX_PREOPT_GENERATE_DM_FILES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_GENERATE_DM_FILES))
-PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
-PRODUCT_DEX_PREOPT_PROFILE_DIR := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_PROFILE_DIR))
-
-# Boot image options.
-PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))
-PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
-
-PRODUCT_SYSTEM_SERVER_COMPILER_FILTER := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
-PRODUCT_SYSTEM_SERVER_DEBUG_INFO := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_DEBUG_INFO))
-PRODUCT_OTHER_JAVA_DEBUG_INFO := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTHER_JAVA_DEBUG_INFO))
+PRODUCT_OTA_PUBLIC_KEYS := $(sort $(PRODUCT_OTA_PUBLIC_KEYS))
+PRODUCT_EXTRA_RECOVERY_KEYS := $(sort $(PRODUCT_EXTRA_RECOVERY_KEYS))
 
 # Resolve and setup per-module dex-preopt configs.
-PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
 DEXPREOPT_DISABLED_MODULES :=
 # If a module has multiple setups, the first takes precedence.
 _pdpmc_modules :=
@@ -443,9 +341,8 @@
       $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf)))))
 _pdpmc_modules :=
 
+
 # Resolve and setup per-module sanitizer configs.
-PRODUCT_SANITIZER_MODULE_CONFIGS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
 # If a module has multiple setups, the first takes precedence.
 _psmc_modules :=
 $(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
@@ -457,127 +354,43 @@
     $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
 _psmc_modules :=
 
-# Whether the product wants to ship libartd. For rules and meaning, see art/Android.mk.
-PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD))
-
-# Make this art variable visible to soong_config.mk.
-PRODUCT_ART_USE_READ_BARRIER := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ART_USE_READ_BARRIER))
-
-# Whether the product is an Android Things variant.
-PRODUCT_IOT := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_IOT))
-
-# Resource overlay list which must be excluded from enforcing RRO.
-PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS))
-
-# Package list to apply enforcing RRO.
-PRODUCT_ENFORCE_RRO_TARGETS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_RRO_TARGETS))
-
-# Whether the product would like to check prebuilt ELF files.
-PRODUCT_CHECK_ELF_FILES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHECK_ELF_FILES))
-.KATI_READONLY := PRODUCT_CHECK_ELF_FILES
-
-# Add reserved headroom to a system image.
-PRODUCT_SYSTEM_HEADROOM := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_HEADROOM))
-
-# Whether to save disk space by minimizing java debug info
-PRODUCT_MINIMIZE_JAVA_DEBUG_INFO := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MINIMIZE_JAVA_DEBUG_INFO))
-
-# Whether any paths are excluded from sanitization when SANITIZE_TARGET=integer_overflow
-PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
-
-# ADB keys for debuggable builds
-PRODUCT_ADB_KEYS :=
-ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
-  PRODUCT_ADB_KEYS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ADB_KEYS))
+# Reset ADB keys for non-debuggable builds
+ifeq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
+  PRODUCT_ADB_KEYS :=
 endif
 ifneq ($(filter-out 0 1,$(words $(PRODUCT_ADB_KEYS))),)
   $(error Only one file may be in PRODUCT_ADB_KEYS: $(PRODUCT_ADB_KEYS))
 endif
-.KATI_READONLY := PRODUCT_ADB_KEYS
 
-# Whether any paths are excluded from sanitization when SANITIZE_TARGET=cfi
-PRODUCT_CFI_EXCLUDE_PATHS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_EXCLUDE_PATHS))
-
-# Whether any paths should have CFI enabled for components
-PRODUCT_CFI_INCLUDE_PATHS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_INCLUDE_PATHS))
-
-# Whether any paths are excluded from being set XOM when ENABLE_XOM=true
-PRODUCT_XOM_EXCLUDE_PATHS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_XOM_EXCLUDE_PATHS))
-
-# which Soong namespaces to export to Make
-PRODUCT_SOONG_NAMESPACES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SOONG_NAMESPACES))
-
-# A flag to override PRODUCT_COMPATIBLE_PROPERTY
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE))
-
-# Whether the whitelist of actionable compatible properties should be disabled or not
-PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE))
-
-# Dynamic partition feature flags.
-
-# When this is true, dynamic partitions is retrofitted on a device that has
-# already been launched without dynamic partitions. Otherwise, the device
-# is launched with dynamic partitions.
-# This flag implies PRODUCT_USE_DYNAMIC_PARTITIONS.
-PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RETROFIT_DYNAMIC_PARTITIONS))
-.KATI_READONLY := PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
-
-PRODUCT_USE_DYNAMIC_PARTITIONS := $(or \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_USE_DYNAMIC_PARTITIONS)), \
-    $(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS))
-.KATI_READONLY := PRODUCT_USE_DYNAMIC_PARTITIONS
+ifndef PRODUCT_USE_DYNAMIC_PARTITIONS
+  PRODUCT_USE_DYNAMIC_PARTITIONS := $(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)
+endif
 
 # All requirements of PRODUCT_USE_DYNAMIC_PARTITIONS falls back to
 # PRODUCT_USE_DYNAMIC_PARTITIONS if not defined.
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := $(or \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_USE_DYNAMIC_PARTITION_SIZE)),\
-    $(PRODUCT_USE_DYNAMIC_PARTITIONS))
-.KATI_READONLY := PRODUCT_USE_DYNAMIC_PARTITION_SIZE
-PRODUCT_BUILD_SUPER_PARTITION := $(or \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BUILD_SUPER_PARTITION)),\
-    $(PRODUCT_USE_DYNAMIC_PARTITIONS))
-.KATI_READONLY := PRODUCT_BUILD_SUPER_PARTITION
+ifndef PRODUCT_USE_DYNAMIC_PARTITION_SIZE
+  PRODUCT_USE_DYNAMIC_PARTITION_SIZE := $(PRODUCT_USE_DYNAMIC_PARTITIONS)
+endif
 
-# List of modules that should be forcefully unmarked from being LOCAL_PRODUCT_MODULE, and hence
-# installed on /system directory by default.
-PRODUCT_FORCE_PRODUCT_MODULES_TO_SYSTEM_PARTITION := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_FORCE_PRODUCT_MODULES_TO_SYSTEM_PARTITION))
-.KATI_READONLY := PRODUCT_FORCE_PRODUCT_MODULES_TO_SYSTEM_PARTITION
+ifndef PRODUCT_BUILD_SUPER_PARTITION
+  PRODUCT_BUILD_SUPER_PARTITION := $(PRODUCT_USE_DYNAMIC_PARTITIONS)
+endif
 
-# If set, kernel configuration requirements are present in OTA package (and will be enforced
-# during OTA). Otherwise, kernel configuration requirements are enforced in VTS.
-# Devices that checks the running kernel (instead of the kernel in OTA package) should not
-# set this variable to prevent OTA failures.
-PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS))
+define product-overrides-config
+$$(foreach rule,$$(PRODUCT_$(1)_OVERRIDES),\
+    $$(if $$(filter 2,$$(words $$(subst :,$$(space),$$(rule)))),,\
+        $$(error Rule "$$(rule)" in PRODUCT_$(1)_OVERRIDE is not <module_name>:<new_value>)))
+endef
 
-# List of <module_name>:<manifest_name> pairs to override the manifest package name
-# of a module <module_name> to <manifest_name>. Patterns can be used as in
-# com.android.%:com.acme.android.%.release
-PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES := \
-    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES))
-.KATI_READONLY := PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
+$(foreach var, \
+    MANIFEST_PACKAGE_NAME \
+    PACKAGE_NAME \
+    CERTIFICATE, \
+  $(eval $(call product-overrides-config,$(var))))
 
 # Macro to use below. $(1) is the name of the partition
 define product-build-image-config
-PRODUCT_BUILD_$(1)_IMAGE := $$(firstword $$(strip $$(PRODUCTS.$$(INTERNAL_PRODUCT).PRODUCT_BUILD_$(1)_IMAGE)))
-.KATI_READONLY := PRODUCT_BUILD_$(1)_IMAGE
+PRODUCT_BUILD_$(1)_IMAGE := $$(firstword $$(PRODUCT_BUILD_$(1)_IMAGE))
 ifneq ($$(filter-out true false,$$(PRODUCT_BUILD_$(1)_IMAGE)),)
     $$(error Invalid PRODUCT_BUILD_$(1)_IMAGE: $$(PRODUCT_BUILD_$(1)_IMAGE) -- true false and empty are supported)
 endif
@@ -597,3 +410,5 @@
   $(eval $(call product-build-image-config,$(image))))
 
 product-build-image-config :=
+
+$(call readonly-product-vars)
diff --git a/core/proguard.flags b/core/proguard.flags
index 6ed1f9b..50049cb 100644
--- a/core/proguard.flags
+++ b/core/proguard.flags
@@ -15,4 +15,35 @@
 @**.VisibleForTesting *;
 }
 
+# Understand the @Keep support annotation.
+-keep class android.support.annotation.Keep
+-keep class androidx.annotation.Keep
+
+-keep @android.support.annotation.Keep class * {*;}
+-keep @androidx.annotation.Keep class * {*;}
+
+-keepclasseswithmembers class * {
+    @android.support.annotation.Keep <methods>;
+}
+
+-keepclasseswithmembers class * {
+    @androidx.annotation.Keep <methods>;
+}
+
+-keepclasseswithmembers class * {
+    @android.support.annotation.Keep <fields>;
+}
+
+-keepclasseswithmembers class * {
+    @androidx.annotation.Keep <fields>;
+}
+
+-keepclasseswithmembers class * {
+    @android.support.annotation.Keep <init>(...);
+}
+
+-keepclasseswithmembers class * {
+    @androidx.annotation.Keep <init>(...);
+}
+
 -include proguard_basic_keeps.flags
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index 1e93cee..8d92b20 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -48,9 +48,11 @@
 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
 
 ifeq ($(module_run_appcompat),true)
   $(LOCAL_BUILT_MODULE): $(appcompat-files)
@@ -85,7 +87,7 @@
 $(resource_export_package): PRIVATE_STAMP := $(resource_export_stamp)
 $(resource_export_package): .KATI_IMPLICIT_OUTPUTS := $(resource_export_stamp)
 $(resource_export_package): $(LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE)
-	@echo "Copy: $$@"
+	@echo "Copy: $@"
 	$(copy-file-to-target)
 	touch $(PRIVATE_STAMP)
 $(call add-dependency,$(LOCAL_BUILT_MODULE),$(resource_export_package))
@@ -157,13 +159,26 @@
 include $(BUILD_SYSTEM)/link_type.mk
 endif # !LOCAL_IS_HOST_MODULE
 
-ifdef LOCAL_SOONG_RRO_DIRS
+ifdef LOCAL_SOONG_DEVICE_RRO_DIRS
   $(call append_enforce_rro_sources, \
       $(my_register_name), \
       false, \
       $(LOCAL_FULL_MANIFEST_FILE), \
-      $(LOCAL_EXPORT_PACKAGE_RESOURCES), \
-      $(LOCAL_SOONG_RRO_DIRS))
+      $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
+      $(LOCAL_SOONG_DEVICE_RRO_DIRS), \
+      vendor \
+  )
+endif
+
+ifdef 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_PRODUCT_RRO_DIRS), \
+      product \
+  )
 endif
 
 SOONG_ALREADY_CONV := $(SOONG_ALREADY_CONV) $(LOCAL_MODULE)
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index 39cc0f0..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,24 +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))
-    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 \
@@ -139,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 cd8cd7f..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))
 
@@ -87,6 +88,8 @@
 $(call add_json_list, XOMExcludePaths,                   $(XOM_EXCLUDE_PATHS) $(PRODUCT_XOM_EXCLUDE_PATHS))
 $(call add_json_list, IntegerOverflowExcludePaths,       $(INTEGER_OVERFLOW_EXCLUDE_PATHS) $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
 
+$(call add_json_bool, DisableScudo,                      $(filter true,$(PRODUCT_DISABLE_SCUDO)))
+
 $(call add_json_bool, ClangTidy,                         $(filter 1 true,$(WITH_TIDY)))
 $(call add_json_str,  TidyChecks,                        $(WITH_TIDY_CHECKS))
 
@@ -112,11 +115,8 @@
 $(call add_json_list, ModulesLoadedByPrivilegedModules,  $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
 
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
-$(call add_json_list, PreoptBootJars,                    $(DEXPREOPT_BOOT_JARS_MODULES))
 
-$(call add_json_bool, DisableDexPreopt,                  $(call invert_bool,$(filter true,$(WITH_DEXPREOPT))))
-$(call add_json_list, DisableDexPreoptModules,           $(DEXPREOPT_DISABLED_MODULES))
-$(call add_json_str,  DexPreoptProfileDir,               $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
+$(call add_json_bool, VndkUseCoreVariant,                $(TARGET_VNDK_USE_CORE_VARIANT))
 
 $(call add_json_bool, Product_is_iot,                    $(filter true,$(PRODUCT_IOT)))
 
@@ -150,13 +150,15 @@
 $(call add_json_str,  DexpreoptGlobalConfig,             $(DEX_PREOPT_CONFIG))
 
 $(call add_json_list, ManifestPackageNameOverrides,      $(PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES))
+$(call add_json_list, PackageNameOverrides,              $(PRODUCT_PACKAGE_NAME_OVERRIDES))
+$(call add_json_list, CertificateOverrides,              $(PRODUCT_CERTIFICATE_OVERRIDES))
 
 $(call add_json_bool, EnforceSystemCertificate,          $(ENFORCE_SYSTEM_CERTIFICATE))
 $(call add_json_list, EnforceSystemCertificateWhitelist, $(ENFORCE_SYSTEM_CERTIFICATE_WHITELIST))
 
-$(call add_json_str,  HiddenAPIStubFlags,                $(INTERNAL_PLATFORM_HIDDENAPI_STUB_FLAGS))
-$(call add_json_str,  HiddenAPIFlags,                    $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS))
-$(call add_json_list, HiddenAPIExtraAppUsageJars,        $(HIDDENAPI_EXTRA_APP_USAGE_JARS))
+$(call add_json_list, ProductHiddenAPIStubs,             $(PRODUCT_HIDDENAPI_STUBS))
+$(call add_json_list, ProductHiddenAPIStubsSystem,       $(PRODUCT_HIDDENAPI_STUBS_SYSTEM))
+$(call add_json_list, ProductHiddenAPIStubsTest,         $(PRODUCT_HIDDENAPI_STUBS_TEST))
 
 $(call add_json_map, VendorVars)
 $(foreach namespace,$(SOONG_CONFIG_NAMESPACES),\
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index 08d545d..9692a99 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -19,8 +19,6 @@
 full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
 full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
 common_javalib.jar := $(intermediates.COMMON)/javalib.jar
-hiddenapi_flags_csv := $(intermediates.COMMON)/hiddenapi/flags.csv
-hiddenapi_metadata_csv := $(intermediates.COMMON)/hiddenapi/greylist.csv
 
 ifdef LOCAL_SOONG_AAR
   LOCAL_ADDITIONAL_CHECKED_MODULE += $(LOCAL_SOONG_AAR)
@@ -96,6 +94,8 @@
         ALL_MODULES.$(my_register_name).INSTALLED += $(installed_odex)
         # Make sure to install the .odex and .vdex when you run "make <module_name>"
        $(my_all_targets): $(installed_odex)
+       # Copy $(LOCAL_BUILT_MODULE) and its dependencies when installing boot.art
+       $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(LOCAL_BUILT_MODULE)
       endif
     endif # is_boot_jar
 
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index cee7c9e..ee759b9 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -85,14 +85,22 @@
 LOCAL_INTERMEDIATE_TARGETS += $(R_file_stamp)
 
 ifeq ($(LOCAL_USE_AAPT2),true)
-# For library we treat all the resource equal with no overlay.
-my_res_resources := $(all_resources)
-my_overlay_resources :=
-# For libraries put everything in the COMMON intermediate directory.
-my_res_package := $(intermediates.COMMON)/package-res.apk
+  ifneq ($(strip $(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),)
+    # If we are using static android libraries, every source file becomes an overlay.
+    # This is to emulate old AAPT behavior which simulated library support.
+    my_res_resources :=
+    my_overlay_resources := $(all_resources)
+  else
+    # Otherwise, for a library we treat all the resource equal with no overlay.
+    my_res_resources := $(all_resources)
+    my_overlay_resources :=
+  endif
+  # For libraries put everything in the COMMON intermediate directory.
+  my_res_package := $(intermediates.COMMON)/package-res.apk
 
-LOCAL_INTERMEDIATE_TARGETS += $(my_res_package)
+  LOCAL_INTERMEDIATE_TARGETS += $(my_res_package)
 endif  # LOCAL_USE_AAPT2
+
 endif  # need_compile_res
 
 all_res_assets := $(all_resources)
diff --git a/core/target_test_internal.mk b/core/target_test_internal.mk
index b5c3a7c..40b2ba8 100644
--- a/core/target_test_internal.mk
+++ b/core/target_test_internal.mk
@@ -29,6 +29,13 @@
 $(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_64 when building test $(LOCAL_MODULE))
 endif
 
+use_testcase_folder := false
+ifneq ($(LOCAL_MODULE),$(filter $(LOCAL_MODULE),$(DEFAULT_DATA_OUT_MODULES)))
+  use_testcase_folder := true
+endif
+
+ifneq ($(use_testcase_folder),true)
 ifndef LOCAL_MODULE_RELATIVE_PATH
 LOCAL_MODULE_RELATIVE_PATH := $(LOCAL_MODULE)
 endif
+endif
diff --git a/core/tasks/find-shareduid-violation.mk b/core/tasks/find-shareduid-violation.mk
new file mode 100644
index 0000000..45fd937
--- /dev/null
+++ b/core/tasks/find-shareduid-violation.mk
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+shareduid_violation_modules_filename := $(PRODUCT_OUT)/shareduid_violation_modules.json
+
+find_shareduid_script := $(BUILD_SYSTEM)/tasks/find-shareduid-violation.py
+
+$(shareduid_violation_modules_filename): $(INSTALLED_SYSTEMIMAGE_TARGET) \
+    $(INSTALLED_RAMDISK_TARGET) \
+    $(INSTALLED_BOOTIMAGE_TARGET) \
+    $(INSTALLED_USERDATAIMAGE_TARGET) \
+    $(INSTALLED_VENDORIMAGE_TARGET) \
+    $(INSTALLED_PRODUCTIMAGE_TARGET) \
+    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)
+
+$(shareduid_violation_modules_filename): $(find_shareduid_script)
+$(shareduid_violation_modules_filename): $(AAPT2)
+	$(find_shareduid_script) $(PRODUCT_OUT) $(AAPT2) > $@
+$(call dist-for-goals,droidcore,$(shareduid_violation_modules_filename))
diff --git a/core/tasks/find-shareduid-violation.py b/core/tasks/find-shareduid-violation.py
new file mode 100755
index 0000000..1f8e4df
--- /dev/null
+++ b/core/tasks/find-shareduid-violation.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+#
+# 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.
+#
+import os
+import subprocess
+from glob import glob
+from collections import defaultdict
+import sys
+import json
+
+if len(sys.argv) < 3:
+    product_out = os.environ["PRODUCT_OUT"]
+    aapt = "aapt2"
+else:
+    product_out = sys.argv[1]
+    aapt = sys.argv[2]
+
+def execute(cmd):
+    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    out, err = map(lambda b: b.decode('utf-8'), p.communicate())
+    return p.returncode == 0, out, err
+
+def make_aapt_cmds(file):
+    return [aapt + ' dump ' + file + ' --file AndroidManifest.xml',
+            aapt + ' dump xmltree ' + file + ' --file AndroidManifest.xml']
+
+def extract_shared_uid(file):
+    for cmd in make_aapt_cmds(file):
+        success, manifest, error_msg = execute(cmd)
+        if success:
+            break
+    else:
+        print(error_msg, file=sys.stderr)
+        sys.exit()
+        return None
+
+    for l in manifest.split('\n'):
+        if "sharedUserId" in l:
+            return l.split('"')[-2]
+    return None
+
+
+partitions = ["system", "vendor", "product"]
+
+shareduid_app_dict = defaultdict(list)
+
+for p in partitions:
+    for f in glob(os.path.join(product_out, p, "*", "*", "*.apk")):
+        apk_file = os.path.basename(f)
+        shared_uid = extract_shared_uid(f)
+
+        if shared_uid is None:
+            continue
+        shareduid_app_dict[shared_uid].append((p, apk_file))
+
+
+output = defaultdict(lambda: defaultdict(list))
+
+for uid, app_infos in shareduid_app_dict.items():
+    partitions = {p for p, _ in app_infos}
+    if len(partitions) > 1:
+        for part in partitions:
+            output[uid][part].extend([a for p, a in app_infos if p == part])
+
+print(json.dumps(output, indent=2, sort_keys=True))
diff --git a/core/tasks/sdk-addon.mk b/core/tasks/sdk-addon.mk
index 122161b..93db1de 100644
--- a/core/tasks/sdk-addon.mk
+++ b/core/tasks/sdk-addon.mk
@@ -18,7 +18,7 @@
 
 # If they didn't define PRODUCT_SDK_ADDON_NAME, then we won't define
 # any of these rules.
-addon_name := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_NAME))
+addon_name := $(PRODUCT_SDK_ADDON_NAME)
 ifneq ($(addon_name),)
 
 addon_dir_leaf  := $(addon_name)-$(FILE_NAME_TAG)-$(INTERNAL_SDK_HOST_OS_NAME)
@@ -43,8 +43,8 @@
 endef
 
 # Files that are built and then copied into the sdk-addon
-ifneq ($(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_COPY_MODULES)),)
-$(foreach cf,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_COPY_MODULES), \
+ifneq ($(PRODUCT_SDK_ADDON_COPY_MODULES),)
+$(foreach cf,$(PRODUCT_SDK_ADDON_COPY_MODULES), \
   $(eval _src := $(call module-stubs-files,$(call word-colon,1,$(cf)))) \
   $(eval $(call stub-addon-jar,$(_src))) \
   $(eval _src := $(call stub-addon-jar-file,$(_src))) \
@@ -55,8 +55,8 @@
 endif
 
 # Files that are copied directly into the sdk-addon
-ifneq ($(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_COPY_FILES)),)
-$(foreach cf,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_COPY_FILES), \
+ifneq ($(PRODUCT_SDK_ADDON_COPY_FILES),)
+$(foreach cf,$(PRODUCT_SDK_ADDON_COPY_FILES), \
   $(eval _src  := $(call word-colon,1,$(cf))) \
   $(eval _dest := $(call word-colon,2,$(cf))) \
   $(if $(findstring images/,$(_dest)), $(eval _root := $(addon_dir_img)), $(eval _root := $(addon_dir_leaf))) \
@@ -72,7 +72,7 @@
 	$(addon_dir_img):$(PRODUCT_OUT)/system/build.prop:images/$(TARGET_CPU_ABI)/build.prop \
 	$(addon_dir_img):device/generic/goldfish/data/etc/userdata.img:images/$(TARGET_CPU_ABI)/userdata.img \
 	$(addon_dir_img):$(target_notice_file_txt):images/$(TARGET_CPU_ABI)/NOTICE.txt \
-	$(addon_dir_img):$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP):images/source.properties
+	$(addon_dir_img):$(PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP):images/source.properties
 
 
 ifeq ($(BOARD_AVB_ENABLE),true)
@@ -93,7 +93,7 @@
 addon_img_source_prop := $(call append-path,$(staging),$(addon_dir_img))/images/$(TARGET_CPU_ABI)/source.properties
 sdk_addon_deps += $(addon_img_source_prop)
 
-$(addon_img_source_prop): $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP)
+$(addon_img_source_prop): $(PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP)
 	@echo Generate $@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) sed \
@@ -108,7 +108,7 @@
 # We don't know about all of the docs files, so depend on the timestamps for
 # them, and record the directories, and the packaging rule will just copy the
 # whole thing.
-doc_modules := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_DOC_MODULES))
+doc_modules := $(PRODUCT_SDK_ADDON_DOC_MODULES)
 sdk_addon_deps += $(foreach dm, $(doc_modules), $(call doc-timestamp-for, $(dm)))
 $(full_target): PRIVATE_DOCS_DIRS := $(addprefix $(OUT_DOCS)/, $(doc_modules))
 
diff --git a/core/tasks/tools/build_custom_image.mk b/core/tasks/tools/build_custom_image.mk
index a1151e9..19d2ab5 100644
--- a/core/tasks/tools/build_custom_image.mk
+++ b/core/tasks/tools/build_custom_image.mk
@@ -84,7 +84,7 @@
 $(my_built_custom_image): PRIVATE_SELINUX := $(CUSTOM_IMAGE_SELINUX)
 $(my_built_custom_image): PRIVATE_SUPPORT_VERITY := $(CUSTOM_IMAGE_SUPPORT_VERITY)
 $(my_built_custom_image): PRIVATE_SUPPORT_VERITY_FEC := $(CUSTOM_IMAGE_SUPPORT_VERITY_FEC)
-$(my_built_custom_image): PRIVATE_VERITY_KEY := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)
+$(my_built_custom_image): PRIVATE_VERITY_KEY := $(PRODUCT_VERITY_SIGNING_KEY)
 $(my_built_custom_image): PRIVATE_VERITY_BLOCK_DEVICE := $(CUSTOM_IMAGE_VERITY_BLOCK_DEVICE)
 $(my_built_custom_image): PRIVATE_DICT_FILE := $(CUSTOM_IMAGE_DICT_FILE)
 $(my_built_custom_image): PRIVATE_AVB_AVBTOOL := $(AVBTOOL)
diff --git a/core/tasks/tools/package-modules.mk b/core/tasks/tools/package-modules.mk
index 629a9b2..82b4c6a 100644
--- a/core/tasks/tools/package-modules.mk
+++ b/core/tasks/tools/package-modules.mk
@@ -40,6 +40,8 @@
     $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).PICKUP_FILES)))\
   $(eval _built_files := $(strip $(ALL_MODULES.$(m).BUILT_INSTALLED)\
     $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).BUILT_INSTALLED)))\
+  $(eval _module_class_folder := $($(strip MODULE_CLASS_$(word 1, $(strip $(ALL_MODULES.$(m).CLASS)\
+    $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS))))))\
   $(if $(_pickup_files)$(_built_files),,\
     $(call my_missing_files,$(m)))\
   $(eval my_pickup_files += $(_pickup_files))\
@@ -49,9 +51,15 @@
     $(if $(filter $(TARGET_OUT_ROOT)/%,$(ins)),\
       $(eval bui := $(word 1,$(bui_ins)))\
       $(eval my_built_modules += $(bui))\
+      $(if $(filter $(_module_class_folder), nativetest benchmarktest),\
+        $(eval module_class_folder_stem := $(_module_class_folder)$(findstring 64, $(patsubst $(PRODUCT_OUT)/%,%,$(ins)))),\
+        $(eval module_class_folder_stem := $(_module_class_folder)))\
       $(eval my_copy_dest := $(patsubst data/%,DATA/%,\
-                               $(patsubst system/%,DATA/%,\
-                                 $(patsubst $(PRODUCT_OUT)/%,%,$(ins)))))\
+                               $(patsubst testcases/%,DATA/$(module_class_folder_stem)/%,\
+                                 $(patsubst testcases/$(m)/$(TARGET_ARCH)/%,DATA/$(module_class_folder_stem)/$(m)/%,\
+                                   $(patsubst testcases/$(m)/$(TARGET_2ND_ARCH)/%,DATA/$(module_class_folder_stem)/$(m)/%,\
+                                     $(patsubst system/%,DATA/%,\
+                                       $(patsubst $(PRODUCT_OUT)/%,%,$(ins))))))))\
       $(eval my_copy_pairs += $(bui):$(my_staging_dir)/$(my_copy_dest)))\
   ))
 
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index 6695994..0b8f1e8 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -48,18 +48,18 @@
         widevine
 
 
-_restrictions := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES))
+_restrictions := $(PRODUCT_RESTRICT_VENDOR_FILES)
 
 ifneq (,$(_restrictions))
-ifneq (,$(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
+ifneq (,$(VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
 $(error Error: cannot set both PRODUCT_RESTRICT_VENDOR_FILES and VENDOR_PRODUCT_RESTRICT_VENDOR_FILES)
 endif
 _vendor_exception_path_prefix :=
 _vendor_exception_modules :=
 else
-_restrictions := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
-_vendor_exception_path_prefix := $(patsubst %, vendor/%/%, $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_EXCEPTION_PATHS))
-_vendor_exception_modules := $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_EXCEPTION_MODULES)
+_restrictions := $(VENDOR_PRODUCT_RESTRICT_VENDOR_FILES)
+_vendor_exception_path_prefix := $(patsubst %, vendor/%/%, $(VENDOR_EXCEPTION_PATHS))
+_vendor_exception_modules := $(VENDOR_EXCEPTION_MODULES)
 endif
 
 
diff --git a/core/use_lld_setup.mk b/core/use_lld_setup.mk
index 2026f31..8f47d68 100644
--- a/core/use_lld_setup.mk
+++ b/core/use_lld_setup.mk
@@ -18,7 +18,3 @@
 ifeq ($($(my_prefix)OS),darwin)
 my_use_clang_lld := false
 endif
-# http://b/110800681 - lld cannot link Android's Windows modules yet.
-ifeq ($($(my_prefix)OS),windows)
-my_use_clang_lld := false
-endif
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 965ba12..a96bf74 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -259,7 +259,7 @@
     #  It must be of the form "YYYY-MM-DD" on production devices.
     #  It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
     #  If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
-      PLATFORM_SECURITY_PATCH := 2019-03-05
+      PLATFORM_SECURITY_PATCH := 2019-04-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
diff --git a/envsetup.sh b/envsetup.sh
index c4c4972..9e381a2 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -9,7 +9,7 @@
               build, and stores those selections in the environment to be read by subsequent
               invocations of 'm' etc.
 - tapas:      tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user]
-- croot:      Changes directory to the top of the tree.
+- croot:      Changes directory to the top of the tree, or a subdirectory thereof.
 - m:          Makes from the top of the tree.
 - mm:         Builds all of the modules in the current directory, but not their dependencies.
 - mmm:        Builds all of the modules in the supplied directories, but not their dependencies.
@@ -28,12 +28,14 @@
 - godir:      Go to the directory containing a file.
 - allmod:     List all modules.
 - gomod:      Go to the directory containing a module.
+- pathmod:    Get the directory containing a module.
 - refreshmod: Refresh list of modules for allmod/gomod.
 
 Environment options:
 - SANITIZE_HOST: Set to 'true' to use ASAN for all host modules. Note that
                  ASAN_OPTIONS=detect_leaks=0 will be set by default until the
                  build is leak-check clean.
+- ANDROID_QUIET_BUILD: set to 'true' to display only the essential messages.
 
 Look at the source to view more functions. The complete list is:
 EOF
@@ -265,6 +267,13 @@
         export ANDROID_EMULATOR_PREBUILTS
     fi
 
+    # Append asuite prebuilts path to ANDROID_BUILD_PATHS.
+    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
+    local ACLOUD_PATH="$T/prebuilts/asuite/acloud/$os_arch:"
+    local AIDEGEN_PATH="$T/prebuilts/asuite/aidegen/$os_arch:"
+    local ATEST_PATH="$T/prebuilts/asuite/atest/$os_arch:"
+    export ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS$ACLOUD_PATH$AIDEGEN_PATH$ATEST_PATH
+
     export PATH=$ANDROID_BUILD_PATHS$PATH
 
     # out with the duplicate old
@@ -353,7 +362,7 @@
     local completion_files=(
       system/core/adb/adb.bash
       system/core/fastboot/fastboot.bash
-      tools/tradefederation/core/atest/atest_completion.sh
+      tools/asuite/asuite.sh
     )
     # Completion can be disabled selectively to allow users to use non-standard completion.
     # e.g.
@@ -368,6 +377,10 @@
     if should_add_completion bit ; then
         complete -C "bit --tab" bit
     fi
+    if [ -z "$ZSH_VERSION" ]; then
+        # Doesn't work in zsh.
+        complete -o nospace -F _croot croot
+    fi
     complete -F _lunch lunch
 
     complete -F _complete_android_module_names gomod
@@ -542,19 +555,14 @@
     destroy_build_var_cache
 }
 
-# Clear this variable.  It will be built up again when the vendorsetup.sh
-# files are included at the end of this file.
-unset LUNCH_MENU_CHOICES
 function add_lunch_combo()
 {
-    local new_combo=$1
-    local c
-    for c in ${LUNCH_MENU_CHOICES[@]} ; do
-        if [ "$new_combo" = "$c" ] ; then
-            return
-        fi
-    done
-    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
+    if [ -n "$ZSH_VERSION" ]; then
+        echo -n "${funcfiletrace[1]}: "
+    else
+        echo -n "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: "
+    fi
+    echo "add_lunch_combo is obsolete. Use COMMON_LUNCH_CHOICES in your AndroidProducts.mk instead."
 }
 
 function print_lunch_menu()
@@ -567,7 +575,7 @@
 
     local i=1
     local choice
-    for choice in $(TARGET_BUILD_APPS= LUNCH_MENU_CHOICES="${LUNCH_MENU_CHOICES[@]}" get_build_var COMMON_LUNCH_CHOICES)
+    for choice in $(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
     do
         echo "     $i. $choice"
         i=$(($i+1))
@@ -595,7 +603,7 @@
         selection=aosp_arm-eng
     elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
     then
-        local choices=($(TARGET_BUILD_APPS= LUNCH_MENU_CHOICES="${LUNCH_MENU_CHOICES[@]}" get_build_var COMMON_LUNCH_CHOICES))
+        local choices=($(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES))
         if [ $answer -le ${#choices[@]} ]
         then
             # array in zsh starts from 1 instead of 0.
@@ -665,7 +673,7 @@
     prev="${COMP_WORDS[COMP_CWORD-1]}"
 
     if [ -z "$COMMON_LUNCH_CHOICES_CACHE" ]; then
-        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= LUNCH_MENU_CHOICES="${LUNCH_MENU_CHOICES[@]}" get_build_var COMMON_LUNCH_CHOICES)
+        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
     fi
 
     COMPREPLY=( $(compgen -W "${COMMON_LUNCH_CHOICES_CACHE}" -- ${cur}) )
@@ -983,6 +991,18 @@
     fi
 }
 
+function _croot()
+{
+    local T=$(gettop)
+    if [ "$T" ]; then
+        local cur="${COMP_WORDS[COMP_CWORD]}"
+        k=0
+        for c in $(compgen -d ${T}/${cur}); do
+            COMPREPLY[k++]=${c#${T}/}/
+        done
+    fi
+}
+
 function cproj()
 {
     local TOPFILE=build/make/core/envsetup.mk
@@ -1517,16 +1537,16 @@
     python -c "import json; print '\n'.join(sorted(json.load(open('$ANDROID_PRODUCT_OUT/module-info.json')).keys()))"
 }
 
-# Go to a specific module in the android tree, as cached in module-info.json. If any build change
+# Get the path of a specific module in the android tree, as cached in module-info.json. If any build change
 # is made, and it should be reflected in the output, you should run 'refreshmod' first.
-function gomod() {
+function pathmod() {
     if [ ! "$ANDROID_PRODUCT_OUT" ]; then
         echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
         return 1
     fi
 
     if [[ $# -ne 1 ]]; then
-        echo "usage: gomod <module>" >&2
+        echo "usage: pathmod <module>" >&2
         return 1
     fi
 
@@ -1546,10 +1566,25 @@
         echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)." >&2
         return 1
     else
-        cd $ANDROID_BUILD_TOP/$relpath
+        echo "$ANDROID_BUILD_TOP/$relpath"
     fi
 }
 
+# Go to a specific module in the android tree, as cached in module-info.json. If any build change
+# is made, and it should be reflected in the output, you should run 'refreshmod' first.
+function gomod() {
+    if [[ $# -ne 1 ]]; then
+        echo "usage: gomod <module>" >&2
+        return 1
+    fi
+
+    local path="$(pathmod $@)"
+    if [ -z "$path" ]; then
+        return 1
+    fi
+    cd $path
+}
+
 function _complete_android_module_names() {
     local word=${COMP_WORDS[COMP_CWORD]}
     COMPREPLY=( $(allmod | grep -E "^$word") )
@@ -1587,6 +1622,10 @@
 
 function _wrap_build()
 {
+    if [[ "${ANDROID_QUIET_BUILD:-}" == true ]]; then
+      "$@"
+      return $?
+    fi
     local start_time=$(date +"%s")
     "$@"
     local ret=$?
@@ -1657,23 +1696,6 @@
     "$ANDROID_PRODUCT_OUT/provision-device" "$@"
 }
 
-function atest()
-{
-    # Let's use the built version over the prebuilt, then source code.
-    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
-    local built_atest=${ANDROID_HOST_OUT}/bin/atest
-    local prebuilt_atest="$(gettop)"/prebuilts/asuite/atest/$os_arch/atest
-    if [[ -x $built_atest ]]; then
-        $built_atest "$@"
-    elif [[ -x $prebuilt_atest ]]; then
-        $prebuilt_atest "$@"
-    else
-        # TODO: once prebuilt atest released, remove the source code section
-        # and change the location of atest_completion.sh in addcompletions().
-        "$(gettop)"/tools/tradefederation/core/atest/atest.py "$@"
-    fi
-}
-
 # Zsh needs bashcompinit called to support bash-style completion.
 function enable_zsh_completion() {
     # Don't override user's options if bash-style completion is already enabled.
@@ -1698,46 +1720,34 @@
     esac
 }
 
-function acloud()
-{
-    # Let's use the built version over the prebuilt.
-    local built_acloud=${ANDROID_HOST_OUT}/bin/acloud
-    if [ -f $built_acloud ]; then
-        $built_acloud "$@"
-        return $?
-    fi
-
-    local host_os_arch=$(get_build_var HOST_PREBUILT_TAG)
-    case $host_os_arch in
-        linux-x86) "$(gettop)"/prebuilts/asuite/acloud/linux-x86/acloud "$@"
-        ;;
-        darwin-x86) "$(gettop)"/prebuilts/asuite/acloud/darwin-x86/acloud "$@"
-        ;;
-    *)
-        echo "acloud is not supported on your host arch: $host_os_arch"
-        ;;
-    esac
-}
-
-function aidegen()
-{
-    # Always use the prebuilt version.
-    local host_os_arch=$(get_build_var HOST_PREBUILT_TAG)
-    case $host_os_arch in
-        linux-x86) "$(gettop)"/prebuilts/asuite/aidegen/linux-x86/aidegen "$@"
-        ;;
-    *)
-        echo "aidegen is not supported on your host arch: $host_os_arch"
-        ;;
-    esac
-}
-
 # Execute the contents of any vendorsetup.sh files we can find.
+# Unless we find an allowed-vendorsetup_sh-files file, in which case we'll only
+# load those.
+#
+# This allows loading only approved vendorsetup.sh files
 function source_vendorsetup() {
+    allowed=
+    for f in $(find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
+        if [ -n "$allowed" ]; then
+            echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
+            echo "  $allowed"
+            echo "  $f"
+            return
+        fi
+        allowed="$f"
+    done
+
+    allowed_files=
+    [ -n "$allowed" ] && allowed_files=$(cat "$allowed")
     for dir in device vendor product; do
         for f in $(test -d $dir && \
             find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do
-            echo "including $f"; . $f
+
+            if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
+                echo "including $f"; . "$f"
+            else
+                echo "ignoring $f, not in $allowed"
+            fi
         done
     done
 }
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 7fe45eb..971a7b2 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -52,3 +52,59 @@
 include $(BUILD_PREBUILT)
 BUILT_VENDOR_MANIFEST := $(LOCAL_BUILT_MODULE)
 endif
+
+# ODM manifest
+ifdef ODM_MANIFEST_FILES
+# ODM_MANIFEST_FILES is a list of files that is combined and installed as the default ODM manifest.
+include $(CLEAR_VARS)
+LOCAL_MODULE := odm_manifest.xml
+LOCAL_MODULE_STEM := manifest.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := vintf
+LOCAL_ODM_MODULE := true
+
+GEN := $(local-generated-sources-dir)/manifest.xml
+$(GEN): PRIVATE_SRC_FILES := $(ODM_MANIFEST_FILES)
+$(GEN): $(ODM_MANIFEST_FILES) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	# Set VINTF_IGNORE_TARGET_FCM_VERSION to true because it should only be in device manifest.
+	VINTF_IGNORE_TARGET_FCM_VERSION=true \
+	$(HOST_OUT_EXECUTABLES)/assemble_vintf -o $@ \
+		-i $(call normalize-path-list,$(PRIVATE_SRC_FILES))
+
+LOCAL_PREBUILT_MODULE_FILE := $(GEN)
+include $(BUILD_PREBUILT)
+endif # ODM_MANIFEST_FILES
+
+# ODM_MANIFEST_SKUS: a list of SKUS where ODM_MANIFEST_<sku>_FILES are defined.
+ifdef ODM_MANIFEST_SKUS
+
+# Install /odm/etc/vintf/manifest_$(sku).xml
+# $(1): sku
+define _add_odm_sku_manifest
+my_fragment_files_var := ODM_MANIFEST_$$(call to-upper,$(1))_FILES
+ifndef $$(my_fragment_files_var)
+$$(error $(1) is in ODM_MANIFEST_SKUS but $$(my_fragment_files_var) is not defined)
+endif
+my_fragment_files := $$($$(my_fragment_files_var))
+include $$(CLEAR_VARS)
+LOCAL_MODULE := odm_manifest_$(1).xml
+LOCAL_MODULE_STEM := manifest_$(1).xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := vintf
+LOCAL_ODM_MODULE := true
+GEN := $$(local-generated-sources-dir)/manifest_$(1).xml
+$$(GEN): PRIVATE_SRC_FILES := $$(my_fragment_files)
+$$(GEN): $$(my_fragment_files) $$(HOST_OUT_EXECUTABLES)/assemble_vintf
+	VINTF_IGNORE_TARGET_FCM_VERSION=true \
+	$$(HOST_OUT_EXECUTABLES)/assemble_vintf -o $$@ \
+		-i $$(call normalize-path-list,$$(PRIVATE_SRC_FILES))
+LOCAL_PREBUILT_MODULE_FILE := $$(GEN)
+include $$(BUILD_PREBUILT)
+my_fragment_files_var :=
+my_fragment_files :=
+endef
+
+$(foreach sku, $(ODM_MANIFEST_SKUS), $(eval $(call _add_odm_sku_manifest,$(sku))))
+_add_odm_sku_manifest :=
+
+endif # ODM_MANIFEST_SKUS
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index 1e325b9..617b3c5 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -20,13 +20,15 @@
 # the GLES renderer disables itself if host GL acceleration isn't available.
 USE_OPENGL_RENDERER := true
 
-# ~100 MB vendor image. Please adjust system image / vendor image sizes
+# ~140 MB vendor image. Please adjust system image / vendor image sizes
 # when finalizing them. The partition size needs to be a multiple of image
 # block size: 4096.
-BOARD_VENDORIMAGE_PARTITION_SIZE := 100003840
+BOARD_VENDORIMAGE_PARTITION_SIZE := 140963840
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
 BOARD_FLASH_BLOCK_SIZE := 512
 DEVICE_MATRIX_FILE   := device/generic/goldfish/compatibility_matrix.xml
 
 BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/common
 
+# TODO(b/125540538): Remove when emulator uses dynamic partitions
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 1037eec..d53995c 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -6,9 +6,6 @@
 
 include build/make/target/board/BoardConfigMainlineCommon.mk
 
-# Enable system property split for Treble
-BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
-
 # This flag is set by mainline but isn't desired for GSI.
 BOARD_USES_SYSTEM_OTHER_ODEX :=
 
@@ -27,19 +24,23 @@
 
 # GSI forces product packages to /system for now.
 TARGET_COPY_OUT_PRODUCT := system/product
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE :=
 
 # Creates metadata partition mount point under root for
 # the devices with metadata parition
 BOARD_USES_METADATA_PARTITION := true
 
 # Android Verified Boot (AVB):
-#   Set AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED (--flag 2) in
-#   vbmeta.img to disable AVB verification.
+#   Set AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED (--flags 2) in
+#   vbmeta.img to disable AVB verification. Also set the rollback index
+#   to zero, to prevent the device bootloader from updating the last seen
+#   rollback index in the tamper-evident storage.
 #
 # To disable AVB for GSI, use the vbmeta.img and the GSI together.
 # To enable AVB for GSI, include the GSI public key into the device-specific
 # vbmeta.img.
-BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flag 2
+BOARD_AVB_ROLLBACK_INDEX := 0
+BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 2
 
 # Enable chain partition for system.
 BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
@@ -49,9 +50,9 @@
 
 # GSI specific System Properties
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-# GSI is always userdebug and needs a couple of properties taking precedence
-# over those set by the vendor.
 TARGET_SYSTEM_PROP := build/make/target/board/gsi_system.prop
+else
+TARGET_SYSTEM_PROP := build/make/target/board/gsi_system_user.prop
 endif
 
 # Set this to create /cache mount point for non-A/B devices that mounts /cache.
@@ -61,3 +62,7 @@
 
 # Disable 64 bit mediadrmserver
 TARGET_ENABLE_MEDIADRM_64 :=
+
+# Ordinary (non-flattened) APEX may require kernel changes. For maximum compatibility,
+# use flattened APEX for GSI
+TARGET_FLATTEN_APEX := true
diff --git a/target/board/BoardConfigMainlineCommon.mk b/target/board/BoardConfigMainlineCommon.mk
index 9a4fb3a..acbd11d 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -5,16 +5,16 @@
 # The generic product target doesn't have any hardware-specific pieces.
 TARGET_NO_BOOTLOADER := true
 TARGET_NO_KERNEL := true
+TARGET_NO_RECOVERY := true
 
 TARGET_USERIMAGES_USE_EXT4 := true
 
 # Mainline devices must have /vendor and /product partitions.
 TARGET_COPY_OUT_VENDOR := vendor
-TARGET_COPY_OUT_PRODUCT := product
+BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
 
-# system-as-root is mandatory from Android P
-TARGET_NO_RECOVERY := true
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
+TARGET_COPY_OUT_PRODUCT := product
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
 
 BOARD_VNDK_VERSION := current
 
@@ -31,5 +31,18 @@
 # Audio: must using XML format for Treblized devices
 USE_XML_AUDIO_POLICY_CONF := 1
 
+# Bluetooth defines
+# TODO(b/123695868): Remove the need for this
+BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := build/make/target/board/mainline_arm64/bluetooth
+
 BOARD_AVB_ENABLE := true
 BOARD_AVB_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+
+BOARD_CHARGER_ENABLE_SUSPEND := true
+
+# Enable A/B update
+AB_OTA_UPDATER := true
+AB_OTA_PARTITIONS := system
+
+# Enable system property split for Treble
+BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk
index 2004624..e5d8e61 100644
--- a/target/board/generic_arm64/device.mk
+++ b/target/board/generic_arm64/device.mk
@@ -14,15 +14,6 @@
 # limitations under the License.
 #
 
-# NFC:
-#   Provide default libnfc-nci.conf file for devices that does not have one in
-#   vendor/etc because aosp system image (of aosp_$arch products) is going to
-#   be used as GSI.
-#   May need to remove the following for newly launched devices in P since this
-#   NFC configuration file should be in vendor/etc, instead of system/etc
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
-
 # Adjust the Dalvik heap to be appropriate for a tablet.
 $(call inherit-product-if-exists, frameworks/base/build/tablet-dalvik-heap.mk)
 $(call inherit-product-if-exists, frameworks/native/build/tablet-dalvik-heap.mk)
diff --git a/target/board/generic_arm64_a/BoardConfig.mk b/target/board/generic_arm64_a/BoardConfig.mk
deleted file mode 100644
index 68aedfc..0000000
--- a/target/board/generic_arm64_a/BoardConfig.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_ABI := arm64-v8a
-TARGET_CPU_ABI2 :=
-TARGET_CPU_VARIANT := generic
-
-TARGET_2ND_ARCH := arm
-TARGET_2ND_ARCH_VARIANT := armv8-a
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_CPU_VARIANT := generic
-
-# This is a non-system-as-root Legacy GSI build target
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := false
diff --git a/target/board/generic_arm_a/BoardConfig.mk b/target/board/generic_arm_a/BoardConfig.mk
deleted file mode 100644
index 464a74f..0000000
--- a/target/board/generic_arm_a/BoardConfig.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm
-TARGET_ARCH_VARIANT := armv7-a-neon
-TARGET_CPU_ABI := armeabi-v7a
-TARGET_CPU_ABI2 := armeabi
-TARGET_CPU_VARIANT := generic
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
-
-# This is a non-system-as-root Legacy GSI build target
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := false
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 0a32415..bbab2b4 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,11 +14,11 @@
 # limitations under the License.
 #
 
-# NFC:
-#   Provide default libnfc-nci.conf file for devices that does not have one in
-#   vendor/etc because aosp system image (of aosp_$arch products) is going to
-#   be used as GSI.
-#   May need to remove the following for newly launched devices in P since this
-#   NFC configuration file should be in vendor/etc, instead of system/etc
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
+ifdef NET_ETH0_STARTONBOOT
+  PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
+endif
+
+# Ensure we package the BIOS files too.
+PRODUCT_HOST_PACKAGES += \
+	bios.bin \
+	vgabios-cirrus.bin \
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index 0a32415..bbab2b4 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -14,11 +14,11 @@
 # limitations under the License.
 #
 
-# NFC:
-#   Provide default libnfc-nci.conf file for devices that does not have one in
-#   vendor/etc because aosp system image (of aosp_$arch products) is going to
-#   be used as GSI.
-#   May need to remove the following for newly launched devices in P since this
-#   NFC configuration file should be in vendor/etc, instead of system/etc
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
+ifdef NET_ETH0_STARTONBOOT
+  PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
+endif
+
+# Ensure we package the BIOS files too.
+PRODUCT_HOST_PACKAGES += \
+	bios.bin \
+	vgabios-cirrus.bin \
diff --git a/target/board/generic_x86_64_a/BoardConfig.mk b/target/board/generic_x86_64_a/BoardConfig.mk
deleted file mode 100644
index 07eef4f..0000000
--- a/target/board/generic_x86_64_a/BoardConfig.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_CPU_ABI := x86_64
-TARGET_ARCH := x86_64
-TARGET_ARCH_VARIANT := x86_64
-
-TARGET_2ND_CPU_ABI := x86
-TARGET_2ND_ARCH := x86
-TARGET_2ND_ARCH_VARIANT := x86_64
-
-# This is a non-system-as-root Legacy GSI build target
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := false
diff --git a/target/board/gsi_system.prop b/target/board/gsi_system.prop
index 0c04a95..d768c83 100644
--- a/target/board/gsi_system.prop
+++ b/target/board/gsi_system.prop
@@ -4,5 +4,8 @@
 # GSI always disables adb authentication
 ro.adb.secure=0
 
+# TODO(b/120679683): disable RescueParty before all problem apps solved
+persist.sys.disable_rescue=true
+
 # TODO(b/78105955): disable privapp_permissions checking before the bug solved
 ro.control_privapp_permissions=disable
diff --git a/target/board/gsi_system_user.prop b/target/board/gsi_system_user.prop
new file mode 100644
index 0000000..becb783
--- /dev/null
+++ b/target/board/gsi_system_user.prop
@@ -0,0 +1,8 @@
+# GSI always generate dex pre-opt in system image
+ro.cp_system_other_odex=0
+
+# TODO(b/120679683): disable RescueParty before all problem apps solved
+persist.sys.disable_rescue=true
+
+# TODO(b/78105955): disable privapp_permissions checking before the bug solved
+ro.control_privapp_permissions=disable
diff --git a/target/board/mainline_arm64/bluetooth/bdroid_buildcfg.h b/target/board/mainline_arm64/bluetooth/bdroid_buildcfg.h
new file mode 100644
index 0000000..0ea8fc2
--- /dev/null
+++ b/target/board/mainline_arm64/bluetooth/bdroid_buildcfg.h
@@ -0,0 +1,28 @@
+/*
+ *
+ *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Not a Contribution, Apache license notifications and license are retained
+ *  for attribution purposes only.
+ *
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BDROID_BUILDCFG_H
+#define _BDROID_BUILDCFG_H
+
+// VSC spec support
+#define BLE_VND_INCLUDED TRUE
+
+#endif
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 12fd99a..cfb8930 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -44,16 +44,12 @@
 else
 PRODUCT_MAKEFILES := \
     $(LOCAL_DIR)/aosp_arm64_ab.mk \
-    $(LOCAL_DIR)/aosp_arm64_a.mk \
     $(LOCAL_DIR)/aosp_arm64.mk \
     $(LOCAL_DIR)/aosp_arm_ab.mk \
-    $(LOCAL_DIR)/aosp_arm_a.mk \
     $(LOCAL_DIR)/aosp_arm.mk \
     $(LOCAL_DIR)/aosp_x86_64_ab.mk \
-    $(LOCAL_DIR)/aosp_x86_64_a.mk \
     $(LOCAL_DIR)/aosp_x86_64.mk \
     $(LOCAL_DIR)/aosp_x86_ab.mk \
-    $(LOCAL_DIR)/aosp_x86_a.mk \
     $(LOCAL_DIR)/aosp_x86_arm.mk \
     $(LOCAL_DIR)/aosp_x86.mk \
     $(LOCAL_DIR)/full.mk \
diff --git a/target/product/aosp_arm.mk b/target/product/aosp_arm.mk
index 98114c1..400fa6a 100644
--- a/target/product/aosp_arm.mk
+++ b/target/product/aosp_arm.mk
@@ -21,29 +21,20 @@
 # - VNDK enforcement
 # - compatible property override enabled
 
--include device/generic/goldfish/arm32-vendor.mk
+# GSI for system/product
+$(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_common.mk)
 
-include $(SRC_TARGET_DIR)/product/full.mk
+# Enable mainline checking for excat this product name
+ifeq (aosp_arm,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
-
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
-
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
+# Emulator for vendor
+$(call inherit-product-if-exists, device/generic/goldfish/arm32-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
 
 PRODUCT_NAME := aosp_arm
+PRODUCT_DEVICE := generic
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := AOSP on ARM32
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 87e14d7..aa6ec4d 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -26,7 +26,23 @@
 # build quite specifically for the emulator, and might not be
 # entirely appropriate to inherit from for on-device configurations.
 
--include device/generic/goldfish/arm64-vendor.mk
+# GSI for system/product
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_common.mk)
+
+# Emulator for vendor
+$(call inherit-product-if-exists, device/generic/goldfish/arm64-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
+
+# Enable mainline checking for excat this product name
+ifeq (aosp_arm64,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    root/init.zygote32_64.rc \
+    root/init.zygote64_32.rc \
 
 # Copy different zygote settings for vendor.img to select by setting property
 # ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
@@ -36,33 +52,7 @@
 PRODUCT_COPY_FILES += \
     system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
-
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
-
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
-
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
-
 PRODUCT_NAME := aosp_arm64
 PRODUCT_DEVICE := generic_arm64
 PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM arm64 Emulator
+PRODUCT_MODEL := AOSP on ARM64
diff --git a/target/product/aosp_arm64_a.mk b/target/product/aosp_arm64_a.mk
deleted file mode 100644
index b1c4b7d..0000000
--- a/target/product/aosp_arm64_a.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-include build/make/target/product/treble_common_64.mk
-
-PRODUCT_NAME := aosp_arm64_a
-PRODUCT_DEVICE := generic_arm64_a
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM64
diff --git a/target/product/aosp_arm64_ab.mk b/target/product/aosp_arm64_ab.mk
index 92f5055..f707a39 100644
--- a/target/product/aosp_arm64_ab.mk
+++ b/target/product/aosp_arm64_ab.mk
@@ -24,14 +24,25 @@
 # - 64 bits binder interface
 # - system-as-root
 
-include build/make/target/product/treble_common_64.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
 
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
+# Enable mainline checking for excat this product name
+ifeq (aosp_arm64_ab,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    root/init.zygote32_64.rc \
+    root/init.zygote64_32.rc \
+
+# Copy different zygote settings for vendor.img to select by setting property
+# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
+#   1. 64-bit primary, 32-bit secondary OR
+#   2. 32-bit primary, 64-bit secondary
+# init.zygote64_32.rc is in the core_64_bit.mk below
+PRODUCT_COPY_FILES += \
+    system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
 
 PRODUCT_NAME := aosp_arm64_ab
 PRODUCT_DEVICE := generic_arm64_ab
diff --git a/target/product/aosp_arm_a.mk b/target/product/aosp_arm_a.mk
deleted file mode 100644
index d89a326..0000000
--- a/target/product/aosp_arm_a.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-include build/make/target/product/treble_common_32.mk
-
-PRODUCT_NAME := aosp_arm_a
-PRODUCT_DEVICE := generic_arm_a
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM32
diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk
index b35e517..e760932 100644
--- a/target/product/aosp_arm_ab.mk
+++ b/target/product/aosp_arm_ab.mk
@@ -24,14 +24,12 @@
 # - 32 bits binder interface
 # - system-as-root
 
-include build/make/target/product/treble_common_32.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
 
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
+# Enable mainline checking for excat this product name
+ifeq (aosp_arm_ab,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
 PRODUCT_NAME := aosp_arm_ab
 PRODUCT_DEVICE := generic_arm_ab
diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk
index 50d7355..b16b5ed 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -21,29 +21,20 @@
 # - VNDK enforcement
 # - compatible property override enabled
 
--include device/generic/goldfish/x86-vendor.mk
+# GSI for system/product
+$(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_common.mk)
 
-include $(SRC_TARGET_DIR)/product/full_x86.mk
+# Emulator for vendor
+$(call inherit-product-if-exists, device/generic/goldfish/x86-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
 
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
-
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
-
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
+# Enable mainline checking for excat this product name
+ifeq (aosp_x86,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
 PRODUCT_NAME := aosp_x86
+PRODUCT_DEVICE := generic_x86
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := AOSP on x86
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index 499831b..f7e2056 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -26,7 +26,23 @@
 # build quite specifically for the emulator, and might not be
 # entirely appropriate to inherit from for on-device configurations.
 
--include device/generic/goldfish/x86_64-vendor.mk
+# GSI for system/product
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_common.mk)
+
+# Emulator for vendor
+$(call inherit-product-if-exists, device/generic/goldfish/x86_64-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
+
+# Enable mainline checking for excat this product name
+ifeq (aosp_x86_64,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    root/init.zygote32_64.rc \
+    root/init.zygote64_32.rc \
 
 # Copy different zygote settings for vendor.img to select by setting property
 # ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
@@ -36,43 +52,7 @@
 PRODUCT_COPY_FILES += \
     system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
-
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
-
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
-
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
-
-ifdef NET_ETH0_STARTONBOOT
-  PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
-endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_PACKAGES += \
-	bios.bin \
-	vgabios-cirrus.bin \
-
-# Overrides
 PRODUCT_NAME := aosp_x86_64
 PRODUCT_DEVICE := generic_x86_64
 PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on IA x86_64 Emulator
+PRODUCT_MODEL := AOSP on x86_64
diff --git a/target/product/aosp_x86_64_a.mk b/target/product/aosp_x86_64_a.mk
deleted file mode 100644
index 6b6785a..0000000
--- a/target/product/aosp_x86_64_a.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-include build/make/target/product/treble_common_64.mk
-
-PRODUCT_NAME := aosp_x86_64_a
-PRODUCT_DEVICE := generic_x86_64_a
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86_64
diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk
index 35bf61a..dfb7b49 100644
--- a/target/product/aosp_x86_64_ab.mk
+++ b/target/product/aosp_x86_64_ab.mk
@@ -24,14 +24,25 @@
 # - 64 bits binder interface
 # - system-as-root
 
-include build/make/target/product/treble_common_64.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
 
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
+# Enable mainline checking for excat this product name
+ifeq (aosp_x86_64_ab,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    root/init.zygote32_64.rc \
+    root/init.zygote64_32.rc \
+
+# Copy different zygote settings for vendor.img to select by setting property
+# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
+#   1. 64-bit primary, 32-bit secondary OR
+#   2. 32-bit primary, 64-bit secondary
+# init.zygote64_32.rc is in the core_64_bit.mk below
+PRODUCT_COPY_FILES += \
+    system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
 
 PRODUCT_NAME := aosp_x86_64_ab
 PRODUCT_DEVICE := generic_x86_64_ab
diff --git a/target/product/aosp_x86_a.mk b/target/product/aosp_x86_a.mk
deleted file mode 100644
index 99ed7e4..0000000
--- a/target/product/aosp_x86_a.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-include build/make/target/product/treble_common_32.mk
-
-PRODUCT_NAME := aosp_x86_a
-PRODUCT_DEVICE := generic_x86_a
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86
diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk
index 185e2f0..d07351c 100644
--- a/target/product/aosp_x86_ab.mk
+++ b/target/product/aosp_x86_ab.mk
@@ -24,14 +24,12 @@
 # - 32 bits binder interface
 # - system-as-root
 
-include build/make/target/product/treble_common_32.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
 
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
-    update_engine \
-    update_verifier
+# Enable mainline checking for excat this product name
+ifeq (aosp_x86_ab,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
 PRODUCT_NAME := aosp_x86_ab
 PRODUCT_DEVICE := generic_x86_ab
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index fe49959..c3a7516 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -17,10 +17,8 @@
 # Base modules and settings for the system partition.
 PRODUCT_PACKAGES += \
     abb \
-    adb \
     adbd \
     am \
-    android.frameworks.bufferhub@1.0-service \
     android.hidl.allocator@1.0-service \
     android.hidl.base-V1.0-java \
     android.hidl.manager-V1.0-java \
@@ -35,12 +33,11 @@
     appops \
     app_process \
     appwidget \
-    atest \
+    ashmemd \
     atrace \
     audioserver \
     BackupRestoreConfirmation \
     bcc \
-    bit \
     blank_screen \
     blkid \
     bmgr \
@@ -50,6 +47,7 @@
     bu \
     bugreport \
     bugreportz \
+    cgroups.json \
     charger \
     cmd \
     com.android.conscrypt \
@@ -71,10 +69,10 @@
     dpm \
     dumpstate \
     dumpsys \
+    DynamicSystemInstallationService \
     e2fsck \
     ExtServices \
     ExtShared \
-    fastboot \
     flags_health_check \
     framework \
     framework-res \
@@ -83,6 +81,7 @@
     fs_config_files_system \
     fs_config_dirs_system \
     gsid \
+    gsi_tool \
     heapprofd \
     heapprofd_client \
     gatekeeperd \
@@ -97,7 +96,6 @@
     incident \
     incidentd \
     incident_helper \
-    incident_report \
     init.environ.rc \
     init.rc \
     init_system \
@@ -118,6 +116,8 @@
     libandroidfw \
     libandroid_runtime \
     libandroid_servers \
+    libartpalette-system \
+    libashmemd_client \
     libaudioeffect_jni \
     libbinder \
     libbinder_ndk \
@@ -153,7 +153,6 @@
     libmedia \
     libmedia_jni \
     libmediandk \
-    libmediaplayerservice \
     libmtp \
     libnetd_client \
     libnetlink \
@@ -168,7 +167,6 @@
     libradio_metadata \
     librtp_jni \
     libsensorservice \
-    libsigchain \
     libskia \
     libsonic \
     libsonivox \
@@ -182,7 +180,6 @@
     libstagefright_omx \
     libstdc++ \
     libsurfaceflinger \
-    libsurfaceflinger_ddmconnection \
     libsysutils \
     libui \
     libusbhost \
@@ -201,7 +198,6 @@
     lshal \
     mdnsd \
     media \
-    media_cmd \
     mediacodec.policy \
     mediadrmserver \
     mediaextractor \
@@ -209,7 +205,6 @@
     media_profiles_V1_0.dtd \
     MediaProvider \
     mediaserver \
-    mediaswcodec \
     mke2fs \
     monkey \
     mtpd \
@@ -251,6 +246,7 @@
     storaged \
     surfaceflinger \
     svc \
+    task_profiles.json \
     tc \
     telecom \
     telephony-common \
@@ -277,15 +273,50 @@
     framework_manifest.xml \
     system_compatibility_matrix.xml \
 
+# Host tools to install
+PRODUCT_HOST_PACKAGES += \
+    BugReport \
+    adb \
+    art-tools \
+    atest \
+    bcc \
+    bit \
+    e2fsck \
+    fastboot \
+    flags_health_check \
+    icu-data_host_runtime_apex \
+    idmap2 \
+    incident_report \
+    ld.mc \
+    lpdump \
+    mdnsd \
+    minigzip \
+    mke2fs \
+    resize2fs \
+    sgdisk \
+    sqlite3 \
+    tinyplay \
+    tune2fs \
+    tzdatacheck \
+    unwind_info \
+    unwind_reg_info \
+    unwind_symbols \
+    viewcompiler \
+    tzdata_host \
+    tzdata_host_runtime_apex \
+    tzlookup.xml_host_runtime_apex \
+    tz_version_host \
+    tz_version_host_runtime_apex \
+
 ifeq ($(TARGET_CORE_JARS),)
 $(error TARGET_CORE_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
 endif
 
-# The order matters
+# The order matters for runtime class lookup performance.
 PRODUCT_BOOT_JARS := \
     $(TARGET_CORE_JARS) \
-    ext \
     framework \
+    ext \
     telephony-common \
     voip-common \
     ims-common \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 224bfdf..584327c 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -18,6 +18,8 @@
 PRODUCT_PACKAGES += \
     adbd.recovery \
     android.hardware.health@2.0-impl-default.recovery \
+    cgroups.recovery.json \
+    charger.recovery \
     init_second_stage.recovery \
     ld.config.recovery.txt \
     linker.recovery \
@@ -25,10 +27,20 @@
     shell_and_utilities_recovery \
     watchdogd.recovery \
 
+# These had been pulled in via init_second_stage.recovery, but may not be needed.
+PRODUCT_HOST_PACKAGES += \
+    e2fsdroid \
+    mke2fs \
+    sload_f2fs \
+    make_f2fs \
+
+PRODUCT_HOST_PACKAGES += \
+    icu-data_host_runtime_apex
+
 # Base modules and settings for the vendor partition.
 PRODUCT_PACKAGES += \
-    android.hardware.cas@1.0-service \
-    android.hardware.configstore@1.2-service \
+    android.hardware.cas@1.1-service \
+    android.hardware.configstore@1.1-service \
     android.hardware.media.omx@1.0-service \
     dumpsys_vendor \
     fs_config_files_nonsystem \
diff --git a/target/product/emulator_vendor.mk b/target/product/emulator_vendor.mk
new file mode 100644
index 0000000..f0a5354
--- /dev/null
+++ b/target/product/emulator_vendor.mk
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# This file is included by other product makefiles to add all the
+# emulator-related modules to PRODUCT_PACKAGES.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
+
+# TODO(b/123495142): these files should be clean up
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST := \
+    system/bin/vintf \
+    system/etc/permissions/android.software.verified_boot.xml \
+    system/etc/permissions/privapp-permissions-goldfish.xml \
+    system/lib/egl/libGLES_android.so \
+    system/lib64/egl/libGLES_android.so \
+    system/priv-app/SdkSetup/SdkSetup.apk \
+
+# Device modules
+PRODUCT_PACKAGES += \
+    libGLES_android \
+    vintf \
+
+# need this for gles libraries to load properly
+# after moving to /vendor/lib/
+PRODUCT_PACKAGES += \
+    vndk-sp
+
+PRODUCT_PACKAGE_OVERLAYS := device/generic/goldfish/overlay
+
+PRODUCT_CHARACTERISTICS := emulator
+
+PRODUCT_FULL_TREBLE_OVERRIDE := true
+
+# goldfish vendor partition configurations
+$(call inherit-product-if-exists, device/generic/goldfish/vendor.mk)
+
+#watchdog tiggers reboot because location service is not
+#responding, disble it for now.
+#still keep it on internal master as it is still working
+#once it is fixed in aosp, remove this block of comment.
+#PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+#config.disable_location=true
+
+# Enable Perfetto traced
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+    persist.traced.enable=1
+
+# enable Google-specific location features,
+# like NetworkLocationProvider and LocationCollector
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+    ro.com.google.locationfeatures=1
+
+# disable setupwizard
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+    ro.setupwizard.mode=DISABLED
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index a76b07c..55c450a 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -32,7 +32,7 @@
 endif
 
 # Ensure we package the BIOS files too.
-PRODUCT_PACKAGES += \
+PRODUCT_HOST_PACKAGES += \
 	bios.bin \
 	vgabios-cirrus.bin \
 
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index 5c68fe8..a756181 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -36,15 +36,19 @@
 # Do not generate libartd.
 PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD := false
 
-# Do not spin up a separate process for the network stack on go devices, use an in-process lib.
-PRODUCT_PACKAGES += NetworkStackLib
-PRODUCT_SYSTEM_SERVER_JARS += NetworkStackLib
+# Do not spin up a separate process for the network stack on go devices, use an in-process APK.
+PRODUCT_PACKAGES += InProcessNetworkStack
 
 # Strip the local variable table and the local variable type table to reduce
 # the size of the system image. This has no bearing on stack traces, but will
 # leave less information available via JDWP.
 PRODUCT_MINIMIZE_JAVA_DEBUG_INFO := true
 
+# Disable Scudo outside of eng builds to save RAM.
+ifneq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
+  PRODUCT_DISABLE_SCUDO := true
+endif
+
 # Add the system properties.
 TARGET_SYSTEM_PROP += \
     build/make/target/board/go_defaults_common.prop
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index 7953db0..eaaa051 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -100,11 +100,14 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := vndk_package
 LOCAL_REQUIRED_MODULES := \
-    $(addsuffix .vendor,$(VNDK_CORE_LIBRARIES)) \
-    $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES)) \
     $(LLNDK_LIBRARIES) \
     llndk.libraries.txt \
     vndksp.libraries.txt
+ifneq ($(TARGET_SKIP_CURRENT_VNDK),true)
+LOCAL_REQUIRED_MODULES += \
+    $(addsuffix .vendor,$(VNDK_CORE_LIBRARIES)) \
+    $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES))
+endif
 include $(BUILD_PHONY_PACKAGE)
 
 include $(CLEAR_VARS)
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/current.txt b/target/product/gsi/current.txt
index 8ba27aa..657aa07 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -5,6 +5,7 @@
 LLNDK: libRS.so
 LLNDK: libandroid_net.so
 LLNDK: libc.so
+LLNDK: libcgrouprc.so
 LLNDK: libdl.so
 LLNDK: libft2.so
 LLNDK: liblog.so
@@ -44,6 +45,7 @@
 VNDK-SP: libhwbinder.so
 VNDK-SP: libhwbinder_noltopgo.so
 VNDK-SP: libion.so
+VNDK-SP: libjsoncpp.so
 VNDK-SP: liblzma.so
 VNDK-SP: libprocessgroup.so
 VNDK-SP: libunwindstack.so
@@ -91,12 +93,13 @@
 VNDK-core: android.hardware.camera.metadata@3.3.so
 VNDK-core: android.hardware.camera.metadata@3.4.so
 VNDK-core: android.hardware.camera.provider@2.4.so
+VNDK-core: android.hardware.camera.provider@2.5.so
 VNDK-core: android.hardware.cas.native@1.0.so
 VNDK-core: android.hardware.cas@1.0.so
+VNDK-core: android.hardware.cas@1.1.so
 VNDK-core: android.hardware.configstore-utils.so
 VNDK-core: android.hardware.configstore@1.0.so
 VNDK-core: android.hardware.configstore@1.1.so
-VNDK-core: android.hardware.configstore@1.2.so
 VNDK-core: android.hardware.confirmationui-support-lib.so
 VNDK-core: android.hardware.confirmationui@1.0.so
 VNDK-core: android.hardware.contexthub@1.0.so
@@ -205,6 +208,9 @@
 VNDK-core: libcamera_metadata.so
 VNDK-core: libcap.so
 VNDK-core: libcn-cbor.so
+VNDK-core: libcodec2.so
+VNDK-core: libcodec2_hidl@1.0.so
+VNDK-core: libcodec2_vndk.so
 VNDK-core: libcrypto.so
 VNDK-core: libcrypto_utils.so
 VNDK-core: libcurl.so
@@ -233,7 +239,6 @@
 VNDK-core: libnetutils.so
 VNDK-core: libnl.so
 VNDK-core: libopus.so
-VNDK-core: libpagemap.so
 VNDK-core: libpcre2.so
 VNDK-core: libpiex.so
 VNDK-core: libpng.so
@@ -249,11 +254,13 @@
 VNDK-core: libsqlite.so
 VNDK-core: libssl.so
 VNDK-core: libstagefright_amrnb_common.so
+VNDK-core: libstagefright_bufferpool@2.0.so
 VNDK-core: libstagefright_bufferqueue_helper.so
 VNDK-core: libstagefright_enc_common.so
 VNDK-core: libstagefright_flacdec.so
 VNDK-core: libstagefright_foundation.so
 VNDK-core: libstagefright_omx.so
+VNDK-core: libstagefright_omx_soft.so
 VNDK-core: libstagefright_omx_utils.so
 VNDK-core: libstagefright_soft_aacdec.so
 VNDK-core: libstagefright_soft_aacenc.so
diff --git a/target/product/gsi_arm64.mk b/target/product/gsi_arm64.mk
index cf4baba..b711d88 100644
--- a/target/product/gsi_arm64.mk
+++ b/target/product/gsi_arm64.mk
@@ -17,6 +17,8 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_common.mk)
 
+# Enable mainline checking
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     root/init.zygote32_64.rc \
     root/init.zygote64_32.rc \
@@ -33,4 +35,3 @@
 PRODUCT_DEVICE := gsi_arm64
 PRODUCT_BRAND := generic
 PRODUCT_MODEL := GSI on ARM64
-
diff --git a/target/product/gsi_common.mk b/target/product/gsi_common.mk
index 0006e62..2c978ab 100644
--- a/target/product/gsi_common.mk
+++ b/target/product/gsi_common.mk
@@ -24,19 +24,18 @@
 $(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
 
 # Additional settings used in all AOSP builds
-PRODUCT_PROPERTY_OVERRIDES := \
+PRODUCT_PROPERTY_OVERRIDES += \
     ro.config.ringtone=Ring_Synth_04.ogg \
     ro.config.notification_sound=pixiedust.ogg
 
-
-# Enable mainline checking and the whitelist for GSI
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST := \
+# The mainline checking whitelist, should be clean up
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/app/messaging/messaging.apk \
-    system/app/PhotoTable/PhotoTable.apk \
     system/app/WAPPushManager/WAPPushManager.apk \
     system/bin/healthd \
     system/etc/init/healthd.rc \
+    system/etc/seccomp_policy/crash_dump.%.policy \
+    system/etc/seccomp_policy/mediacodec.policy \
     system/etc/vintf/manifest/manifest_healthd.xml \
     system/lib/libframesequence.so \
     system/lib/libgiftranscode.so \
@@ -51,11 +50,12 @@
 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
+# Exclude all files under system/product and system/product_services
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/product/%
-
+    system/product/% \
+    system/product_services/%
 
 # Split selinux policy
 PRODUCT_FULL_TREBLE_OVERRIDE := true
@@ -63,10 +63,6 @@
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-
 # Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
 PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
 
@@ -96,3 +92,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/treble_common_32.mk b/target/product/gsi_keys.mk
similarity index 60%
rename from target/product/treble_common_32.mk
rename to target/product/gsi_keys.mk
index 0023c3b..5a814db 100644
--- a/target/product/treble_common_32.mk
+++ b/target/product/gsi_keys.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2017 The Android Open-Source Project
+# Copyright (C) 2019 The Android Open-Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
 # limitations under the License.
 #
 
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# treble_system.prop.
-
-include build/make/target/product/treble_common.mk
+# Include GSI keys into first-stage ramdisk, so we can enable verified
+# boot when booting a GSI.
+PRODUCT_PACKAGES += \
+    q-gsi.avbpubkey \
+    r-gsi.avbpubkey \
+    s-gsi.avbpubkey \
diff --git a/target/product/handheld_product.mk b/target/product/handheld_product.mk
index 758fa9b..0d100b2 100644
--- a/target/product/handheld_product.mk
+++ b/target/product/handheld_product.mk
@@ -40,3 +40,7 @@
     StorageManager \
     SystemUI \
     WallpaperCropper \
+    frameworks-base-overlays
+
+PRODUCT_PACKAGES_DEBUG += \
+    frameworks-base-overlays-debug
diff --git a/target/product/handheld_vendor.mk b/target/product/handheld_vendor.mk
index 755ac70..cb7cf74 100644
--- a/target/product/handheld_vendor.mk
+++ b/target/product/handheld_vendor.mk
@@ -22,22 +22,8 @@
 
 # /vendor packages
 PRODUCT_PACKAGES += \
-    AccentColorBlackOverlay \
-    AccentColorGreenOverlay \
-    AccentColorPurpleOverlay \
     audio.primary.default \
-    DisplayCutoutEmulationCornerOverlay \
-    DisplayCutoutEmulationDoubleOverlay \
-    DisplayCutoutEmulationTallOverlay \
-    FontArbutusSourceOverlay \
-    FontArvoLatoOverlay \
-    FontRubikRubikOverlay \
-    IconShapeRoundedRectOverlay \
-    IconShapeSquircleOverlay \
-    IconShapeTeardropOverlay \
     local_time.default \
     power.default \
     vibrator.default \
 
-PRODUCT_PACKAGES_DEBUG += \
-    frameworks-base-overlays \
diff --git a/target/product/legacy_gsi_common.mk b/target/product/legacy_gsi_common.mk
new file mode 100644
index 0000000..fdae6eb
--- /dev/null
+++ b/target/product/legacy_gsi_common.mk
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+include $(SRC_TARGET_DIR)/product/gsi_common.mk
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/etc/init/init.legacy-gsi.rc \
+    system/etc/init/gsi/init.vndk-27.rc \
+    system/etc/ld.config.vndk_lite.txt \
+
+# Legacy GSI support addtional O-MR1 interface
+PRODUCT_EXTRA_VNDK_VERSIONS += 27
+
+# Support for the O-MR1 devices
+PRODUCT_COPY_FILES += \
+    build/make/target/product/gsi/init.legacy-gsi.rc:system/etc/init/init.legacy-gsi.rc \
+    build/make/target/product/gsi/init.vndk-27.rc:system/etc/init/gsi/init.vndk-27.rc
+
+# Name space configuration file for non-enforcing VNDK
+PRODUCT_PACKAGES += \
+    ld.config.vndk_lite.txt
+
+# Legacy GSI relax the compatible property checking
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := false
diff --git a/target/product/mainline.mk b/target/product/mainline.mk
index 59bad98..7900cdf 100644
--- a/target/product/mainline.mk
+++ b/target/product/mainline.mk
@@ -14,10 +14,24 @@
 # limitations under the License.
 #
 
-# Makefile including the mainline system image, and the relevant AOSP portions
-# for the other partitions.
+# This makefile is intended to serve as a base for completely AOSP based
+# mainline devices, It contain the mainline system partition and sensible
+# defaults for the product and vendor partition.
 $(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_product.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_product.mk)
+
+$(call inherit-product, frameworks/base/data/sounds/AllAudio.mk)
+
+PRODUCT_PROPERTY_OVERRIDES += \
+    ro.config.ringtone=Ring_Synth_04.ogg \
+    ro.com.android.dataroaming=true \
+
+PRODUCT_PACKAGES += \
+    PhotoTable \
+    WallpaperPicker \
+
+PRODUCT_COPY_FILES += device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml
diff --git a/target/product/mainline_arm64.mk b/target/product/mainline_arm64.mk
index dcb6fe0..622fe94 100644
--- a/target/product/mainline_arm64.mk
+++ b/target/product/mainline_arm64.mk
@@ -16,6 +16,7 @@
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/mainline.mk)
+$(call enforce-product-packages-exist,)
 
 PRODUCT_NAME := mainline_arm64
 PRODUCT_DEVICE := mainline_arm64
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index b382add..2c3a76e 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -27,7 +27,6 @@
 
 # Applications
 PRODUCT_PACKAGES += \
-    DMService \
     LiveWallpapersPicker \
     PartnerBookmarksProvider \
     PresencePolling \
@@ -82,16 +81,13 @@
     android.hardware.radio.config@1.0 \
     android.hardware.radio.deprecated@1.0 \
     android.hardware.secure_element@1.0 \
-    android.hardware.tests.libhwbinder@1.0-impl \
     android.hardware.wifi@1.0 \
-    android.hidl.base@1.0 \
     libaudio-resampler \
     liblogwrap \
     liblz4 \
     libminui \
     libnl \
     libprotobuf-cpp-full \
-    libprotobuf-cpp-full-rtti \
 
 PRODUCT_PACKAGES_DEBUG += \
     avbctl \
@@ -102,6 +98,9 @@
     tinypcminfo \
     update_engine_client \
 
+PRODUCT_HOST_PACKAGES += \
+    tinyplay
+
 # Enable stats logging in LMKD
 TARGET_LMKD_STATS_LOG := true
 PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
diff --git a/target/product/mainline_system_arm64.mk b/target/product/mainline_system_arm64.mk
index 560dfd3..f01cc54 100644
--- a/target/product/mainline_system_arm64.mk
+++ b/target/product/mainline_system_arm64.mk
@@ -16,6 +16,17 @@
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+$(call enforce-product-packages-exist,)
+
+PRODUCT_BUILD_CACHE_IMAGE := false
+PRODUCT_BUILD_ODM_IMAGE := false
+PRODUCT_BUILD_PRODUCT_IMAGE  := false
+PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE := false
+PRODUCT_BUILD_RAMDISK_IMAGE := false
+PRODUCT_BUILD_SYSTEM_IMAGE := true
+PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false
+PRODUCT_BUILD_USERDATA_IMAGE := false
+PRODUCT_BUILD_VENDOR_IMAGE := false
 
 PRODUCT_NAME := mainline_system_arm64
 PRODUCT_DEVICE := mainline_arm64
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index b59bbd3..cd4e9c6 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -59,6 +59,8 @@
     StatementService \
     vndk_snapshot_package \
 
+PRODUCT_HOST_PACKAGES += \
+    fsck.f2fs \
 
 PRODUCT_COPY_FILES += \
     frameworks/native/data/etc/android.software.webview.xml:system/etc/permissions/android.software.webview.xml
diff --git a/target/product/profile_boot_common.mk b/target/product/profile_boot_common.mk
index f243902..4147dfa 100644
--- a/target/product/profile_boot_common.mk
+++ b/target/product/profile_boot_common.mk
@@ -41,5 +41,8 @@
 
 # Use speed compiler filter since system server doesn't have JIT.
 PRODUCT_DEX_PREOPT_BOOT_FLAGS += --compiler-filter=speed
+# System server is speed compiled and doesn't have a separate preopt flag,
+# so we enable hotness in compiled code for everything.
+PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := --count-hotness-in-compiled-code
 
 PRODUCT_DIST_BOOT_AND_SYSTEM_JARS := true
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index 3391a57..b84584b 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -33,17 +33,14 @@
 PRODUCT_PACKAGES += \
     ext \
 
-# Libcore ICU. TODO: Try to figure out if/why we need them explicitly.
+# Libcore ICU. TODO(b/124218500): Remove them explicitly when the bug is resolved.
 PRODUCT_PACKAGES += \
     libicui18n \
     libicuuc \
 
-# ART.
-PRODUCT_PACKAGES += art-runtime
-# ART/dex helpers.
-PRODUCT_PACKAGES += art-tools
 # Android Runtime APEX module.
 PRODUCT_PACKAGES += com.android.runtime
+PRODUCT_HOST_PACKAGES += com.android.runtime
 
 # Certificates.
 PRODUCT_PACKAGES += \
@@ -87,6 +84,10 @@
     pm.dexopt.inactive=verify \
     pm.dexopt.shared=speed
 
+# Enable resolution of startup const strings.
+# PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+#    dalvik.vm.dex2oat-resolve-startup-strings=true
+
 # Enable minidebuginfo generation unless overridden.
 PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
     dalvik.vm.minidebuginfo=true \
diff --git a/target/product/security/com.android.conscrypt.pk8 b/target/product/security/com.android.conscrypt.pk8
deleted file mode 100644
index 4c04deb..0000000
--- a/target/product/security/com.android.conscrypt.pk8
+++ /dev/null
Binary files differ
diff --git a/target/product/security/com.android.conscrypt.x509.pem b/target/product/security/com.android.conscrypt.x509.pem
deleted file mode 100644
index ba914fa..0000000
--- a/target/product/security/com.android.conscrypt.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1DCCA7ygAwIBAgIJAN0lMAb+9i0JMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMR4wHAYDVQQD
-DBVjb20uYW5kcm9pZC5jb25zY3J5cHQwIBcNMTkwMTI1MTcxNjM3WhgPNDc1NjEy
-MjExNzE2MzdaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw
-FAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQL
-DAdBbmRyb2lkMR4wHAYDVQQDDBVjb20uYW5kcm9pZC5jb25zY3J5cHQwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCcfdThwuWhAk0362p7+s/8xL0Hi6Fe
-orQL30Kat8iK4ZPWM5HxOY1zmktBzjgKQ0qM4fuvHzrQJr2+SLl+l2miX4XTruAL
-w7MBS1EGzh0YC4cOBq9z8IsAW/lB6MDeAJ6TuflTk5BRun+bDB70IkWd0ylYSiTi
-AWEs4LM03rBbTcxpNuoLMj1PDNkNOmWiu0rtRbO2Y5+GI9Kw2lyPsWKkU0ixifq2
-o3gHAepmwD7bt5tDFSuOW+uCeF7TzyqsE/CFvqWYUn+5rlOlcyFARAgCh1NZXqxq
-mkcyI9vmtneIUimYw0dzgNoG0dijYAvpuQgSr0HSa2JBiQOgMrJug2PtmWpH2PNk
-UubVZYSfPiO4wTB9Jus63Y27KRdo4Bz4R4n/u0FjIi/cu0Zms07MTo60NPaGHNM/
-nMJSEDDjQ7ppoPXsamn0DID8HlZMivmcQgzokWswxw4b/i1O2fUotKEDf3wvJhUB
-4U7bAgF55FNWWfcaHYqhytWc0qO4zdMUyVqFF+/Db3hz4IkhJyzjCYxBovSSx4yN
-atHa93SwM+uH1s2iI3gOJbn/SrsfKbkrU85S5zVRDEOQg9lm2d99PMnXqXED7bRw
-G9pKmUfOzMANm8yhvL/urlSXVDHxtdw+IJGSVUlzYT3OAx2eFdnpiymiQyWotr8W
-IXfOyr/lB6IkvQIDAQABo1MwUTAdBgNVHQ4EFgQU/vXb6Hy1AxgAxhDuwnO457cD
-3+owHwYDVR0jBBgwFoAU/vXb6Hy1AxgAxhDuwnO457cD3+owDwYDVR0TAQH/BAUw
-AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARVpJBLitmnJXL/suxt+IsszEBz/pj5g1
-uwor1L3Zvb8j614BhqrKFlPia3PKlHJHotNugjs35CrQ6S4zC3Dx3R2Wb/hBOhtk
-bfpjKZuWaPvqHx1nlBsRa6H7tOKOW/6DHkkb/L5oJo7FPZT0Y0XNandFAmveBL69
-CLZS5dFnhkbVHi7PuvSwcFEXSr/fozcIMnCsQAds42cWqlWlDDVq90vYzOM+jQxS
-cctJ3cZiL0heWEyiZmG0J95Z6kB28gEmaDw8LNUwaUsyaO7U6GwXIe/KQvI2cT/F
-yjpkBmKqDr89Xvyd9DYtZv8GbndTQLwyrPhlKLNOoly3jqjbxqAZGBpyxwVDU+Mo
-/NwkCheQeEYLrGXBgv9fLfyOLSZA7yihPTc0IQcm27DnpkZmJ/lWJ5jDG0VEkNp+
-60O5GYCs2/r3tO+YoiDSFNjsFgCoTcnOQwYhbBZC7YJLOKV0lYDjfsohE6tcCUuS
-H8Ln6Em9HhFAXZBVQU0N+OyC0bAuDTD72ClvbMQikyeWwhdvY3F0x5dDima0liqe
-0jMTJxlizLoa2YKOiLqLomLt6+sJawF0+bGSKSHpcy0NoopXTb3UBlkFpxRp9UnN
-vrnN6KyRzj7OssDEHfXSZgSR0ZAVrAsgP3vc+lBpze9jtNbITDV1gOxUBX771hdU
-UIxewtyODcY=
------END CERTIFICATE-----
diff --git a/target/product/security/com.android.media.pk8 b/target/product/security/com.android.media.pk8
deleted file mode 100644
index 6df741e..0000000
--- a/target/product/security/com.android.media.pk8
+++ /dev/null
Binary files differ
diff --git a/target/product/security/com.android.media.x509.pem b/target/product/security/com.android.media.x509.pem
deleted file mode 100644
index e7908fa..0000000
--- a/target/product/security/com.android.media.x509.pem
+++ /dev/null
@@ -1,33 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFzDCCA7SgAwIBAgIJAO05DBBusaaLMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRowGAYDVQQD
-DBFjb20uYW5kcm9pZC5tZWRpYTAgFw0xOTAxMjUxNzE3MTdaGA80NzU2MTIyMTE3
-MTcxN1owejELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
-BAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsMB0Fu
-ZHJvaWQxGjAYBgNVBAMMEWNvbS5hbmRyb2lkLm1lZGlhMIICIjANBgkqhkiG9w0B
-AQEFAAOCAg8AMIICCgKCAgEAmNkVxUbp/bLbeGbvKqYXzwBycSDpmOhh///lNGYQ
-/AMUD0q6EaZzU2bd4aL0rOGqfoYlhKd0kMVmMUmfdE9ODAfKxleEeEaRl2GJS8a9
-ABi770l3GHbB2xMI2sEWeOD9xsPFF6+ByPZmoUuNhMr4pUbXsDpE3h8ljrgXHtIg
-bh7ofbvddruwBV0lS1k9OZ9jPVGhEKkJnhgQa67cwgdjizAMbI0Dcz9gtMMawsDj
-Z2aQd1r+vxgh1/XkI/NMmXCnG2ERytXcJeC5S4gEtHfTTPoP0FuVgSB6y6dalMuZ
-F0NBZw8Mvgdy3QJip0uNa36J63CMZKTJWbTdlFpPL2hk0PgaYvje8C5Xtk5282wT
-dMocc8n2zIXbzbnSXGvjcNZib3Pfu55YUnX6eTqZ1BxlJ0FHZAsC4quFFWXxYBYD
-LCRoNNFEtIDQpuvuHF2DuHNDULpAQjy2y6+7eot0KEsVoDmZ4H8BpuAVVu2SxYNb
-gYflR9SmM0tmYeAcRT48q3xrocGyEHMqvgQRUpPfvct/8l8xVcDzOI/sJVDqmYzM
-u0Cj3fkSypGDJOMF/esFSmVvoI01tS7kaNS5vvtKYib//xqKRC9f0dCsGfFLnuUK
-o4KYbYWYwMyJqEd/5/ZvXyKIPAEeJL174L9+wTkc3cQpoBwJN4t+2E5MnhOEq6do
-5L0CAwEAAaNTMFEwHQYDVR0OBBYEFHjNK/GZko1RdZp+8iavWXL5xz9wMB8GA1Ud
-IwQYMBaAFHjNK/GZko1RdZp+8iavWXL5xz9wMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQELBQADggIBACmPQMksuLrNV1vbI44S1f70I0FHdBxchFGB39zuLbcn
-SsYom/LPtYJiD0Dl4bB4eb+ZnxkQP2XeP6pycmUH2j1EWexFwvdUvlfe8Qz+wAec
-ap4AxiX4Z2Ke2ivYotIZFUHdZOLkX20js8Wex1mzY43MLQn5APl9gK1VZTxDggeR
-EObH1S+JVjGwQqYZj2e6gNZH34Q25NQ698RL85GDkYtSISAifJtaJsU/B3vKm82I
-k9xMiCooCH6bRdGHG1jze4SRpidjxEm8cxkiaQagfcuXeCLziXJr3qAMKYiEY6bp
-0+bAqCt3S8OrrN3RQZfQrnlwitsM1jJJ/+C+WoDg4eY5AFrXDLvNeKh1qO/f8xv+
-fCXkQPcVVphLfRH9oxNrSgOWBP5/qIDH4s1YUL9luGT6H+08dlue3RkbzDbBqsQu
-7fQ/BbrIG/GuVKgyEM+a7C9gv7zc86YlueVYJEyxKidnn7RxOqyDBqyyfXA3zvme
-Rro7xIrMHPL7Nu3AWjwjXzbp/w0z+tEFPsfVB+OOHKsWPcUG0HUTJGkyeO/uHRjN
-qPEkkf7BHHUO4V2gjOIdCsELxKwHf7vsZTOk40EV751fZ7FDHMr1eddQkgH4eqAb
-DB79uP+SLfUo+42n4q6eMmoqw8d76bBXRoUhIo/Ms4sebhV0sRtAS67OQioc9UUg
------END CERTIFICATE-----
diff --git a/target/product/security/com.android.resolv.pk8 b/target/product/security/com.android.resolv.pk8
deleted file mode 100644
index 3481a69..0000000
--- a/target/product/security/com.android.resolv.pk8
+++ /dev/null
Binary files differ
diff --git a/target/product/security/com.android.resolv.x509.pem b/target/product/security/com.android.resolv.x509.pem
deleted file mode 100644
index 77650f0..0000000
--- a/target/product/security/com.android.resolv.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFzjCCA7agAwIBAgIJAJuYkMMWaDUCMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRswGQYDVQQD
-DBJjb20uYW5kcm9pZC5yZXNvbHYwIBcNMTkwMTI1MTcxODEwWhgPNDc1NjEyMjEx
-NzE4MTBaMHsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYD
-VQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdB
-bmRyb2lkMRswGQYDVQQDDBJjb20uYW5kcm9pZC5yZXNvbHYwggIiMA0GCSqGSIb3
-DQEBAQUAA4ICDwAwggIKAoICAQDHKz23/+Ji2wjvzYMMjvIm8jE6ghgqDrUfadQz
-UkfN0FnkDkBMQE3Qh41SYFxd7wn4q22HKn3OtO/TR8f9X15+HF9vCN6LMtHWRO+w
-wHNOuCYRLqNyKx3XlYOyokiF0NLMkUrmHyflqZQ6xwJIcYj6J13cp11sAc61snRR
-wwczxDiSiIExeKIC6LtEzbAxp09a3BgRVQrlQllr1MPBmXjQxkJ9nAglM3HFq7oQ
-xYGafwabjkpvC8x7hHEmi7XEOssHaT66C1adwFNc3trGK+1ZNOHmkmM+fRO1hffF
-wQ5yhbAt1zKaqj7TXYdJ2NaJYfCZSnJ8bH9Q5u28wBMoUYUh1b4zwWPUyszJ61h2
-nb8oZp8P1tZzD4R9LsQ7iW31D6i3wVAazhLnbXnH0BREWamKvkbA3/PTCSC+/AMc
-4wh/aN/SU/TzCvvI6i6CG5un38OSvsNLTBmLj4Y8ECD7nxUwfeMKKSba37Twh/YG
-PlslsbVBZK0iHtG+hCJuyy7ttGpGydE93m8Rqm1CJnm+/HaKa8UKCHd5GqiDhKtT
-EvdfLJwQPsf49IVrNWQp+1Q15WNVhSA9nLiMYVQYtBVbTYtYghXbRcSD2IjUdfA4
-lIcubkPxWD+jthBFZhlyGoJ9OapNrbRf0isHCsTUMnCy02MQNnMTaLGfseBFAFqj
-+95SJQIDAQABo1MwUTAdBgNVHQ4EFgQUny0NZgR8PJCPSYJ6BQ721hhB2DkwHwYD
-VR0jBBgwFoAUny0NZgR8PJCPSYJ6BQ721hhB2DkwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQsFAAOCAgEAWabMCkP4kcG7DwAwpyGCehh5rg0FTSkRRKTY4S0P
-gSEmgPUNV1uqFUECGGr1HeOf6PUYCdAQ6K2tnhnknBLqfcQX+h652D+0Md/KldJt
-7HwC16S0MEfR35w/VgUfxe2oO0OYDJdkUXeEjou2+VrAYT6pe9TRB5+F5KQetgZa
-3H9KW7RVc1oeK3kZtSNA5zDsJNcvgdfWoSJkewlHZ8KNLQBaZoDYV/mfF8d06ydE
-L7SnTkHrJZF9MZ0V58y06sIX9XwlKhypY8sZi3bq+H0t5mzsVAaBHVOC8NHCy351
-XLArkCFdDMb50FaxN8F9eY6A997n08msfeMlMjBrem8r14tf5UEjYyykuLfhW19R
-W+Kli67PZ2VR1I7reEjab2hKt6nwBfw9/Pnb2lugIh48GG5kQ6sgROyAu14q/rnL
-Mof+athhTSD+ttU3YyBOq6hA7Vbft9xAnFqr50bBRbbO21OBJuN8PTWQm82FwXKB
-hNwMy7HSggJqZSJt8HiA2rmoZ79/gNIic6GddoYnASQqjxaCv6vhg8/FQ+r/FJ+x
-gy89yQ6WFLau4/YjVjTyBqGeUPorRuysK7XPH6vDZZKJawwNV3jaYzG8BQAIBqqp
-dNEx97jin7bJQ6ObGF5pmvjzo1XYAiKuj/sjzCC2EN2BjjimTVlsoB+Gv/CFUTbr
-8vw=
------END CERTIFICATE-----
diff --git a/target/product/security/com.android.runtime.debug.pk8 b/target/product/security/com.android.runtime.debug.pk8
deleted file mode 100644
index 5eec5d8..0000000
--- a/target/product/security/com.android.runtime.debug.pk8
+++ /dev/null
Binary files differ
diff --git a/target/product/security/com.android.runtime.debug.x509.pem b/target/product/security/com.android.runtime.debug.x509.pem
deleted file mode 100644
index 73402f5..0000000
--- a/target/product/security/com.android.runtime.debug.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF0DCCA7igAwIBAgIJALbaJLNNAiRDMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRwwGgYDVQQD
-DBNjb20uYW5kcm9pZC5ydW50aW1lMCAXDTE5MDEyNTE3MTQ1NloYDzQ3NTYxMjIx
-MTcxNDU2WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
-A1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwH
-QW5kcm9pZDEcMBoGA1UEAwwTY29tLmFuZHJvaWQucnVudGltZTCCAiIwDQYJKoZI
-hvcNAQEBBQADggIPADCCAgoCggIBAN1Ns75c0ZdLKnUvEuEotzJ0xyOLzOHYP3y6
-RzcwFyPf84aADc7rQDtjbmEuf9g9QpJhZAxe7G2Jg/wxqaxMW6wCfkpuElW5CAcj
-XQ0i12hRVtqePs5Z5bjzJ/8C7luWh82Vb/s2YoRPoKNXVWFT16CB4RMnw2nW5Uyo
-RHZ98N4MgFSGilafIc6Z0DImreTTwlEvcyKihVUSuzeyPG8CRjshw0C1Hqxt4a8J
-rxAgfPpd84Xo4etYePpVr2K5+vNAVwLpUdD48Y7q9peOJ0tbL8DSohudkzvZsQUo
-CfEfrVBfZv7aPnt6ZJYhcFo1WRBMYczKP4jWb0KgmF963ee3zliU1pXtIYsNBNth
-Mdvy3ml301tI7CKE5A3Yevm40VVqo+IDt7FNxoV3rKPhnO9vi/YqzX/1xMvAto8E
-9A5NvMTqHmS2P0wt1pt9KSuXXjoIAWaHZOATDkVI+jLjDrYFNdhqXVgbAaVtI60j
-lRaSWxzBr4o+g2W8ks/JgM2mwJ6qaTNoDMzg823MKzy/t3935sxm5GhFs9AY9Qz/
-4B3exqYUEFJLN6dJLCVppCmFCdCONSxN7bXPo+3b9LlZuKAOP17N04+eKcwXVeYz
-Z3a7SfyMzq+DtLhAn/TSliSbbCAVUxiOZnVX1nM0Gs3/BYCs0TUh2tSqO48pwDrx
-Pw7z9+m5AgMBAAGjUzBRMB0GA1UdDgQWBBRT9s/tu4uqtrglUFjQbwY5p+17DjAf
-BgNVHSMEGDAWgBRT9s/tu4uqtrglUFjQbwY5p+17DjAPBgNVHRMBAf8EBTADAQH/
-MA0GCSqGSIb3DQEBCwUAA4ICAQBNY5giwZCM0sE93Dj2zEe8qCRwIaV4bvSe744X
-Y1+405vdrNEHKPUfFn1xLSnhiGU3loZrP15lexmWvxycLNEy0UxZgq3eR7HuW6xp
-GIm9ttYDZEP+pL9hwew3jiR38NRRR1Ur1MsBNkZnCELC1W8RFWIi77Fsb4fj2mGn
-2R+2voBvVS5kjkytW079CEIsZN9RVYfERiKPCfJDa87kk0xduqyh7sDegQl0B2Ot
-R9KnD1dJZjbii2GRkhpJ/Ig17CQH3J8PY/SIt9L+QAchnIEF051sjbBRUJuPK9gL
-eBEkZkwD1JLqGO6fxkcjNx7MIevTnIBjX2Epr8luyRy7eR3TdBT3aRQcCUqBCi3i
-WxAVR5sOZ90INTXftFbztoklitpQ9mxKXgFr+xggL6u3BdJk1Nt9BsYmRzh5Bg+6
-1eMDBumy3JEA7whE8p75X9cSnKTNrDQU3DA5XzpIhmI91XJArBhBfxgqGxaTf0uq
-SfZRDfnaO456ZsZdKUy62mry6Vg/hvzX52x/HxDlSQWbpYp5t03hshaWxtNE376q
-GdqOoGRRWCvyWi/UOYzabp6czTjwV1JH9IU379CsqIO5UNJ2MM2re4TDXofefU1C
-6eiYihy28xDfIiCdretLRlvFYFF/5X5xby/XWsDA9sGlL5OOiXC6o0Pl9vbek2+T
-Ibx3Nw==
------END CERTIFICATE-----
diff --git a/target/product/security/com.android.runtime.release.pk8 b/target/product/security/com.android.runtime.release.pk8
deleted file mode 100644
index c63efb8..0000000
--- a/target/product/security/com.android.runtime.release.pk8
+++ /dev/null
Binary files differ
diff --git a/target/product/security/com.android.runtime.release.x509.pem b/target/product/security/com.android.runtime.release.x509.pem
deleted file mode 100644
index 4a7607a..0000000
--- a/target/product/security/com.android.runtime.release.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF0DCCA7igAwIBAgIJAMtsu/wrkZurMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRwwGgYDVQQD
-DBNjb20uYW5kcm9pZC5ydW50aW1lMCAXDTE5MDEyNTE3MTU0MFoYDzQ3NTYxMjIx
-MTcxNTQwWjB8MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
-A1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwH
-QW5kcm9pZDEcMBoGA1UEAwwTY29tLmFuZHJvaWQucnVudGltZTCCAiIwDQYJKoZI
-hvcNAQEBBQADggIPADCCAgoCggIBAL+aGSc+HU69vV1VbZb6WjXMDrE2Jo+JjXLU
-yVS3o8qlQeqN0RFbsbwnihnwg2xBnM6JiskAcuocz87dDuEt1zUEInC3Hpt/C2eg
-GUZepbq8po+v+b04YlX3aTaYTFqMjU0aQkjOqhnmVxg+KHpvudlvKB3VhH3D61al
-RReQzgM/Q6aUxcr4Z8XwvzV3i0K5NjiSuSt14K2yIaheh2OTbbwtvm3d+0sQDco6
-1gl0l4rM4e+GjxgWVqx8mfKhd4HTS3YIBDWXR6DFPBARzVBIpZu2QK4U6Jdsy2wI
-xg8+d5KWAoNQb7IQK6LQy7Fbw3PNJDo4Ph39G2wNgeMemz8uSQ9FZujc0AgxBom6
-J+ad7zlJBhYFC4UIKBYrRfJCHTN3GLuLvhu0p0jNMfdQXF6Tv/iG9g8JdZ0QjeWm
-/K+h1p6LUAIUV0UP7j8nIdp0j6NqMywkoeRDYlVQV/XdI7BiQe9Z8yNbF5Y3CxWT
-hMfN9iby11ImPilzpgv39ORVjDQdxxcwhJg2Xuu1752cBxcHu3ZcR8AiB7PCksXu
-EpUrjjOH8eVxoG1JJ/na5elUg/H35Or+JYYd8I8Ad1/GRkPrnIBAGzuyntOsNs4t
-2CEnhmV6EkEH8KP8miTdaa5NdPIwFRIHVBHcrqsqdmrINvoJhaVRH7YwmFjv48ak
-N4OyW3oLAgMBAAGjUzBRMB0GA1UdDgQWBBRqVJ0tsEOyqhKiZOrOfRD1+jQFMDAf
-BgNVHSMEGDAWgBRqVJ0tsEOyqhKiZOrOfRD1+jQFMDAPBgNVHRMBAf8EBTADAQH/
-MA0GCSqGSIb3DQEBCwUAA4ICAQAs+I1tRWRPmhA+FqcRdlAcY2Vy7NO12hjWXCT9
-hqenGk1/VnhH8aZT5lXZNaWeKonT5W7XydyrjiF09ndZBGew0rEZh6sMXH+G/drT
-9JxvfHsCQGrmX32V1XgAoRjV1VpUYIb2747fFWHHbl5frowNj955pkfseeKilSnF
-orUl5uGNxr6iNaVEUDfXBWkHwipYVyejAqdHkCQDhLtDBWsiskKpLWmmNKuy2QXQ
-uoyUyfeSR1Y+pT83qgmGb1LFLiOqL9ZKPrsIP+tG4lYB8L4SrYJf4MgfoJaKQ8ed
-2jsd42MegvOB2vdMyLgkf7EM/9DpE4BLpAy2mNd1AccL9YQ+0ezruxh6sYklJWGe
-2bHEbZk0duoNPsA87ZNKfFVV2cNVwSg/22HHjGieMUyPIwyGIzsHId8XiwXpZhLX
-VyacOVRd0SjTWK5Pxj6g21NrrcMXvFeCbveucf2ljKVxBVSbQKt67YlXxd9nLZjN
-zHnJWzDwlWXbyvxheLVVGEo0cqRbhxYMxXd9dM01EXJmIWqS8t0+aw90KKPFITNv
-qpxXnF5JJm1CzeBDtpmfepDupUR1bWansOd0sUuiDF/H1UcDiuBUC643RET1vjhv
-MllsShSeC6KGm3WwE0bhcvA9IdZC8CA3Btzw2J9aJO1gbVZ6vRkH+21cfR07so4N
-yXgprQ==
------END CERTIFICATE-----
diff --git a/target/product/security/com.android.tzdata.pk8 b/target/product/security/com.android.tzdata.pk8
deleted file mode 100644
index f786710..0000000
--- a/target/product/security/com.android.tzdata.pk8
+++ /dev/null
Binary files differ
diff --git a/target/product/security/com.android.tzdata.x509.pem b/target/product/security/com.android.tzdata.x509.pem
deleted file mode 100644
index bf78bee..0000000
--- a/target/product/security/com.android.tzdata.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFzjCCA7agAwIBAgIJAIyjs8l5WRp5MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
-aWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRswGQYDVQQD
-DBJjb20uYW5kcm9pZC50emRhdGEwIBcNMTkwMTI1MTY0ODE0WhgPNDc1NjEyMjEx
-NjQ4MTRaMHsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYD
-VQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdB
-bmRyb2lkMRswGQYDVQQDDBJjb20uYW5kcm9pZC50emRhdGEwggIiMA0GCSqGSIb3
-DQEBAQUAA4ICDwAwggIKAoICAQC3PzY5waM71QpWUVQPfTrtCf9Mx9097DjM6RlD
-jaOd2FtN7gUN/d+z19h0WRkBcBMDWH3z4aHIDp4YXABIdqIzXehhdCFLro4W6H4I
-TNcbH6/M4rmtGs2v0zCkrr8z/mEasCdsw9iz8LOiyouGxgt0Q2qPSQ3OcbZSGX0C
-T8VNxDIP1RpQdRUKhZt/hsmcuPHGq64yil/i7FHX4dLgjnik4sUkHPsQTam/H/J/
-brl9OToTCyRuTgaq6EfxCZVXPfxQE6KTDchFr4wYSbxIgSN9zk2wPLXCsyvSb2lV
-fDSbkRmS89cCaCArF3SP3FAKoZdxdNtT1Q/KayMs7c/jrhFloiIpkstNCzMrPT9i
-j5QwRqcBscSijqaEJOyK458EhaO7m3GHc9e+1afsxTIn//vbrpJU7ewOiwcAsJAT
-KGFMotbK1fV4jGCzKxDVBd1OP5yN/iPYS8INH4tt1W1Q5jaQn/Uy+RuS1tPZTtrL
-ldj/QJ/K9XNSg4v12hXlLDwUlwEMu2Akbe6BYItfhdAEITRr332l6e466cQDp3V2
-mOWANPEX35s5/CaxeqJOi3Y+DSx4iwjOKiormnnEalRFAZrSDU2UNxIqrmidl03Y
-/0p13ugbPmJbpXFPZFDPsUuvPuGLSAU2luUuFSgT0FVyWj5BfzFmcuLxQom03+ds
-cX8GxQIDAQABo1MwUTAdBgNVHQ4EFgQUVCZf+AGkP1wMi7C0l6FFefk9kVAwHwYD
-VR0jBBgwFoAUVCZf+AGkP1wMi7C0l6FFefk9kVAwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQsFAAOCAgEAc0NA+Ya/L5Vs+8CZ/5rP6dIbzbgL7tm1nmjU65jY
-8znsSrB0JDTEHCLc+9u35YU77Z3sW9lFE9el1i693gYQnYSy1lducHHKzbnss2/f
-+DJ4QExrPR+PfnkSxdjL8+MXVAtVZDCeEBTcUgLES6m4WLS9hKL4+Oe+igXkAJA+
-d8w1/5ASuood3cTNy3nxssdueAKl4Tyj0y0zejoVlznaYw4zMTmlnrz1l0ZbaKiM
-tr52U2kASEVQW6EhiielsLMzDngqAQ49FQriv7oUhrlbmP3+CkhhPWbM3keSHm/a
-vIQGD3+mbJpekuRgC5w1nCborCxpnHoZUXMyb6/3PnY9u4O8VT5rY5NipVfL/Cvu
-12w0kvcuXTP58gvOJANB5t8Jo4tctG99hO0ECr7/439YM4NMkL5nYEcJe3DemquB
-pB7xVBAD7WKEcB5KV/oDXoLjxMlassKSAvBVbx+fvbGIW6k1pe3uiHl8p/zvxoNb
-9FFRoElCyuzzVP5r/kN5uNbPVIexbVET4elOcUhKigHWZHYv/PQ9ncpA8tbDeAIr
-vzoofKWv4r4tyQZLR4YnEYTGBORO6rX//Mcg8zKE6vXb0zKLW5vW1zxv31q1p2lC
-0R5e4ix7UjR8OJcBCnyKuqSRdCIpMitam2V+BXwh/7mLZBA4LuV4koNofVaBFxlt
-BCo=
------END CERTIFICATE-----
diff --git a/target/product/security/networkstack.pk8 b/target/product/security/networkstack.pk8
new file mode 100644
index 0000000..877f516
--- /dev/null
+++ b/target/product/security/networkstack.pk8
Binary files differ
diff --git a/target/product/security/networkstack.x509.pem b/target/product/security/networkstack.x509.pem
new file mode 100644
index 0000000..c49b95a
--- /dev/null
+++ b/target/product/security/networkstack.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF3DCCA8SgAwIBAgIJAPxssNim/dFoMA0GCSqGSIb3DQEBCwUAMIGBMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEhMB8GA1UE
+AwwYY29tLmFuZHJvaWQubmV0d29ya3N0YWNrMCAXDTE5MDIxMjAxNDYyMFoYDzQ3
+NTcwMTA4MDE0NjIwWjCBgTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju
+aWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAO
+BgNVBAsMB0FuZHJvaWQxITAfBgNVBAMMGGNvbS5hbmRyb2lkLm5ldHdvcmtzdGFj
+azCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALtx9RN/8LLXV6zCyj03
+jg+N4RCQ1crz1J4xTTXCg7d4sC15LY66RANkypcJhUQWYPC8AK+8Y91hGxv1GtKK
+Ht0h4ASPVIuA+L0RPiVoKCL1fauCc6+vEsZNGaDGviOPPmbdx5sQ/ZJpMePuYKe/
+YYZE2jwsT8QoE51F0nvtp/5F4wB1tJPq1uwBzdVdkxwKZX4uWXQspjK23DhCot63
+0iRDyAkpHXpUkgOuauNWWCpMoj8w8FScTshAinUnjpXGnoOQrVKAvO+u9vEwmkG9
+nzv7XRLcp+eexv1oSBk/qatygiSIe0+T6YXsfL9kAbDoY6S5HAXQRvBA/pVABLFk
+WVT8tBFM7h6LZLR9cZoZ70wAHLGD9/PhZuQ/VtaAR8NEDaNP31KdRCdLiy9q+zRQ
+ka2K1Lk71cVdUihqXTwVdGXbjd9i5822sQ+xiIgEav3SY65vISXZBldZx+QvhhCm
+dG7b3FR9QwFhLu7Dw8vRJN7OzI04sg5zsT8k7nyhOpjF9h8MgbB9K1GXSbwry54J
+Sa72wRij6BJearV/zka7CRpmdA4Qsxx0C4kZAMDs2pzGnstPM2mZixdRBt0KT/1w
+JOt+df7dGlsTHQuytAxjSR48+GuJV7IVIbOpbtE3alGmrGl4ZrAlbe4bzZq5oYi/
+TO2AtZpfJMLamlXrew5QIRbjAgMBAAGjUzBRMB0GA1UdDgQWBBSTg8ks+/CZ1cR7
+DDZX2GIqCEty4TAfBgNVHSMEGDAWgBSTg8ks+/CZ1cR7DDZX2GIqCEty4TAPBgNV
+HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBqBQE4L94qa49wxgzRuO5P
+eIcYwoixcCWO86liMLZQBWUNakxCpZqXst3sUCQT57Q4+9BgNj10t0ojI4Kn93/T
+2jTjj3n60DWotHLFz/NlgYoBGNh/oeMcx+1L79J2KHYMKQmAw8w7f/DP0Bt1/x/M
+g+mBtbJaVNhbaKgEJKwmAV+zpMdUlppxF0wLwoP2yIGR3O1gniRfWTj/0K15kZji
+0L9jQiIcGwpdMy7S//xmiYLKu8t9O2MP+EduXISsCtN635IkA1IAA5+V7B+pW/g3
+lsDomGE1zuLcrvGQskmFWn5zl9SgvxfqY9l4WJxrSBGKOB//vXkMRNgCM+LjUpKj
+tVM8o/LMFz+Fz5BK3+Lk4hg9weug664HuDmoH/G8kuKSVQlXyFma8h6cBJe5I0zj
+RfP1CLHMhyqlXdtedzxcfdZXe5qLba7SCuH/S4IG/Z9cj1oiuhmAvvAa5vyyZZuX
+rVuYX6gcAZ/+AI3dnIEwwG/GAyshScIgn8Q4p+jDsgzgNlCtMcTuSPFpd3oK4YK3
+LKMbgVQPYfFn2Net9Pa7IzD/XCQDckUADYFywSq11apYkLixLbDw5yliZOtm5/lx
+TDEARkn7S4ZABfnEPIDbP23lL9RNbiA2v+f1gHFW7Vq1kdBv1ruTukM06ic5r4tB
+7SaGRU5gtmbRBzi7e6iAAQ==
+-----END CERTIFICATE-----
diff --git a/target/product/telephony_product.mk b/target/product/telephony_product.mk
index 70d4828..a4c7e31 100644
--- a/target/product/telephony_product.mk
+++ b/target/product/telephony_product.mk
@@ -21,3 +21,4 @@
 PRODUCT_PACKAGES += \
     CarrierConfig \
     Dialer \
+    EmergencyInfo \
diff --git a/target/product/telephony_system.mk b/target/product/telephony_system.mk
index fd79472..584cf1e 100644
--- a/target/product/telephony_system.mk
+++ b/target/product/telephony_system.mk
@@ -22,6 +22,5 @@
     CarrierDefaultApp \
     CallLogBackup \
     CellBroadcastReceiver \
-    EmergencyInfo \
 
 PRODUCT_COPY_FILES := \
diff --git a/target/product/treble_common.mk b/target/product/treble_common.mk
deleted file mode 100644
index 7e4a98e..0000000
--- a/target/product/treble_common.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# treble_system.prop.
-
-# Generic system image inherits from AOSP with telephony
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony.mk)
-
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
-
-# Split selinux policy
-PRODUCT_FULL_TREBLE_OVERRIDE := true
-
-# The Messaging app:
-#   Needed for android.telecom.cts.ExtendedInCallServiceTest#testOnCannedTextResponsesLoaded
-PRODUCT_PACKAGES += \
-    messaging
-
-# Telephony:
-#   Provide a default APN configuration
-PRODUCT_COPY_FILES += \
-    device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml
-
-# NFC:
-#   Provide default libnfc-nci.conf file for devices that does not have one in
-#   vendor/etc
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
-
-# GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
-
-# Support for the O-MR1 devices
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/init.legacy-gsi.rc:system/etc/init/init.legacy-gsi.rc \
-    build/make/target/product/gsi/init.vndk-27.rc:system/etc/init/gsi/init.vndk-27.rc
-
-# Name space configuration file for non-enforcing VNDK
-PRODUCT_PACKAGES += \
-    ld.config.vndk_lite.txt
-
-# Support addtional O-MR1 and P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 27 28
diff --git a/target/product/treble_common_64.mk b/target/product/treble_common_64.mk
deleted file mode 100644
index fc3c16f..0000000
--- a/target/product/treble_common_64.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# treble_system.prop.
-
-include build/make/target/product/treble_common.mk
-
-# For now this will allow 64-bit apps, but still compile all apps with JNI
-# for 32-bit only.
-
-# Copy different zygote settings for vendor.img to select by setting property
-# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
-#   1. 64-bit primary, 32-bit secondary OR
-#   2. 32-bit primary, 64-bit secondary
-#   3. 64-bit only is currently forbidden (b/64280459#comment6)
-PRODUCT_COPY_FILES += \
-    system/core/rootdir/init.zygote64_32.rc:root/init.zygote64_32.rc \
-    system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
-
-TARGET_SUPPORTS_32_BIT_APPS := true
-TARGET_SUPPORTS_64_BIT_APPS := true
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index 7286f95..24ac663 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -28,10 +28,6 @@
 if [ -n "$AB_OTA_UPDATER" ] ; then
   echo "ro.build.ab_update=$AB_OTA_UPDATER"
 fi
-echo "ro.product.model=$PRODUCT_MODEL"
-echo "ro.product.brand=$PRODUCT_BRAND"
-echo "ro.product.name=$PRODUCT_NAME"
-echo "ro.product.device=$TARGET_DEVICE"
 
 # These values are deprecated, use "ro.product.cpu.abilist"
 # instead (see below).
@@ -45,7 +41,6 @@
 echo "ro.product.cpu.abilist32=$TARGET_CPU_ABI_LIST_32_BIT"
 echo "ro.product.cpu.abilist64=$TARGET_CPU_ABI_LIST_64_BIT"
 
-echo "ro.product.manufacturer=$PRODUCT_MANUFACTURER"
 if [ -n "$PRODUCT_DEFAULT_LOCALE" ] ; then
   echo "ro.product.locale=$PRODUCT_DEFAULT_LOCALE"
 fi
@@ -54,9 +49,8 @@
 echo "# ro.build.product is obsolete; use ro.product.device"
 echo "ro.build.product=$TARGET_DEVICE"
 
-echo "# Do not try to parse description, fingerprint, or thumbprint"
+echo "# Do not try to parse description or thumbprint"
 echo "ro.build.description=$PRIVATE_BUILD_DESC"
-echo "ro.build.fingerprint=$BUILD_FINGERPRINT"
 if [ -n "$BUILD_THUMBPRINT" ] ; then
   echo "ro.build.thumbprint=$BUILD_THUMBPRINT"
 fi
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/checkowners.py b/tools/checkowners.py
index 7f03968..d6853d8 100755
--- a/tools/checkowners.py
+++ b/tools/checkowners.py
@@ -52,12 +52,13 @@
   noparent = 'set +noparent'
   email = '([^@ ]+@[^ @]+|\\*)'
   emails = '(%s( *, *%s)*)' % (email, email)
-  directive = '(%s|%s)' % (emails, noparent)
+  file_directive = 'file: *([^ :]+ *: *)?[^ ]+'
+  directive = '(%s|%s|%s)' % (emails, noparent, file_directive)
   glob = '[a-zA-Z0-9_\\.\\-\\*\\?]+'
   globs = '(%s( *, *%s)*)' % (glob, glob)
   perfile = 'per-file +' + globs + ' *= *' + directive
   include = 'include +([^ :]+ *: *)?[^ ]+'
-  pats = '(|%s|%s|%s|%s)$' % (noparent, email, perfile, include)
+  pats = '(|%s|%s|%s|%s|%s)$' % (noparent, email, perfile, include, file_directive)
   patterns = re.compile(pats)
   address_pattern = re.compile('([^@ ]+@[^ @]+)')
   perfile_pattern = re.compile('per-file +.*=(.*)')
diff --git a/tools/extract_kernel.py b/tools/extract_kernel.py
new file mode 100755
index 0000000..16ccb22
--- /dev/null
+++ b/tools/extract_kernel.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+A tool to extract kernel information from a kernel image.
+"""
+
+import argparse
+import subprocess
+import sys
+import re
+
+CONFIG_PREFIX = b'IKCFG_ST'
+GZIP_HEADER = b'\037\213\010'
+COMPRESSION_ALGO = (
+    (["gzip", "-d"], GZIP_HEADER),
+    (["xz", "-d"], b'\3757zXZ\000'),
+    (["bzip2", "-d"], b'BZh'),
+    (["lz4", "-d", "-l"], b'\002\041\114\030'),
+
+    # These are not supported in the build system yet.
+    # (["unlzma"], b'\135\0\0\0'),
+    # (["lzop", "-d"], b'\211\114\132'),
+)
+
+# "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+# LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+LINUX_BANNER_PREFIX = b'Linux version '
+LINUX_BANNER_REGEX = LINUX_BANNER_PREFIX + \
+    r'([0-9]+[.][0-9]+[.][0-9]+).* \(.*@.*\) \(.*\) .*\n'
+
+
+def get_version(input_bytes, start_idx):
+  null_idx = input_bytes.find('\x00', start_idx)
+  if null_idx < 0:
+    return None
+  linux_banner = input_bytes[start_idx:null_idx].decode()
+  mo = re.match(LINUX_BANNER_REGEX, linux_banner)
+  if mo:
+    return mo.group(1)
+  return None
+
+
+def dump_version(input_bytes):
+  idx = 0
+  while True:
+    idx = input_bytes.find(LINUX_BANNER_PREFIX, idx)
+    if idx < 0:
+      return None
+
+    version = get_version(input_bytes, idx)
+    if version:
+      return version
+
+    idx += len(LINUX_BANNER_PREFIX)
+
+
+def dump_configs(input_bytes):
+  """
+  Dump kernel configuration from input_bytes. This can be done when
+  CONFIG_IKCONFIG is enabled, which is a requirement on Treble devices.
+
+  The kernel configuration is archived in GZip format right after the magic
+  string 'IKCFG_ST' in the built kernel.
+  """
+
+  # Search for magic string + GZip header
+  idx = input_bytes.find(CONFIG_PREFIX + GZIP_HEADER)
+  if idx < 0:
+    return None
+
+  # Seek to the start of the archive
+  idx += len(CONFIG_PREFIX)
+
+  sp = subprocess.Popen(["gzip", "-d", "-c"], stdin=subprocess.PIPE,
+                        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  o, _ = sp.communicate(input=input_bytes[idx:])
+  if sp.returncode == 1: # error
+    return None
+
+  # success or trailing garbage warning
+  assert sp.returncode in (0, 2), sp.returncode
+
+  return o
+
+
+def try_decompress(cmd, search_bytes, input_bytes):
+  idx = input_bytes.find(search_bytes)
+  if idx < 0:
+    return None
+
+  idx = 0
+  sp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                        stderr=subprocess.PIPE)
+  o, _ = sp.communicate(input=input_bytes[idx:])
+  # ignore errors
+  return o
+
+
+def decompress_dump(func, input_bytes):
+  """
+  Run func(input_bytes) first; and if that fails (returns value evaluates to
+  False), then try different decompression algorithm before running func.
+  """
+  o = func(input_bytes)
+  if o:
+    return o
+  for cmd, search_bytes in COMPRESSION_ALGO:
+    decompressed = try_decompress(cmd, search_bytes, input_bytes)
+    if decompressed:
+      o = func(decompressed)
+      if o:
+        return o
+    # Force decompress the whole file even if header doesn't match
+    decompressed = try_decompress(cmd, b"", input_bytes)
+    if decompressed:
+      o = func(decompressed)
+      if o:
+        return o
+
+def main():
+  parser = argparse.ArgumentParser(
+      formatter_class=argparse.RawTextHelpFormatter,
+      description=__doc__ +
+      "\nThese algorithms are tried when decompressing the image:\n    " +
+      " ".join(tup[0][0] for tup in COMPRESSION_ALGO))
+  parser.add_argument('--input',
+                      help='Input kernel image. If not specified, use stdin',
+                      metavar='FILE',
+                      type=argparse.FileType('rb'),
+                      default=sys.stdin)
+  parser.add_argument('--output-configs',
+                      help='If specified, write configs. Use stdout if no file '
+                           'is specified.',
+                      metavar='FILE',
+                      nargs='?',
+                      type=argparse.FileType('wb'),
+                      const=sys.stdout)
+  parser.add_argument('--output-version',
+                      help='If specified, write version. Use stdout if no file '
+                           'is specified.',
+                      metavar='FILE',
+                      nargs='?',
+                      type=argparse.FileType('wb'),
+                      const=sys.stdout)
+  parser.add_argument('--tools',
+                      help='Decompression tools to use. If not specified, PATH '
+                           'is searched.',
+                      metavar='ALGORITHM:EXECUTABLE',
+                      nargs='*')
+  args = parser.parse_args()
+
+  tools = {pair[0]: pair[1]
+           for pair in (token.split(':') for token in args.tools or [])}
+  for cmd, _ in COMPRESSION_ALGO:
+    if cmd[0] in tools:
+      cmd[0] = tools[cmd[0]]
+
+  input_bytes = args.input.read()
+
+  ret = 0
+  if args.output_configs is not None:
+    o = decompress_dump(dump_configs, input_bytes)
+    if o:
+      args.output_configs.write(o)
+    else:
+      sys.stderr.write(
+          "Cannot extract kernel configs in {}".format(args.input.name))
+      ret = 1
+  if args.output_version is not None:
+    o = decompress_dump(dump_version, input_bytes)
+    if o:
+      args.output_version.write(o)
+    else:
+      sys.stderr.write(
+          "Cannot extract kernel versions in {}".format(args.input.name))
+      ret = 1
+
+  return ret
+
+
+if __name__ == '__main__':
+  exit(main())
diff --git a/tools/fs_config/Android.bp b/tools/fs_config/Android.bp
index 797cfe2..19a4624 100644
--- a/tools/fs_config/Android.bp
+++ b/tools/fs_config/Android.bp
@@ -21,43 +21,3 @@
     ],
     cflags: ["-Werror"],
 }
-
-// -----------------------------------------------------------------------------
-// Unit tests.
-// -----------------------------------------------------------------------------
-
-test_c_flags = [
-    "-fstack-protector-all",
-    "-g",
-    "-Wall",
-    "-Wextra",
-    "-Werror",
-    "-fno-builtin",
-    "-DANDROID_FILESYSTEM_CONFIG=\"android_filesystem_config_test_data.h\"",
-]
-
-//#################################
-// test executable
-cc_test_host {
-    name: "fs_config_generate_test",
-    srcs: ["fs_config_generate.c"],
-    shared_libs: ["libcutils"],
-    cflags: test_c_flags,
-    relative_install_path: "fs_config-unit-tests",
-    no_named_install_directory: true,
-    gtest: false,
-
-}
-
-//#################################
-// gTest tool
-cc_test_host {
-    name: "fs_config-unit-tests",
-    cflags: test_c_flags + ["-DHOST"],
-    shared_libs: [
-        "liblog",
-        "libcutils",
-        "libbase",
-    ],
-    srcs: ["fs_config_test.cpp"],
-}
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index 5ade258..0e0b1da 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -14,96 +14,19 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# One can override the default android_filesystem_config.h file in one of two ways:
-#
-# 1. The old way:
-#   To Build the custom target binary for the host to generate the fs_config
-#   override files. The executable is hard coded to include the
-#   $(TARGET_ANDROID_FILESYSTEM_CONFIG_H) file if it exists.
-#   Expectations:
-#      device/<vendor>/<device>/android_filesystem_config.h
-#          fills in struct fs_path_config android_device_dirs[] and
-#                   struct fs_path_config android_device_files[]
-#      device/<vendor>/<device>/device.mk
-#          PRODUCT_PACKAGES += fs_config_dirs fs_config_files
-#   If not specified, check if default one to be found
-#
-# 2. The new way:
-#   set TARGET_FS_CONFIG_GEN to contain a list of intermediate format files
+# One can override the default android_filesystem_config.h file by using TARGET_FS_CONFIG_GEN.
+#   Set TARGET_FS_CONFIG_GEN to contain a list of intermediate format files
 #   for generating the android_filesystem_config.h file.
 #
 # More information can be found in the README
-ANDROID_FS_CONFIG_H := android_filesystem_config.h
 
-ifneq ($(TARGET_ANDROID_FILESYSTEM_CONFIG_H),)
-ifneq ($(TARGET_FS_CONFIG_GEN),)
-$(error Cannot set TARGET_ANDROID_FILESYSTEM_CONFIG_H and TARGET_FS_CONFIG_GEN simultaneously)
-endif
-
-# One and only one file can be specified.
-ifneq ($(words $(TARGET_ANDROID_FILESYSTEM_CONFIG_H)),1)
-$(error Multiple fs_config files specified, \
- see "$(TARGET_ANDROID_FILESYSTEM_CONFIG_H)".)
-endif
-
-ifeq ($(filter %/$(ANDROID_FS_CONFIG_H),$(TARGET_ANDROID_FILESYSTEM_CONFIG_H)),)
-$(error TARGET_ANDROID_FILESYSTEM_CONFIG_H file name must be $(ANDROID_FS_CONFIG_H), \
- see "$(notdir $(TARGET_ANDROID_FILESYSTEM_CONFIG_H))".)
-endif
-
-my_fs_config_h := $(TARGET_ANDROID_FILESYSTEM_CONFIG_H)
-else ifneq ($(wildcard $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H)),)
-
-ifneq ($(TARGET_FS_CONFIG_GEN),)
-$(error Cannot provide $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H) and set TARGET_FS_CONFIG_GEN simultaneously)
-endif
-my_fs_config_h := $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H)
-
-else
-my_fs_config_h := $(LOCAL_PATH)/default/$(ANDROID_FS_CONFIG_H)
+ifneq ($(wildcard $(TARGET_DEVICE_DIR)/android_filesystem_config.h),)
+$(error Using $(TARGET_DEVICE_DIR)/android_filesystem_config.h is deprecated, please use TARGET_FS_CONFIG_GEN instead)
 endif
 
 system_android_filesystem_config := system/core/include/private/android_filesystem_config.h
+system_capability_header := bionic/libc/kernel/uapi/linux/capability.h
 
-##################################
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := fs_config_generate.c
-LOCAL_MODULE := fs_config_generate_$(TARGET_DEVICE)
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SHARED_LIBRARIES := libcutils
-LOCAL_CFLAGS := -Werror -Wno-error=\#warnings
-
-ifneq ($(TARGET_FS_CONFIG_GEN),)
-# Generate the "generated_oem_aid.h" file
-oem := $(local-generated-sources-dir)/generated_oem_aid.h
-$(oem): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
-$(oem): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(oem): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
-$(oem): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/fs_config_generator.py oemaid --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
-$(oem): $(TARGET_FS_CONFIG_GEN) $(LOCAL_PATH)/fs_config_generator.py
-	$(transform-generated-source)
-
-# Generate the fs_config header
-gen := $(local-generated-sources-dir)/$(ANDROID_FS_CONFIG_H)
-$(gen): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
-$(gen): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(gen): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
-$(gen): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/fs_config_generator.py fsconfig --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
-$(gen): $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(LOCAL_PATH)/fs_config_generator.py
-	$(transform-generated-source)
-
-LOCAL_GENERATED_SOURCES := $(oem) $(gen)
-
-my_fs_config_h := $(gen)
-my_gen_oem_aid := $(oem)
-gen :=
-oem :=
-endif
-
-LOCAL_C_INCLUDES := $(dir $(my_fs_config_h)) $(dir $(my_gen_oem_aid))
-
-include $(BUILD_HOST_EXECUTABLE)
-fs_config_generate_bin := $(LOCAL_INSTALLED_MODULE)
 # List of supported vendor, oem, odm, product and product_services Partitions
 fs_config_generate_extra_partition_list := $(strip \
   $(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),vendor) \
@@ -166,12 +89,20 @@
 LOCAL_MODULE_CLASS := ETC
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
 include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
 $(LOCAL_BUILT_MODULE): PRIVATE_PARTITION_LIST := $(fs_config_generate_extra_partition_list)
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -D $(if $(PRIVATE_PARTITION_LIST), \
-	   -P '$(subst $(space),$(comma),$(addprefix -,$(PRIVATE_PARTITION_LIST)))') \
-	   -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition system \
+	   --all-partitions $(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST)) \
+	   --dirs \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
 # Generate the system/etc/fs_config_files binary file for the target
@@ -183,12 +114,20 @@
 LOCAL_MODULE_CLASS := ETC
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
 include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
 $(LOCAL_BUILT_MODULE): PRIVATE_PARTITION_LIST := $(fs_config_generate_extra_partition_list)
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -F $(if $(PRIVATE_PARTITION_LIST), \
-	   -P '$(subst $(space),$(comma),$(addprefix -,$(PRIVATE_PARTITION_LIST)))') \
-	   -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition system \
+	   --all-partitions $(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST)) \
+	   --files \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ifneq ($(filter vendor,$(fs_config_generate_extra_partition_list)),)
 ##################################
@@ -202,9 +141,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
 LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -D -P vendor -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition vendor \
+	   --dirs \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
 # Generate the vendor/etc/fs_config_files binary file for the target
@@ -217,9 +165,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
 LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -F -P vendor -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition vendor \
+	   --files \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 endif
 
@@ -235,9 +192,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
 LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -D -P oem -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition oem \
+	   --dirs \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
 # Generate the oem/etc/fs_config_files binary file for the target
@@ -250,9 +216,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
 LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -F -P oem -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition oem \
+	   --files \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 endif
 
@@ -268,9 +243,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
 LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -D -P odm -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition odm \
+	   --dirs \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
 # Generate the odm/etc/fs_config_files binary file for the target
@@ -283,9 +267,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
 LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -F -P odm -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition odm \
+	   --files \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 endif
 
@@ -301,9 +294,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -D -P product -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition product \
+	   --dirs \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
 # Generate the product/etc/fs_config_files binary file for the target
@@ -316,10 +318,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -F -P product -o $@
-
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition product \
+	   --files \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 endif
 
 ifneq ($(filter product_services,$(fs_config_generate_extra_partition_list)),)
@@ -334,9 +344,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -D -P product_services -o $@
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition product_services \
+	   --dirs \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
 # Generate the product_services/etc/fs_config_files binary file for the target
@@ -349,10 +368,18 @@
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header)
 	@mkdir -p $(dir $@)
-	$< -F -P product_services -o $@
-
+	$< fsconfig \
+	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
+	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
+	   --partition product_services \
+	   --files \
+	   --out_file $@ \
+	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 endif
 
 ##################################
@@ -362,8 +389,21 @@
 ifneq ($(TARGET_FS_CONFIG_GEN),)
 include $(CLEAR_VARS)
 LOCAL_MODULE := oemaids_headers
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(dir $(my_gen_oem_aid))
-LOCAL_EXPORT_C_INCLUDE_DEPS := $(my_gen_oem_aid)
+
+LOCAL_MODULE_CLASS := ETC
+
+# Generate the "generated_oem_aid.h" file
+oem := $(local-generated-sources-dir)/generated_oem_aid.h
+$(oem): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
+$(oem): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(oem): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
+$(oem): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/fs_config_generator.py oemaid --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
+$(oem): $(TARGET_FS_CONFIG_GEN) $(LOCAL_PATH)/fs_config_generator.py
+	$(transform-generated-source)
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(dir $(oem))
+LOCAL_EXPORT_C_INCLUDE_DEPS := $(oem)
+
 include $(BUILD_HEADER_LIBRARY)
 endif
 
@@ -379,15 +419,11 @@
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
-ifneq ($(TARGET_FS_CONFIG_GEN),)
 $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-else
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := /dev/null
-endif
 $(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
 $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config)
 	@mkdir -p $(dir $@)
-	$(hide) $< passwd --required-prefix=vendor_ --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
+	$(hide) $< passwd --required-prefix=vendor_ --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) > $@
 
 ##################################
 # Generate the vendor/etc/group text file for the target
@@ -401,20 +437,12 @@
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
-ifneq ($(TARGET_FS_CONFIG_GEN),)
 $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-else
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := /dev/null
-endif
 $(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
 $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config)
 	@mkdir -p $(dir $@)
-	$(hide) $< group --required-prefix=vendor_ --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
+	$(hide) $< group --required-prefix=vendor_ --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) > $@
 
 system_android_filesystem_config :=
-
-ANDROID_FS_CONFIG_H :=
-my_fs_config_h :=
-fs_config_generate_bin :=
-my_gen_oem_aid :=
+system_capability_header :=
 fs_config_generate_extra_partition_list :=
diff --git a/tools/fs_config/README b/tools/fs_config/README
index cc2a68f..f7d4deb 100644
--- a/tools/fs_config/README
+++ b/tools/fs_config/README
@@ -5,25 +5,9 @@
 
 Generating the android_filesystem_config.h:
 
-To generate the android_filesystem_config.h file, one can choose from
-one of two methods. The first method, is to declare
-TARGET_ANDROID_FILESYSTEM_CONFIG_H in the device BoardConfig.mk file. This
-variable can only have one item in it, and it is used directly as the
-android_filesystem_config.h header when building
-fs_config_generate_$(TARGET_DEVICE) which is used to generate fs_config_files
-and fs_config_dirs target executable.
-
-The limitation with this, is that it can only be set once, thus if the device
-has a make hierarchy, then each device needs its own file, and cannot share
-from a common source or that common source needs to include everything from
-both devices.
-
-The other way is to set TARGET_FS_CONFIG_GEN, which can be a list of
-intermediate fs configuration files. It is a build error on any one
-these conditions:
- * Specify TARGET_FS_CONFIG_GEN and TARGET_ANDROID_FILESYSTEM_CONFIG_H
- * Specify TARGET_FS_CONFIG_GEN and provide
-   $(TARGET_DEVICE_DIR)/android_filesystem_config.h
+To generate the android_filesystem_config.h file, one can set
+TARGET_FS_CONFIG_GEN, which can be a list of intermediate fs configuration
+files.
 
 The parsing of the config file follows the Python ConfigParser specification,
 with the sections and fields as defined below. There are two types of sections,
diff --git a/tools/fs_config/android_filesystem_config_test_data.h b/tools/fs_config/android_filesystem_config_test_data.h
deleted file mode 100644
index c65d406..0000000
--- a/tools/fs_config/android_filesystem_config_test_data.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <private/android_filesystem_config.h>
-
-/* Test Data */
-
-#undef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
-#undef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES
-
-static const struct fs_path_config android_device_dirs[] = {
-    {00555, AID_ROOT, AID_SYSTEM, 0, "system/etc"},
-    {00555, AID_ROOT, AID_SYSTEM, 0, "vendor/etc"},
-    {00555, AID_ROOT, AID_SYSTEM, 0, "oem/etc"},
-    {00555, AID_ROOT, AID_SYSTEM, 0, "odm/etc"},
-    {00555, AID_ROOT, AID_SYSTEM, 0, "product/etc"},
-    {00555, AID_ROOT, AID_SYSTEM, 0, "product_services/etc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "data/misc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "oem/data/misc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "odm/data/misc"},
-    {00755, AID_SYSTEM, AID_ROOT, 0, "vendor/data/misc"},
-    {00555, AID_SYSTEM, AID_ROOT, 0, "etc"},
-};
-
-static const struct fs_path_config android_device_files[] = {
-    {00444, AID_ROOT, AID_SYSTEM, 0, "system/etc/fs_config_dirs"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "vendor/etc/fs_config_dirs"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "oem/etc/fs_config_dirs"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "odm/etc/fs_config_dirs"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "product/etc/fs_config_dirs"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "product_services/etc/fs_config_dirs"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "system/etc/fs_config_files"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "vendor/etc/fs_config_files"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "oem/etc/fs_config_files"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "odm/etc/fs_config_files"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "product/etc/fs_config_files"},
-    {00444, AID_ROOT, AID_SYSTEM, 0, "product_services/etc/fs_config_files"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc/fs_config_dirs"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc/fs_config_dirs"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc/fs_config_files"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc/fs_config_files"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc/fs_config_files"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/product/etc/fs_config_files"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "system/product_services/etc/fs_config_files"},
-    {00644, AID_SYSTEM, AID_ROOT, 0, "etc/fs_config_files"},
-    {00666, AID_ROOT, AID_SYSTEM, 0, "data/misc/oem"},
-};
diff --git a/tools/fs_config/default/android_filesystem_config.h b/tools/fs_config/default/android_filesystem_config.h
deleted file mode 100644
index b7d936a..0000000
--- a/tools/fs_config/default/android_filesystem_config.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* This file is used to enhance the properties of the filesystem
-** images generated by build tools (mkbootfs and mkyaffs2image) and
-** by the device side of adb.
-*/
-
-/* Rules for directories.
-** These rules are applied based on "first match", so they
-** should start with the most specific path and work their
-** way up to the root.
-*/
-
-#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS 1 /* opt out of specifying */
-
-/* Rules for files.
-** These rules are applied based on "first match", so they
-** should start with the most specific path and work their
-** way up to the root. Prefixes ending in * denotes wildcard
-** and will allow partial matches.
-*/
-
-#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES 1 /* opt out of specifying */
diff --git a/tools/fs_config/end_to_end_test/config.fs b/tools/fs_config/end_to_end_test/config.fs
new file mode 100644
index 0000000..339e5ae
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/config.fs
@@ -0,0 +1,108 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file is used to define the properties of the filesystem
+# images generated by build tools (mkbootfs and mkyaffs2image) and
+# by the device side of adb.
+
+[AID_VENDOR_NEW_SERVICE]
+value: 2900
+
+[AID_VENDOR_NEW_SERVICE_TWO]
+value:2902
+
+[vendor/bin/service1]
+mode: 0755
+user: AID_SYSTEM
+group: AID_VENDOR_NEW_SERVICE
+caps: CHOWN DAC_OVERRIDE
+
+[vendor/bin/service2]
+mode: 0755
+user: AID_VENDOR_NEW_SERVICE_TWO
+group: AID_SYSTEM
+caps: AUDIT_READ CHOWN SYS_ADMIN
+
+[system/vendor/bin/service3]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: AUDIT_READ CHOWN SYS_ADMIN
+
+[vendor/dir/]
+mode: 0755
+user: AID_VENDOR_NEW_SERVICE_TWO
+group: AID_SYSTEM
+caps: 0
+
+[system/vendor/dir2/]
+mode: 0755
+user: AID_VENDOR_NEW_SERVICE_TWO
+group: AID_SYSTEM
+caps: 0
+
+[product/bin/service1]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: 0x34
+
+[product/bin/service2]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: NET_BIND_SERVICE WAKE_ALARM
+
+[system/product/bin/service3]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: NET_BIND_SERVICE WAKE_ALARM
+
+[product/dir/]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: 0
+
+[system/product/dir/]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: 0
+
+[system/bin/service]
+mode: 0755
+user: AID_SYSTEM
+group: AID_RADIO
+caps: NET_BIND_SERVICE
+
+[system/dir/]
+mode: 0755
+user: AID_SYSTEM
+group: AID_RADIO
+caps: 0
+
+[root_file]
+mode: 0755
+user: AID_SYSTEM
+group: AID_RADIO
+caps: 0
+
+[root_dir/]
+mode: 0755
+user: AID_SYSTEM
+group: AID_RADIO
+caps: 0
diff --git a/tools/fs_config/end_to_end_test/product_fs_config_dirs b/tools/fs_config/end_to_end_test/product_fs_config_dirs
new file mode 100644
index 0000000..e69ad65
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/product_fs_config_dirs
Binary files differ
diff --git a/tools/fs_config/end_to_end_test/product_fs_config_files b/tools/fs_config/end_to_end_test/product_fs_config_files
new file mode 100644
index 0000000..376a2a6
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/product_fs_config_files
Binary files differ
diff --git a/tools/fs_config/end_to_end_test/run_test.sh b/tools/fs_config/end_to_end_test/run_test.sh
new file mode 100755
index 0000000..7402276
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/run_test.sh
@@ -0,0 +1,76 @@
+cd $ANDROID_BUILD_TOP/build/make/tools/fs_config/end_to_end_test
+
+$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
+  --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+  --capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
+  --partition system \
+  --all-partitions vendor,product \
+  --files \
+  --out_file result_system_fs_config_files \
+  ./config.fs
+
+diff system_fs_config_files result_system_fs_config_files 1>/dev/null && echo 'Success system_fs_config_files' ||
+  echo 'Fail: Mismatch between system_fs_config_files and result_system_fs_config_files'
+
+$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
+  --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+  --capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
+  --partition system \
+  --all-partitions vendor,product \
+  --dirs \
+  --out_file result_system_fs_config_dirs \
+  ./config.fs
+
+diff system_fs_config_dirs result_system_fs_config_dirs 1>/dev/null && echo 'Success system_fs_config_dirs' ||
+  echo 'Fail: Mismatch between system_fs_config_dirs and result_system_fs_config_dirs'
+
+$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
+  --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+  --capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
+  --partition vendor \
+  --files \
+  --out_file result_vendor_fs_config_files \
+  ./config.fs
+
+diff vendor_fs_config_files result_vendor_fs_config_files 1>/dev/null && echo 'Success vendor_fs_config_files' ||
+  echo 'Fail: Mismatch between vendor_fs_config_files and result_vendor_fs_config_files'
+
+$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
+  --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+  --capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
+  --partition vendor \
+  --dirs \
+  --out_file result_vendor_fs_config_dirs \
+  ./config.fs
+
+diff vendor_fs_config_dirs result_vendor_fs_config_dirs 1>/dev/null && echo 'Success vendor_fs_config_dirs' ||
+  echo 'Fail: Mismatch between vendor_fs_config_dirs and result_vendor_fs_config_dirs'
+
+$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
+  --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+  --capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
+  --partition product \
+  --files \
+  --out_file result_product_fs_config_files \
+  ./config.fs
+
+diff product_fs_config_files result_product_fs_config_files 1>/dev/null && echo 'Success product_fs_config_files' ||
+  echo 'Fail: Mismatch between product_fs_config_files and result_product_fs_config_files'
+
+$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
+  --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+  --capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
+  --partition product \
+  --dirs \
+  --out_file result_product_fs_config_dirs \
+  ./config.fs
+
+diff product_fs_config_dirs result_product_fs_config_dirs 1>/dev/null && echo 'Success product_fs_config_dirs' ||
+  echo 'Fail: Mismatch between product_fs_config_dirs and result_product_fs_config_dirs'
+
+rm result_system_fs_config_files
+rm result_system_fs_config_dirs
+rm result_vendor_fs_config_files
+rm result_vendor_fs_config_dirs
+rm result_product_fs_config_files
+rm result_product_fs_config_dirs
diff --git a/tools/fs_config/end_to_end_test/system_fs_config_dirs b/tools/fs_config/end_to_end_test/system_fs_config_dirs
new file mode 100644
index 0000000..3a95e40
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/system_fs_config_dirs
Binary files differ
diff --git a/tools/fs_config/end_to_end_test/system_fs_config_files b/tools/fs_config/end_to_end_test/system_fs_config_files
new file mode 100644
index 0000000..578091c
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/system_fs_config_files
Binary files differ
diff --git a/tools/fs_config/end_to_end_test/vendor_fs_config_dirs b/tools/fs_config/end_to_end_test/vendor_fs_config_dirs
new file mode 100644
index 0000000..02dded7
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/vendor_fs_config_dirs
Binary files differ
diff --git a/tools/fs_config/end_to_end_test/vendor_fs_config_files b/tools/fs_config/end_to_end_test/vendor_fs_config_files
new file mode 100644
index 0000000..90bedc9
--- /dev/null
+++ b/tools/fs_config/end_to_end_test/vendor_fs_config_files
Binary files differ
diff --git a/tools/fs_config/fs_config_generate.c b/tools/fs_config/fs_config_generate.c
deleted file mode 100644
index dddd331..0000000
--- a/tools/fs_config/fs_config_generate.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <private/android_filesystem_config.h>
-
-/*
- * This program expects android_device_dirs and android_device_files
- * to be defined in the supplied android_filesystem_config.h file in
- * the device/<vendor>/<product> $(TARGET_DEVICE_DIR). Then generates
- * the binary format used in the /system/etc/fs_config_dirs and
- * the /system/etc/fs_config_files to be used by the runtimes.
- */
-#ifdef ANDROID_FILESYSTEM_CONFIG
-#include ANDROID_FILESYSTEM_CONFIG
-#else
-#include "android_filesystem_config.h"
-#endif
-
-#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
-static const struct fs_path_config android_device_dirs[] = { };
-#endif
-
-#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES
-static const struct fs_path_config android_device_files[] = { };
-#endif
-
-static void usage() {
-  fprintf(stderr,
-    "Generate binary content for fs_config_dirs (-D) and fs_config_files (-F)\n"
-    "from device-specific android_filesystem_config.h override.  Filter based\n"
-    "on a comma separated partition list (-P) whitelist or prefixed by a\n"
-    "minus blacklist.  Partitions are identified as path references to\n"
-    "<partition>/ or system/<partition>/\n\n"
-    "Usage: fs_config_generate -D|-F [-P list] [-o output-file]\n");
-}
-
-/* If tool switches to C++, use android-base/macros.h array_size() */
-#ifndef ARRAY_SIZE /* popular macro */
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#endif
-
-int main(int argc, char** argv) {
-  const struct fs_path_config* pc;
-  const struct fs_path_config* end;
-  bool dir = false, file = false;
-  const char* partitions = NULL;
-  FILE* fp = stdout;
-  int opt;
-  static const char optstring[] = "DFP:ho:";
-
-  while ((opt = getopt(argc, argv, optstring)) != -1) {
-    switch (opt) {
-    case 'D':
-      if (file) {
-        fprintf(stderr, "Must specify only -D or -F\n");
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      dir = true;
-      break;
-    case 'F':
-      if (dir) {
-        fprintf(stderr, "Must specify only -F or -D\n");
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      file = true;
-      break;
-    case 'P':
-      if (partitions) {
-        fprintf(stderr, "Specify only one partition list\n");
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      while (*optarg && isspace(*optarg)) ++optarg;
-      if (!optarg[0]) {
-        fprintf(stderr, "Partition list empty\n");
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      if (!optarg[1]) {
-        fprintf(stderr, "Partition list too short \"%s\"\n", optarg);
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      if ((optarg[0] == '-') && strchr(optstring, optarg[1]) && !optarg[2]) {
-        fprintf(stderr, "Partition list is a flag \"%s\"\n", optarg);
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      partitions = optarg;
-      break;
-    case 'o':
-      if (fp != stdout) {
-        fprintf(stderr, "Specify only one output file\n");
-        usage();
-        exit(EXIT_FAILURE);
-      }
-      fp = fopen(optarg, "wb");
-      if (fp == NULL) {
-        fprintf(stderr, "Can not open \"%s\"\n", optarg);
-        exit(EXIT_FAILURE);
-      }
-      break;
-    case 'h':
-      usage();
-      exit(EXIT_SUCCESS);
-    default:
-      usage();
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  if (optind < argc) {
-    fprintf(stderr, "Unknown non-argument \"%s\"\n", argv[optind]);
-    usage();
-    exit(EXIT_FAILURE);
-  }
-
-  if (!file && !dir) {
-    fprintf(stderr, "Must specify either -F or -D\n");
-    usage();
-    exit(EXIT_FAILURE);
-  }
-
-  if (dir) {
-    pc = android_device_dirs;
-    end = &android_device_dirs[ARRAY_SIZE(android_device_dirs)];
-  } else {
-    pc = android_device_files;
-    end = &android_device_files[ARRAY_SIZE(android_device_files)];
-  }
-  for (; (pc < end) && pc->prefix; pc++) {
-    bool submit;
-    char buffer[512];
-    ssize_t len = fs_config_generate(buffer, sizeof(buffer), pc);
-    if (len < 0) {
-      fprintf(stderr, "Entry too large\n");
-      exit(EXIT_FAILURE);
-    }
-    submit = true;
-    if (partitions) {
-      char* partitions_copy = strdup(partitions);
-      char* arg = partitions_copy;
-      char* sv = NULL; /* Do not leave uninitialized, NULL is known safe. */
-      /* Deal with case all iterated partitions are blacklists with no match */
-      bool all_blacklist_but_no_match = true;
-      submit = false;
-
-      if (!partitions_copy) {
-        fprintf(stderr, "Failed to allocate a copy of %s\n", partitions);
-        exit(EXIT_FAILURE);
-      }
-      /* iterate through (officially) comma separated list of partitions */
-      while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
-        static const char system[] = "system/";
-        size_t plen;
-        bool blacklist = false;
-        if (*arg == '-') {
-          blacklist = true;
-          ++arg;
-        } else {
-          all_blacklist_but_no_match = false;
-        }
-        plen = strlen(arg);
-        /* deal with evil callers */
-        while (arg[plen - 1] == '/') {
-          --plen;
-        }
-        /* check if we have <partition>/ or /system/<partition>/ */
-        if ((!strncmp(pc->prefix, arg, plen) && (pc->prefix[plen] == '/')) ||
-            (!strncmp(pc->prefix, system, strlen(system)) &&
-             !strncmp(pc->prefix + strlen(system), arg, plen) &&
-             (pc->prefix[strlen(system) + plen] == '/'))) {
-          all_blacklist_but_no_match = false;
-          /* we have a match !!! */
-          if (!blacklist) submit = true;
-          break;
-        }
-        arg = NULL;
-      }
-      free(partitions_copy);
-      if (all_blacklist_but_no_match) submit = true;
-    }
-    if (submit && (fwrite(buffer, 1, len, fp) != (size_t)len)) {
-      fprintf(stderr, "Write failure\n");
-      exit(EXIT_FAILURE);
-    }
-  }
-  fclose(fp);
-
-  return 0;
-}
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
index 0a8def8..dccff92 100755
--- a/tools/fs_config/fs_config_generator.py
+++ b/tools/fs_config/fs_config_generator.py
@@ -12,6 +12,7 @@
 
 import argparse
 import ConfigParser
+import ctypes
 import re
 import sys
 import textwrap
@@ -112,7 +113,8 @@
                 'Cannot specify delimiter character ":" in uid: "%s"' % uid)
         if ':' in logon:
             raise ValueError(
-                'Cannot specify delimiter character ":" in logon: "%s"' % logon)
+                'Cannot specify delimiter character ":" in logon: "%s"' %
+                logon)
         return logon, uid
 
 
@@ -158,16 +160,17 @@
 
         try:
             self.normalized_value = str(int(value, 0))
-        except ValueException:
-            raise ValueError('Invalid "value", not aid number, got: \"%s\"' % value)
+        except ValueError:
+            raise ValueError(
+                'Invalid "value", not aid number, got: \"%s\"' % value)
 
         # Where we calculate the friendly name
         friendly = identifier[len(AID.PREFIX):].lower()
         self.friendly = AID._fixup_friendly(friendly)
 
         if len(self.friendly) > 31:
-            raise ValueError('AID names must be under 32 characters "%s"' % self.friendly)
-
+            raise ValueError(
+                'AID names must be under 32 characters "%s"' % self.friendly)
 
     def __eq__(self, other):
 
@@ -217,6 +220,7 @@
         user (str): The uid or #define identifier (AID_SYSTEM)
         group (str): The gid or #define identifier (AID_SYSTEM)
         caps (str): The capability set.
+        path (str): The path of the file or directory.
         filename (str): The file it was found in.
     """
 
@@ -227,6 +231,7 @@
             user (str): The uid or #define identifier (AID_SYSTEM)
             group (str): The gid or #define identifier (AID_SYSTEM)
             caps (str): The capability set as a list.
+            path (str): The path of the file or directory.
             filename (str): The file it was found in.
         """
         self.mode = mode
@@ -242,6 +247,51 @@
             and self.group == other.group and self.caps == other.caps \
             and self.path == other.path and self.filename == other.filename
 
+    def __repr__(self):
+        return 'FSConfig(%r, %r, %r, %r, %r, %r)' % (self.mode, self.user,
+                                                     self.group, self.caps,
+                                                     self.path, self.filename)
+
+
+class CapabilityHeaderParser(object):
+    """Parses capability.h file
+
+    Parses a C header file and extracts lines starting with #define CAP_<name>.
+    """
+
+    _CAP_DEFINE = re.compile(r'\s*#define\s+(CAP_\S+)\s+(\S+)')
+    _SKIP_CAPS = ['CAP_LAST_CAP', 'CAP_TO_INDEX(x)', 'CAP_TO_MASK(x)']
+
+    def __init__(self, capability_header):
+        """
+        Args:
+            capability_header (str): file name for the header file containing AID entries.
+        """
+
+        self.caps = {}
+        with open(capability_header) as open_file:
+            self._parse(open_file)
+
+    def _parse(self, capability_file):
+        """Parses a capability header file. Internal use only.
+
+        Args:
+            capability_file (file): The open capability header file to parse.
+        """
+
+        for line in capability_file:
+            match = CapabilityHeaderParser._CAP_DEFINE.match(line)
+            if match:
+                cap = match.group(1)
+                value = match.group(2)
+
+                if not cap in self._SKIP_CAPS:
+                    try:
+                        self.caps[cap] = int(value, 0)
+                    except ValueError:
+                        sys.exit('Could not parse capability define "%s":"%s"'
+                                 % (cap, value))
+
 
 class AIDHeaderParser(object):
     """Parses an android_filesystem_config.h file.
@@ -256,10 +306,10 @@
     work.
     """
 
-
     _SKIP_AIDS = [
         re.compile(r'%sUNUSED[0-9].*' % AID.PREFIX),
-        re.compile(r'%sAPP' % AID.PREFIX), re.compile(r'%sUSER' % AID.PREFIX)
+        re.compile(r'%sAPP' % AID.PREFIX),
+        re.compile(r'%sUSER' % AID.PREFIX)
     ]
     _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % AID.PREFIX)
     _OEM_START_KW = 'START'
@@ -310,7 +360,9 @@
                 identifier = chunks[1]
                 value = chunks[2]
 
-                if any(x.match(identifier) for x in AIDHeaderParser._SKIP_AIDS):
+                if any(
+                        x.match(identifier)
+                        for x in AIDHeaderParser._SKIP_AIDS):
                     continue
 
                 try:
@@ -322,8 +374,8 @@
                         self._handle_aid(identifier, value)
                 except ValueError as exception:
                     sys.exit(
-                        error_message('{} for "{}"'.format(exception,
-                                                           identifier)))
+                        error_message('{} for "{}"'.format(
+                            exception, identifier)))
 
     def _handle_aid(self, identifier, value):
         """Handle an AID C #define.
@@ -346,8 +398,8 @@
             raise ValueError('Duplicate aid "%s"' % identifier)
 
         if value in self._aid_value_to_name and aid.identifier not in AIDHeaderParser._COLLISION_OK:
-            raise ValueError('Duplicate aid value "%s" for %s' % (value,
-                                                                  identifier))
+            raise ValueError(
+                'Duplicate aid value "%s" for %s' % (value, identifier))
 
         self._aid_name_to_value[aid.friendly] = aid
         self._aid_value_to_name[value] = aid.friendly
@@ -400,11 +452,11 @@
             if tmp == int_value:
                 raise ValueError('START and END values equal %u' % int_value)
             elif is_start and tmp < int_value:
-                raise ValueError('END value %u less than START value %u' %
-                                 (tmp, int_value))
+                raise ValueError(
+                    'END value %u less than START value %u' % (tmp, int_value))
             elif not is_start and tmp > int_value:
-                raise ValueError('END value %u less than START value %u' %
-                                 (int_value, tmp))
+                raise ValueError(
+                    'END value %u less than START value %u' % (int_value, tmp))
 
         # Add START values to the head of the list and END values at the end.
         # Thus, the list is ordered with index 0 as START and index 1 as END.
@@ -533,7 +585,7 @@
 
     # list of handler to required options, used to identify the
     # parsing section
-    _SECTIONS = [('_handle_aid', ('value',)),
+    _SECTIONS = [('_handle_aid', ('value', )),
                  ('_handle_path', ('mode', 'user', 'group', 'caps'))]
 
     def __init__(self, config_files, oem_ranges):
@@ -596,8 +648,8 @@
                     break
 
             if not found:
-                sys.exit('Invalid section "%s" in file: "%s"' %
-                         (section, file_name))
+                sys.exit('Invalid section "%s" in file: "%s"' % (section,
+                                                                 file_name))
 
             # sort entries:
             # * specified path before prefix match
@@ -717,9 +769,9 @@
             try:
                 # test if string is int, if it is, use as is.
                 int(cap, 0)
-                tmp.append('(' + cap + ')')
+                tmp.append(cap)
             except ValueError:
-                tmp.append('CAP_MASK_LONG(CAP_' + cap.upper() + ')')
+                tmp.append('CAP_' + cap.upper())
 
         caps = tmp
 
@@ -734,7 +786,7 @@
         if len(mode) != 4:
             sys.exit('Mode must be 3 or 4 characters, got: "%s"' % mode)
 
-        caps_str = '|'.join(caps)
+        caps_str = ','.join(caps)
 
         entry = FSConfig(mode, user, group, caps_str, section_name, file_name)
         if section_name[-1] == '/':
@@ -892,41 +944,20 @@
     Output is  used in generating fs_config_files and fs_config_dirs.
     """
 
-    _GENERATED = textwrap.dedent("""\
-        /*
-         * THIS IS AN AUTOGENERATED FILE! DO NOT MODIFY
-         */
-        """)
-
-    _INCLUDES = [
-        '<private/android_filesystem_config.h>', '"generated_oem_aid.h"'
-    ]
-
-    _DEFINE_NO_DIRS = '#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS'
-    _DEFINE_NO_FILES = '#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES'
-
-    _DEFAULT_WARNING = (
-        '#warning No device-supplied android_filesystem_config.h,'
-        ' using empty default.')
-
-    _OPEN_FILE_STRUCT = (
-        'static const struct fs_path_config android_device_files[] = {')
-
-    _OPEN_DIR_STRUCT = (
-        'static const struct fs_path_config android_device_dirs[] = {')
-
-    _CLOSE_FILE_STRUCT = '};'
-
-    _GENERIC_DEFINE = "#define %s\t%s"
-
-    _FILE_COMMENT = '// Defined in file: \"%s\"'
-
     def __init__(self, *args, **kwargs):
         BaseGenerator.__init__(args, kwargs)
 
         self._oem_parser = None
         self._base_parser = None
         self._friendly_to_aid = None
+        self._id_to_aid = None
+        self._capability_parser = None
+
+        self._partition = None
+        self._all_partitions = None
+        self._out_file = None
+        self._generate_files = False
+        self._generate_dirs = False
 
     def add_opts(self, opt_group):
 
@@ -939,11 +970,56 @@
             help='An android_filesystem_config.h file'
             ' to parse AIDs and OEM Ranges from')
 
+        opt_group.add_argument(
+            '--capability-header',
+            required=True,
+            help='A capability.h file to parse capability defines from')
+
+        opt_group.add_argument(
+            '--partition',
+            required=True,
+            help='Partition to generate contents for')
+
+        opt_group.add_argument(
+            '--all-partitions',
+            help='Comma separated list of all possible partitions, used to'
+            ' ignore these partitions when generating the output for the system partition'
+        )
+
+        opt_group.add_argument(
+            '--files', action='store_true', help='Output fs_config_files')
+
+        opt_group.add_argument(
+            '--dirs', action='store_true', help='Output fs_config_dirs')
+
+        opt_group.add_argument('--out_file', required=True, help='Output file')
+
     def __call__(self, args):
 
+        self._capability_parser = CapabilityHeaderParser(
+            args['capability_header'])
         self._base_parser = AIDHeaderParser(args['aid_header'])
         self._oem_parser = FSConfigFileParser(args['fsconfig'],
                                               self._base_parser.oem_ranges)
+
+        self._partition = args['partition']
+        self._all_partitions = args['all_partitions']
+        if self._partition == 'system' and self._all_partitions is None:
+            sys.exit(
+                'All other partitions must be provided if generating output'
+                ' for the system partition')
+
+        self._out_file = args['out_file']
+
+        self._generate_files = args['files']
+        self._generate_dirs = args['dirs']
+
+        if self._generate_files and self._generate_dirs:
+            sys.exit('Only one of --files or --dirs can be provided')
+
+        if not self._generate_files and not self._generate_dirs:
+            sys.exit('One of --files or --dirs must be provided')
+
         base_aids = self._base_parser.aids
         oem_aids = self._oem_parser.aids
 
@@ -959,7 +1035,7 @@
 
         common = base_set & oem_set
 
-        if len(common) > 0:
+        if common:
             emsg = 'Following AID Collisions detected for: \n'
             for friendly in common:
                 base = base_friendly[friendly]
@@ -973,53 +1049,105 @@
         self._friendly_to_aid = oem_friendly
         self._friendly_to_aid.update(base_friendly)
 
+        self._id_to_aid = {aid.identifier: aid for aid in base_aids}
+        self._id_to_aid.update({aid.identifier: aid for aid in oem_aids})
+
         self._generate()
 
-    def _to_fs_entry(self, fs_config):
+    def _to_fs_entry(self, fs_config, out_file):
         """Converts an FSConfig entry to an fs entry.
 
-        Prints '{ mode, user, group, caps, "path" },'.
+        Writes the fs_config contents to the output file.
 
         Calls sys.exit() on error.
 
         Args:
-            fs_config (FSConfig): The entry to convert to
-                a valid C array entry.
+            fs_config (FSConfig): The entry to convert to write to file.
+            file (File): The file to write to.
         """
 
         # Get some short names
         mode = fs_config.mode
         user = fs_config.user
         group = fs_config.group
-        fname = fs_config.filename
         caps = fs_config.caps
         path = fs_config.path
 
-        emsg = 'Cannot convert friendly name "%s" to identifier!'
+        emsg = 'Cannot convert "%s" to identifier!'
 
-        # remap friendly names to identifier names
+        # convert mode from octal string to integer
+        mode = int(mode, 8)
+
+        # remap names to values
         if AID.is_friendly(user):
             if user not in self._friendly_to_aid:
                 sys.exit(emsg % user)
-            user = self._friendly_to_aid[user].identifier
+            user = self._friendly_to_aid[user].value
+        else:
+            if user not in self._id_to_aid:
+                sys.exit(emsg % user)
+            user = self._id_to_aid[user].value
 
         if AID.is_friendly(group):
             if group not in self._friendly_to_aid:
                 sys.exit(emsg % group)
-            group = self._friendly_to_aid[group].identifier
+            group = self._friendly_to_aid[group].value
+        else:
+            if group not in self._id_to_aid:
+                sys.exit(emsg % group)
+            group = self._id_to_aid[group].value
 
-        fmt = '{ %s, %s, %s, %s, "%s" },'
+        caps_dict = self._capability_parser.caps
 
-        expanded = fmt % (mode, user, group, caps, path)
+        caps_value = 0
 
-        print FSConfigGen._FILE_COMMENT % fname
-        print '    ' + expanded
+        try:
+            # test if caps is an int
+            caps_value = int(caps, 0)
+        except ValueError:
+            caps_split = caps.split(',')
+            for cap in caps_split:
+                if cap not in caps_dict:
+                    sys.exit('Unkonwn cap "%s" found!' % cap)
+                caps_value += 1 << caps_dict[cap]
 
-    @staticmethod
-    def _gen_inc():
-        """Generate the include header lines and print to stdout."""
-        for include in FSConfigGen._INCLUDES:
-            print '#include %s' % include
+        path_length_with_null = len(path) + 1
+        path_length_aligned_64 = (path_length_with_null + 7) & ~7
+        # 16 bytes of header plus the path length with alignment
+        length = 16 + path_length_aligned_64
+
+        length_binary = bytearray(ctypes.c_uint16(length))
+        mode_binary = bytearray(ctypes.c_uint16(mode))
+        user_binary = bytearray(ctypes.c_uint16(int(user, 0)))
+        group_binary = bytearray(ctypes.c_uint16(int(group, 0)))
+        caps_binary = bytearray(ctypes.c_uint64(caps_value))
+        path_binary = ctypes.create_string_buffer(path,
+                                                  path_length_aligned_64).raw
+
+        out_file.write(length_binary)
+        out_file.write(mode_binary)
+        out_file.write(user_binary)
+        out_file.write(group_binary)
+        out_file.write(caps_binary)
+        out_file.write(path_binary)
+
+    def _emit_entry(self, fs_config):
+        """Returns a boolean whether or not to emit the input fs_config"""
+
+        path = fs_config.path
+
+        if self._partition == 'system':
+            for skip_partition in self._all_partitions.split(','):
+                if path.startswith(skip_partition) or path.startswith(
+                        'system/' + skip_partition):
+                    return False
+            return True
+        else:
+            if path.startswith(
+                    self._partition) or path.startswith('system/' +
+                                                        self._partition):
+                return True
+            return False
 
     def _generate(self):
         """Generates an OEM android_filesystem_config.h header file to stdout.
@@ -1030,50 +1158,20 @@
                 entries.
             aids ([AIDS]): A list of AID objects for Android Id entries.
         """
-        print FSConfigGen._GENERATED
-        print
-
-        FSConfigGen._gen_inc()
-        print
-
         dirs = self._oem_parser.dirs
         files = self._oem_parser.files
-        aids = self._oem_parser.aids
 
-        are_dirs = len(dirs) > 0
-        are_files = len(files) > 0
-        are_aids = len(aids) > 0
+        if self._generate_files:
+            with open(self._out_file, 'wb') as open_file:
+                for fs_config in files:
+                    if self._emit_entry(fs_config):
+                        self._to_fs_entry(fs_config, open_file)
 
-        if are_aids:
-            for aid in aids:
-                # use the preserved _path value
-                print FSConfigGen._FILE_COMMENT % aid.found
-                print FSConfigGen._GENERIC_DEFINE % (aid.identifier, aid.value)
-
-            print
-
-        if not are_dirs:
-            print FSConfigGen._DEFINE_NO_DIRS + '\n'
-
-        if not are_files:
-            print FSConfigGen._DEFINE_NO_FILES + '\n'
-
-        if not are_files and not are_dirs and not are_aids:
-            return
-
-        if are_files:
-            print FSConfigGen._OPEN_FILE_STRUCT
-            for fs_config in files:
-                self._to_fs_entry(fs_config)
-
-            print FSConfigGen._CLOSE_FILE_STRUCT
-
-        if are_dirs:
-            print FSConfigGen._OPEN_DIR_STRUCT
-            for dir_entry in dirs:
-                self._to_fs_entry(dir_entry)
-
-            print FSConfigGen._CLOSE_FILE_STRUCT
+        if self._generate_dirs:
+            with open(self._out_file, 'wb') as open_file:
+                for dir_entry in dirs:
+                    if self._emit_entry(dir_entry):
+                        self._to_fs_entry(dir_entry, open_file)
 
 
 @generator('aidarray')
@@ -1234,11 +1332,12 @@
         aids = parser.aids
 
         # nothing to do if no aids defined
-        if len(aids) == 0:
+        if not aids:
             return
 
         for aid in aids:
-            if required_prefix is None or aid.friendly.startswith(required_prefix):
+            if required_prefix is None or aid.friendly.startswith(
+                    required_prefix):
                 self._print_formatted_line(aid)
             else:
                 sys.exit("%s: AID '%s' must start with '%s'" %
@@ -1294,6 +1393,7 @@
 
         print "%s::%s:" % (logon, uid)
 
+
 @generator('print')
 class PrintGen(BaseGenerator):
     """Prints just the constants and values, separated by spaces, in an easy to
diff --git a/tools/fs_config/fs_config_test.cpp b/tools/fs_config/fs_config_test.cpp
deleted file mode 100644
index 916c615..0000000
--- a/tools/fs_config/fs_config_test.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <sys/cdefs.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/macros.h>
-#include <android-base/strings.h>
-#include <gtest/gtest.h>
-#include <private/android_filesystem_config.h>
-#include <private/fs_config.h>
-
-#include "android_filesystem_config_test_data.h"
-
-// must run test in the test directory
-static const std::string fs_config_generate_command = "./fs_config_generate_test";
-
-static std::string popenToString(const std::string command) {
-  std::string ret;
-
-  auto fp = popen(command.c_str(), "r");
-  if (fp) {
-    if (!android::base::ReadFdToString(fileno(fp), &ret)) ret = "";
-    pclose(fp);
-  }
-  return ret;
-}
-
-static void confirm(std::string&& data, const fs_path_config* config,
-                    ssize_t num_config) {
-  auto pc = reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
-  auto len = data.size();
-
-  ASSERT_TRUE(config != NULL);
-  ASSERT_LT(0, num_config);
-
-  while (len > 0) {
-    auto host_len = pc->len;
-    if (host_len > len) break;
-
-    EXPECT_EQ(config->mode, pc->mode);
-    EXPECT_EQ(config->uid, pc->uid);
-    EXPECT_EQ(config->gid, pc->gid);
-    EXPECT_EQ(config->capabilities, pc->capabilities);
-    EXPECT_STREQ(config->prefix, pc->prefix);
-
-    EXPECT_LT(0, num_config);
-    --num_config;
-    if (num_config >= 0) ++config;
-    pc = reinterpret_cast<const fs_path_config_from_file*>(
-        reinterpret_cast<const char*>(pc) + host_len);
-    len -= host_len;
-  }
-  EXPECT_EQ(0, num_config);
-}
-
-/* See local android_filesystem_config.h for test data */
-
-TEST(fs_conf_test, dirs) {
-  confirm(popenToString(fs_config_generate_command + " -D"),
-          android_device_dirs, arraysize(android_device_dirs));
-}
-
-TEST(fs_conf_test, files) {
-  confirm(popenToString(fs_config_generate_command + " -F"),
-          android_device_files, arraysize(android_device_files));
-}
-
-static bool is_system(const char* prefix) {
-  return !android::base::StartsWith(prefix, "vendor/") &&
-         !android::base::StartsWith(prefix, "system/vendor/") &&
-         !android::base::StartsWith(prefix, "oem/") &&
-         !android::base::StartsWith(prefix, "system/oem/") &&
-         !android::base::StartsWith(prefix, "odm/") &&
-         !android::base::StartsWith(prefix, "system/odm/") &&
-         !android::base::StartsWith(prefix, "product/") &&
-         !android::base::StartsWith(prefix, "system/product/") &&
-         !android::base::StartsWith(prefix, "product_services/") &&
-         !android::base::StartsWith(prefix, "system/product_services/");
-}
-
-TEST(fs_conf_test, system_dirs) {
-  std::vector<fs_path_config> dirs;
-  auto config = android_device_dirs;
-  for (auto num = arraysize(android_device_dirs); num; --num) {
-    if (is_system(config->prefix)) {
-      dirs.emplace_back(*config);
-    }
-    ++config;
-  }
-  confirm(popenToString(fs_config_generate_command + " -D -P -vendor,-oem,-odm,-product,-product_services"),
-          &dirs[0], dirs.size());
-}
-
-static void fs_conf_test_dirs(const std::string& partition_name) {
-  std::vector<fs_path_config> dirs;
-  auto config = android_device_dirs;
-  const auto str = partition_name + "/";
-  const auto alt_str = "system/" + partition_name + "/";
-  for (auto num = arraysize(android_device_dirs); num; --num) {
-    if (android::base::StartsWith(config->prefix, str) ||
-        android::base::StartsWith(config->prefix, alt_str)) {
-      dirs.emplace_back(*config);
-    }
-    ++config;
-  }
-  confirm(popenToString(fs_config_generate_command + " -D -P " + partition_name),
-          &dirs[0], dirs.size());
-}
-
-TEST(fs_conf_test, vendor_dirs) {
-  fs_conf_test_dirs("vendor");
-}
-
-TEST(fs_conf_test, oem_dirs) {
-  fs_conf_test_dirs("oem");
-}
-
-TEST(fs_conf_test, odm_dirs) {
-  fs_conf_test_dirs("odm");
-}
-
-TEST(fs_conf_test, system_files) {
-  std::vector<fs_path_config> files;
-  auto config = android_device_files;
-  for (auto num = arraysize(android_device_files); num; --num) {
-    if (is_system(config->prefix)) {
-      files.emplace_back(*config);
-    }
-    ++config;
-  }
-  confirm(popenToString(fs_config_generate_command + " -F -P -vendor,-oem,-odm,-product,-product_services"),
-          &files[0], files.size());
-}
-
-static void fs_conf_test_files(const std::string& partition_name) {
-  std::vector<fs_path_config> files;
-  auto config = android_device_files;
-  const auto str = partition_name + "/";
-  const auto alt_str = "system/" + partition_name + "/";
-  for (auto num = arraysize(android_device_files); num; --num) {
-    if (android::base::StartsWith(config->prefix, str) ||
-        android::base::StartsWith(config->prefix, alt_str)) {
-      files.emplace_back(*config);
-    }
-    ++config;
-  }
-  confirm(popenToString(fs_config_generate_command + " -F -P " + partition_name),
-          &files[0], files.size());
-}
-
-TEST(fs_conf_test, vendor_files) {
-  fs_conf_test_files("vendor");
-}
-
-TEST(fs_conf_test, oem_files) {
-  fs_conf_test_files("oem");
-}
-
-TEST(fs_conf_test, odm_files) {
-  fs_conf_test_files("odm");
-}
-
-TEST(fs_conf_test, product_files) {
-  fs_conf_test_files("product");
-}
-
-TEST(fs_conf_test, product_services_files) {
-  fs_conf_test_files("product_services");
-}
diff --git a/tools/fs_config/test_fs_config_generator.py b/tools/fs_config/test_fs_config_generator.py
index a49058a..b7f173e 100755
--- a/tools/fs_config/test_fs_config_generator.py
+++ b/tools/fs_config/test_fs_config_generator.py
@@ -45,19 +45,21 @@
     def test_aid(self):
         """Test AID class constructor"""
 
-        aid = AID('AID_FOO_BAR', '0xFF', 'myfakefile')
-        self.assertEquals(aid.identifier, 'AID_FOO_BAR')
-        self.assertEquals(aid.value, '0xFF')
-        self.assertEquals(aid.found, 'myfakefile')
-        self.assertEquals(aid.normalized_value, '255')
-        self.assertEquals(aid.friendly, 'foo_bar')
+        aid = AID('AID_FOO_BAR', '0xFF', 'myfakefile', '/system/bin/sh')
+        self.assertEqual(aid.identifier, 'AID_FOO_BAR')
+        self.assertEqual(aid.value, '0xFF')
+        self.assertEqual(aid.found, 'myfakefile')
+        self.assertEqual(aid.normalized_value, '255')
+        self.assertEqual(aid.friendly, 'foo_bar')
+        self.assertEqual(aid.login_shell, '/system/bin/sh')
 
-        aid = AID('AID_MEDIA_EX', '1234', 'myfakefile')
-        self.assertEquals(aid.identifier, 'AID_MEDIA_EX')
-        self.assertEquals(aid.value, '1234')
-        self.assertEquals(aid.found, 'myfakefile')
-        self.assertEquals(aid.normalized_value, '1234')
-        self.assertEquals(aid.friendly, 'mediaex')
+        aid = AID('AID_MEDIA_EX', '1234', 'myfakefile', '/vendor/bin/sh')
+        self.assertEqual(aid.identifier, 'AID_MEDIA_EX')
+        self.assertEqual(aid.value, '1234')
+        self.assertEqual(aid.found, 'myfakefile')
+        self.assertEqual(aid.normalized_value, '1234')
+        self.assertEqual(aid.friendly, 'mediaex')
+        self.assertEqual(aid.login_shell, '/vendor/bin/sh')
 
     def test_aid_header_parser_good(self):
         """Test AID Header Parser good input file"""
@@ -265,9 +267,9 @@
             dirs = parser.dirs
             aids = parser.aids
 
-            self.assertEquals(len(files), 1)
-            self.assertEquals(len(dirs), 1)
-            self.assertEquals(len(aids), 1)
+            self.assertEqual(len(files), 1)
+            self.assertEqual(len(dirs), 1)
+            self.assertEqual(len(aids), 1)
 
             aid = aids[0]
             fcap = files[0]
@@ -275,14 +277,14 @@
 
             self.assertEqual(fcap,
                              FSConfig('0777', 'AID_FOO', 'AID_SYSTEM',
-                                      '(1ULL << CAP_BLOCK_SUSPEND)',
+                                      'CAP_BLOCK_SUSPEND',
                                       '/system/bin/file', temp_file.name))
 
             self.assertEqual(dcap,
-                             FSConfig('0777', 'AID_FOO', 'AID_SYSTEM', '(0)',
+                             FSConfig('0777', 'AID_FOO', 'AID_SYSTEM', '0',
                                       '/vendor/path/dir/', temp_file.name))
 
-            self.assertEqual(aid, AID('AID_OEM1', '0x1389', temp_file.name))
+            self.assertEqual(aid, AID('AID_OEM1', '0x1389', temp_file.name, '/vendor/bin/sh'))
 
     def test_fs_config_file_parser_bad(self):
         """Test FSConfig Parser bad input file"""
diff --git a/tools/generate-enforce-rro-android-manifest.py b/tools/generate-enforce-rro-android-manifest.py
index 68331cf..2d9382a 100755
--- a/tools/generate-enforce-rro-android-manifest.py
+++ b/tools/generate-enforce-rro-android-manifest.py
@@ -23,10 +23,10 @@
 import sys
 
 ANDROID_MANIFEST_TEMPLATE="""<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="%s.auto_generated_rro__"
+    package="%s.auto_generated_rro_%s__"
     android:versionCode="1"
     android:versionName="1.0">
-    <overlay android:targetPackage="%s" android:priority="0" android:isStatic="true"/>
+    <overlay android:targetPackage="%s" android:priority="%s" android:isStatic="true"/>
 </manifest>
 """
 
@@ -40,6 +40,12 @@
         '-p', '--package-info', required=True,
         help='Manifest package name or manifest file path of source module.')
     parser.add_argument(
+        '--partition', required=True,
+        help='The partition this RRO package is installed on.')
+    parser.add_argument(
+        '--priority', required=True,
+        help='The priority for the <overlay>.')
+    parser.add_argument(
         '-o', '--output', required=True,
         help='Output manifest file path.')
     return parser.parse_args()
@@ -48,8 +54,11 @@
 def main(argv):
   args = get_args()
 
-  package_name = args.package_info
-  if not args.use_package_name:
+  partition = args.partition
+  priority = args.priority
+  if args.use_package_name:
+    package_name = args.package_info
+  else:
     with open(args.package_info) as f:
       data = f.read()
       f.close()
@@ -57,7 +66,7 @@
       package_name = dom.documentElement.getAttribute('package')
 
   with open(args.output, 'w+') as f:
-    f.write(ANDROID_MANIFEST_TEMPLATE % (package_name, package_name))
+    f.write(ANDROID_MANIFEST_TEMPLATE % (package_name, partition, package_name, priority))
     f.close()
 
 
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index e75b3b7..10aecf9 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -119,9 +119,12 @@
 
   simg = sparse_img.SparseImage(imgname)
   care_map_ranges = simg.care_map
-  key = which + "_image_blocks"
-  image_blocks = OPTIONS.info_dict.get(key)
-  if image_blocks:
+  size_key = which + "_image_size"
+  image_size = OPTIONS.info_dict.get(size_key)
+  if image_size:
+    # excludes the verity metadata blocks of the given image. When AVB is enabled,
+    # this size is the max image size returned by the AVB tool
+    image_blocks = int(image_size) / 4096 - 1
     assert image_blocks > 0, "blocks for {} must be positive".format(which)
     care_map_ranges = care_map_ranges.intersect(
         rangelib.RangeSet("0-{}".format(image_blocks)))
@@ -143,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")
@@ -257,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,
@@ -319,9 +323,7 @@
   if block_list:
     block_list.Write()
 
-  # Set the '_image_blocks' that excludes the verity metadata blocks of the
-  # given image. When AVB is enabled, this size is the max image size returned
-  # by the AVB tool.
+  # Set the '_image_size' for given image size.
   is_verity_partition = "verity_block_device" in image_props
   verity_supported = (image_props.get("verity") == "true" or
                       image_props.get("avb_enable") == "true")
@@ -329,8 +331,8 @@
   if verity_supported and (is_verity_partition or is_avb_enable):
     image_size = image_props.get("image_size")
     if image_size:
-      image_blocks_key = what + "_image_blocks"
-      info_dict[image_blocks_key] = int(image_size) / 4096 - 1
+      image_size_key = what + "_image_size"
+      info_dict[image_size_key] = int(image_size)
 
   use_dynamic_size = (
       info_dict.get("use_dynamic_partition_size") == "true" and
@@ -427,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)
 
@@ -733,6 +735,7 @@
                           os.path.exists(os.path.join(OPTIONS.input_tmp,
                                                       "IMAGES",
                                                       "product_services.img")))
+  has_system = os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM"))
   has_system_other = os.path.isdir(os.path.join(OPTIONS.input_tmp,
                                                 "SYSTEM_OTHER"))
 
@@ -797,9 +800,10 @@
         if output_zip:
           recovery_two_step_image.AddToZip(output_zip)
 
-  banner("system")
-  partitions['system'] = AddSystem(
-      output_zip, recovery_img=recovery_image, boot_img=boot_image)
+  if has_system:
+    banner("system")
+    partitions['system'] = AddSystem(
+        output_zip, recovery_img=recovery_image, boot_img=boot_image)
 
   if has_vendor:
     banner("vendor")
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
new file mode 100644
index 0000000..d14c94f
--- /dev/null
+++ b/tools/releasetools/apex_utils.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import os.path
+import re
+import shlex
+import sys
+
+import common
+
+logger = logging.getLogger(__name__)
+
+
+class ApexInfoError(Exception):
+  """An Exception raised during Apex Information command."""
+
+  def __init__(self, message):
+    Exception.__init__(self, message)
+
+
+class ApexSigningError(Exception):
+  """An Exception raised during Apex Payload signing."""
+
+  def __init__(self, message):
+    Exception.__init__(self, message)
+
+
+def SignApexPayload(payload_file, payload_key_path, payload_key_name, algorithm,
+                    salt, signing_args=None):
+  """Signs a given payload_file with the payload key."""
+  # Add the new footer. Old footer, if any, will be replaced by avbtool.
+  cmd = ['avbtool', 'add_hashtree_footer',
+         '--do_not_generate_fec',
+         '--algorithm', algorithm,
+         '--key', payload_key_path,
+         '--prop', 'apex.key:{}'.format(payload_key_name),
+         '--image', payload_file,
+         '--salt', salt]
+  if signing_args:
+    cmd.extend(shlex.split(signing_args))
+
+  try:
+    common.RunAndCheckOutput(cmd)
+  except common.ExternalError as e:
+    raise ApexSigningError, \
+        'Failed to sign APEX payload {} with {}:\n{}'.format(
+            payload_file, payload_key_path, e), sys.exc_info()[2]
+
+  # Verify the signed payload image with specified public key.
+  logger.info('Verifying %s', payload_file)
+  VerifyApexPayload(payload_file, payload_key_path)
+
+
+def VerifyApexPayload(payload_file, payload_key):
+  """Verifies the APEX payload signature with the given key."""
+  cmd = ['avbtool', 'verify_image', '--image', payload_file,
+         '--key', payload_key]
+  try:
+    common.RunAndCheckOutput(cmd)
+  except common.ExternalError as e:
+    raise ApexSigningError, \
+        'Failed to validate payload signing for {} with {}:\n{}'.format(
+            payload_file, payload_key, e), sys.exc_info()[2]
+
+
+def ParseApexPayloadInfo(payload_path):
+  """Parses the APEX payload info.
+
+  Args:
+    payload_path: The path to the payload image.
+
+  Raises:
+    ApexInfoError on parsing errors.
+
+  Returns:
+    A dict that contains payload property-value pairs. The dict should at least
+    contain Algorithm, Salt and apex.key.
+  """
+  if not os.path.exists(payload_path):
+    raise ApexInfoError('Failed to find image: {}'.format(payload_path))
+
+  cmd = ['avbtool', 'info_image', '--image', payload_path]
+  try:
+    output = common.RunAndCheckOutput(cmd)
+  except common.ExternalError as e:
+    raise ApexInfoError, \
+        'Failed to get APEX payload info for {}:\n{}'.format(
+            payload_path, e), sys.exc_info()[2]
+
+  # Extract the Algorithm / Salt / Prop info from payload (i.e. an image signed
+  # with avbtool). For example,
+  # Algorithm:                SHA256_RSA4096
+  PAYLOAD_INFO_PATTERN = (
+      r'^\s*(?P<key>Algorithm|Salt|Prop)\:\s*(?P<value>.*?)$')
+  payload_info_matcher = re.compile(PAYLOAD_INFO_PATTERN)
+
+  payload_info = {}
+  for line in output.split('\n'):
+    line_info = payload_info_matcher.match(line)
+    if not line_info:
+      continue
+
+    key, value = line_info.group('key'), line_info.group('value')
+
+    if key == 'Prop':
+      # Further extract the property key-value pair, from a 'Prop:' line. For
+      # example,
+      #   Prop: apex.key -> 'com.android.runtime'
+      # Note that avbtool writes single or double quotes around values.
+      PROPERTY_DESCRIPTOR_PATTERN = r'^\s*(?P<key>.*?)\s->\s*(?P<value>.*?)$'
+
+      prop_matcher = re.compile(PROPERTY_DESCRIPTOR_PATTERN)
+      prop = prop_matcher.match(value)
+      if not prop:
+        raise ApexInfoError(
+            'Failed to parse prop string {}'.format(value))
+
+      prop_key, prop_value = prop.group('key'), prop.group('value')
+      if prop_key == 'apex.key':
+        # avbtool dumps the prop value with repr(), which contains single /
+        # double quotes that we don't want.
+        payload_info[prop_key] = prop_value.strip('\"\'')
+
+    else:
+      payload_info[key] = value
+
+  # Sanity check.
+  for key in ('Algorithm', 'Salt', 'apex.key'):
+    if key not in payload_info:
+      raise ApexInfoError(
+          'Failed to find {} prop in {}'.format(key, payload_path))
+
+  return payload_info
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index ba1d60e..d2f4e25 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -576,7 +576,7 @@
     copy_prop("avb_system_other_algorithm", "avb_algorithm")
     copy_prop("fs_type", "fs_type")
     copy_prop("system_fs_type", "fs_type")
-    copy_prop("system_size", "partition_size")
+    copy_prop("system_other_size", "partition_size")
     if not copy_prop("system_journal_size", "journal_size"):
       d["journal_size"] = "0"
     copy_prop("system_verity_block_device", "verity_block_device")
@@ -723,7 +723,7 @@
   if mount_point == "system":
     copy_prop("partition_size", "system_size")
   elif mount_point == "system_other":
-    copy_prop("partition_size", "system_size")
+    copy_prop("partition_size", "system_other_size")
   elif mount_point == "vendor":
     copy_prop("partition_size", "vendor_size")
   elif mount_point == "odm":
diff --git a/tools/releasetools/build_super_image.py b/tools/releasetools/build_super_image.py
index 5dc4cee..676acba 100755
--- a/tools/releasetools/build_super_image.py
+++ b/tools/releasetools/build_super_image.py
@@ -24,9 +24,8 @@
   - target files package. Same as above, but extracts the archive before
     building super image.
   - a dictionary file containing input arguments to build. Check
-    `dump_dynamic_partitions_info' for details.
+    `dump-super-image-info' for details.
     In addition:
-    - "ab_update" needs to be true for A/B devices.
     - If source images should be included in the output image (for super.img
       and super split images), a list of "*_image" should be paths of each
       source images.
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index b9f39a6..4b0d4c7 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -39,6 +39,7 @@
 
 """
 
+import logging
 import os
 import re
 import subprocess
@@ -52,6 +53,8 @@
   sys.exit(1)
 
 
+logger = logging.getLogger(__name__)
+
 # Work around a bug in Python's zipfile module that prevents opening of zipfiles
 # if any entry has an extra field of between 1 and 3 bytes (which is common with
 # zipaligned APKs). This overrides the ZipInfo._decodeExtra() method (which
@@ -165,6 +168,7 @@
 
 
 class APK(object):
+
   def __init__(self, full_filename, filename):
     self.filename = filename
     self.certs = None
@@ -241,12 +245,12 @@
     # must decompress them individually before we perform any analysis.
 
     # This is the list of wildcards of files we extract from |filename|.
-    apk_extensions = ['*.apk']
+    apk_extensions = ['*.apk', '*.apex']
 
     self.certmap, compressed_extension = common.ReadApkCerts(
-        zipfile.ZipFile(filename, "r"))
+        zipfile.ZipFile(filename))
     if compressed_extension:
-      apk_extensions.append("*.apk" + compressed_extension)
+      apk_extensions.append('*.apk' + compressed_extension)
 
     d = common.UnzipTemp(filename, apk_extensions)
     self.apks = {}
@@ -269,7 +273,7 @@
           os.remove(os.path.join(dirpath, fn))
           fn = uncompressed_fn
 
-        if fn.endswith(".apk"):
+        if fn.endswith(('.apk', '.apex')):
           fullname = os.path.join(dirpath, fn)
           displayname = fullname[len(d)+1:]
           apk = APK(fullname, displayname)
@@ -415,6 +419,8 @@
     common.Usage(__doc__)
     sys.exit(1)
 
+  common.InitLogging()
+
   ALL_CERTS.FindLocalCerts()
 
   Push("input target_files:")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 5d310d2..632c1e2 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
@@ -46,9 +47,16 @@
 
 class Options(object):
   def __init__(self):
+    base_out_path = os.getenv('OUT_DIR_COMMON_BASE')
+    if base_out_path is None:
+      base_search_path = "out"
+    else:
+      base_search_path = os.path.join(base_out_path,
+                                      os.path.basename(os.getcwd()))
+
     platform_search_path = {
-        "linux2": "out/host/linux-x86",
-        "darwin": "out/host/darwin-x86",
+        "linux2": os.path.join(base_search_path, "host/linux-x86"),
+        "darwin": os.path.join(base_search_path, "host/darwin-x86"),
     }
 
     self.search_path = platform_search_path.get(sys.platform)
@@ -190,6 +198,29 @@
   return subprocess.Popen(args, **kwargs)
 
 
+def RunAndWait(args, verbose=None, **kwargs):
+  """Runs the given command waiting for it to complete.
+
+  Args:
+    args: The command represented as a list of strings.
+    verbose: Whether the commands should be shown. Default to the global
+        verbosity if unspecified.
+    kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
+        stdin, etc. stdout and stderr will default to subprocess.PIPE and
+        subprocess.STDOUT respectively unless caller specifies any of them.
+
+  Raises:
+    ExternalError: On non-zero exit from the command.
+  """
+  proc = Run(args, verbose=verbose, **kwargs)
+  proc.wait()
+
+  if proc.returncode != 0:
+    raise ExternalError(
+        "Failed to run command '{}' (exit code {})".format(
+            args, proc.returncode))
+
+
 def RunAndCheckOutput(args, verbose=None, **kwargs):
   """Runs the given command and returns the output.
 
@@ -523,11 +554,7 @@
   """
   if key is None:
     key = info_dict["avb_" + partition + "_key_path"]
-  avbtool = os.getenv('AVBTOOL') or info_dict["avb_avbtool"]
-  pubkey_path = MakeTempFile(prefix="avb-", suffix=".pubkey")
-  RunAndCheckOutput(
-      [avbtool, "extract_public_key", "--key", key, "--output", pubkey_path])
-
+  pubkey_path = ExtractAvbPublicKey(key)
   rollback_index_location = info_dict[
       "avb_" + partition + "_rollback_index_location"]
   return "{}:{}:{}".format(partition, rollback_index_location, pubkey_path)
@@ -678,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",
@@ -745,30 +772,54 @@
     shutil.copyfileobj(in_file, out_file)
 
 
+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.
+    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 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)
+
+
 def UnzipTemp(filename, pattern=None):
   """Unzips the given archive into a temporary directory and returns the name.
 
-  If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a temp dir,
-  then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
+  Args:
+    filename: If filename is of the form "foo.zip+bar.zip", unzip foo.zip into
+    a temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
+
+    pattern: Files to unzip from the archive. If omitted, will unzip the entire
+    archvie.
 
   Returns:
     The name of the temporary directory.
   """
 
-  def unzip_to_dir(filename, dirname):
-    cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
-    if pattern is not None:
-      cmd.extend(pattern)
-    RunAndCheckOutput(cmd)
-
   tmp = MakeTempDir(prefix="targetfiles-")
   m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)
   if m:
-    unzip_to_dir(m.group(1), tmp)
-    unzip_to_dir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"))
+    UnzipToDir(m.group(1), tmp, pattern)
+    UnzipToDir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"), pattern)
     filename = m.group(1)
   else:
-    unzip_to_dir(filename, tmp)
+    UnzipToDir(filename, tmp, pattern)
 
   return tmp
 
@@ -957,7 +1008,8 @@
 
 
 def SignFile(input_name, output_name, key, password, min_api_level=None,
-             codename_to_api_level_map=None, whole_file=False):
+             codename_to_api_level_map=None, whole_file=False,
+             extra_signapk_args=None):
   """Sign the input_name zip/jar/apk, producing output_name.  Use the
   given key and password (the latter may be None if the key does not
   have a password.
@@ -972,9 +1024,14 @@
 
   codename_to_api_level_map is needed to translate the codename which may be
   encountered as the APK's minSdkVersion.
+
+  Caller may optionally specify extra args to be passed to SignApk, which
+  defaults to OPTIONS.extra_signapk_args if omitted.
   """
   if codename_to_api_level_map is None:
     codename_to_api_level_map = {}
+  if extra_signapk_args is None:
+    extra_signapk_args = OPTIONS.extra_signapk_args
 
   java_library_path = os.path.join(
       OPTIONS.search_path, OPTIONS.signapk_shared_library_path)
@@ -982,7 +1039,7 @@
   cmd = ([OPTIONS.java_path] + OPTIONS.java_args +
          ["-Djava.library.path=" + java_library_path,
           "-jar", os.path.join(OPTIONS.search_path, OPTIONS.signapk_path)] +
-         OPTIONS.extra_signapk_args)
+         extra_signapk_args)
   if whole_file:
     cmd.append("-w")
 
@@ -2078,6 +2135,21 @@
   return pubkey
 
 
+def ExtractAvbPublicKey(key):
+  """Extracts the AVB public key from the given public or private key.
+
+  Args:
+    key: The input key file, which should be PEM-encoded public or private key.
+
+  Returns:
+    The path to the extracted AVB public key file.
+  """
+  output = MakeTempFile(prefix='avb-', suffix='.avbpubkey')
+  RunAndCheckOutput(
+      ['avbtool', 'extract_public_key', "--key", key, "--output", output])
+  return output
+
+
 def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
                       info_dict=None):
   """Generates the recovery-from-boot patch and writes the script to output.
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
new file mode 100755
index 0000000..3b72551
--- /dev/null
+++ b/tools/releasetools/merge_target_files.py
@@ -0,0 +1,814 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+"""
+This script merges two partial target files packages (one of which contains
+system files, and the other contains non-system files) together, producing a
+complete target files package that can be used to generate an OTA package.
+
+Usage: merge_target_files.py [args]
+
+  --system-target-files system-target-files-zip-archive
+      The input target files package containing system bits. This is a zip
+      archive.
+
+  --system-item-list system-item-list-file
+      The optional path to a newline-separated config file that replaces the
+      contents of default_system_item_list if provided.
+
+  --system-misc-info-keys system-misc-info-keys-file
+      The optional path to a newline-separated config file that replaces the
+      contents of default_system_misc_info_keys if provided.
+
+  --other-target-files other-target-files-zip-archive
+      The input target files package containing other bits. This is a zip
+      archive.
+
+  --other-item-list other-item-list-file
+      The optional path to a newline-separated config file that replaces the
+      contents of default_other_item_list if provided.
+
+  --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.
+
+  --keep-tmp
+      Keep tempoary files for debugging purposes.
+"""
+
+from __future__ import print_function
+
+import fnmatch
+import logging
+import os
+import sys
+import zipfile
+
+import common
+import add_img_to_target_files
+
+logger = logging.getLogger(__name__)
+OPTIONS = common.OPTIONS
+OPTIONS.verbose = True
+OPTIONS.system_target_files = None
+OPTIONS.system_item_list = None
+OPTIONS.system_misc_info_keys = None
+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
+# system target files package as is, meaning these items will land in the
+# output target files package exactly as they appear in the input partial
+# system target files package.
+
+default_system_item_list = [
+    'META/apkcerts.txt',
+    'META/filesystem_config.txt',
+    'META/root_filesystem_config.txt',
+    'META/system_manifest.xml',
+    'META/system_matrix.xml',
+    'META/update_engine_config.txt',
+    'PRODUCT/*',
+    'ROOT/*',
+    'SYSTEM/*',
+]
+
+# system_extract_special_item_list is a list of items to extract from the
+# partial system target files package that need some special processing, such
+# as some sort of combination with items from the partial other target files
+# package.
+
+system_extract_special_item_list = [
+    'META/*',
+]
+
+# default_system_misc_info_keys is a list of keys to obtain from the system instance of
+# META/misc_info.txt. The remaining keys from the other instance.
+
+default_system_misc_info_keys = [
+    'avb_system_hashtree_enable',
+    'avb_system_add_hashtree_footer_args',
+    'avb_system_key_path',
+    'avb_system_algorithm',
+    'avb_system_rollback_index_location',
+    'avb_product_hashtree_enable',
+    'avb_product_add_hashtree_footer_args',
+    'avb_product_services_hashtree_enable',
+    'avb_product_services_add_hashtree_footer_args',
+    'system_root_image',
+    'root_dir',
+    'ab_update',
+    'default_system_dev_certificate',
+    'system_size',
+]
+
+# default_other_item_list is a list of items to extract from the partial
+# other target files package as is, meaning these items will land in the output
+# target files package exactly as they appear in the input partial other target
+# files package.
+
+default_other_item_list = [
+    'META/boot_filesystem_config.txt',
+    'META/otakeys.txt',
+    'META/releasetools.py',
+    'META/vendor_filesystem_config.txt',
+    'META/vendor_manifest.xml',
+    'META/vendor_matrix.xml',
+    'BOOT/*',
+    'DATA/*',
+    'ODM/*',
+    'OTA/android-info.txt',
+    'PREBUILT_IMAGES/*',
+    'RADIO/*',
+    'VENDOR/*',
+]
+
+# other_extract_special_item_list is a list of items to extract from the
+# partial other target files package that need some special processing, such as
+# some sort of combination with items from the partial system target files
+# package.
+
+other_extract_special_item_list = [
+    'META/*',
+]
+
+
+def extract_items(target_files, target_files_temp_dir, extract_item_list):
+  """Extract items from target files to temporary directory.
+
+  This function extracts from the specified target files zip archive into the
+  specified temporary directory, the items specified in the extract item list.
+
+  Args:
+    target_files: The target files zip archive from which to extract items.
+
+    target_files_temp_dir: The temporary directory where the extracted items
+    will land.
+
+    extract_item_list: A list of items to extract.
+  """
+
+  logger.info('extracting from %s', target_files)
+
+  # Filter the extract_item_list to remove any items that do not exist in the
+  # zip file. Otherwise, the extraction step will fail.
+
+  with zipfile.ZipFile(
+      target_files,
+      'r',
+      allowZip64=True) as target_files_zipfile:
+    target_files_namelist = target_files_zipfile.namelist()
+
+  filtered_extract_item_list = []
+  for pattern in extract_item_list:
+    matching_namelist = fnmatch.filter(target_files_namelist, pattern)
+    if not matching_namelist:
+      logger.warning('no match for %s', pattern)
+    else:
+      filtered_extract_item_list.append(pattern)
+
+  # Extract from target_files into target_files_temp_dir the
+  # filtered_extract_item_list.
+
+  common.UnzipToDir(
+      target_files,
+      target_files_temp_dir,
+      filtered_extract_item_list)
+
+
+def read_config_list(config_file_path):
+  """Reads a config file into a list of strings.
+
+  Expects the file to be newline-separated.
+
+  Args:
+    config_file_path: The path to the config file to open and read.
+  """
+  with open(config_file_path) as config_file:
+    return config_file.read().splitlines()
+
+
+def validate_config_lists(
+    system_item_list,
+    system_misc_info_keys,
+    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.
+
+    system_misc_info_keys: A list of keys to obtain from the system instance
+    of META/misc_info.txt. The remaining keys from the other instance.
+
+    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
+
+  if ('dynamic_partition_list' in system_misc_info_keys) or (
+      'super_partition_groups' in system_misc_info_keys):
+    logger.error('Dynamic partition misc info keys should come from '
+                 'the other instance of META/misc_info.txt.')
+    return False
+
+  return True
+
+
+def process_ab_partitions_txt(
+    system_target_files_temp_dir,
+    other_target_files_temp_dir,
+    output_target_files_temp_dir):
+  """Perform special processing for META/ab_partitions.txt
+
+  This function merges the contents of the META/ab_partitions.txt files from
+  the system directory and the other directory, placing the merged result in
+  the output directory. The precondition in that the files are already
+  extracted. The post condition is that the output META/ab_partitions.txt
+  contains the merged content. The format for each ab_partitions.txt a one
+  partition name per line. The output file contains the union of the parition
+  names.
+
+  Args:
+    system_target_files_temp_dir: The name of a directory containing the
+    special items extracted from the system target files package.
+
+    other_target_files_temp_dir: The name of a directory containing the
+    special items extracted from the other target files package.
+
+    output_target_files_temp_dir: The name of a directory that will be used
+    to create the output target files package after all the special cases
+    are processed.
+  """
+
+  system_ab_partitions_txt = os.path.join(
+      system_target_files_temp_dir, 'META', 'ab_partitions.txt')
+
+  other_ab_partitions_txt = os.path.join(
+      other_target_files_temp_dir, 'META', 'ab_partitions.txt')
+
+  with open(system_ab_partitions_txt) as f:
+    system_ab_partitions = f.read().splitlines()
+
+  with open(other_ab_partitions_txt) as f:
+    other_ab_partitions = f.read().splitlines()
+
+  output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
+
+  output_ab_partitions_txt = os.path.join(
+      output_target_files_temp_dir, 'META', 'ab_partitions.txt')
+
+  with open(output_ab_partitions_txt, 'w') as output:
+    for partition in sorted(output_ab_partitions):
+      output.write('%s\n' % partition)
+
+
+def append_recovery_to_filesystem_config(output_target_files_temp_dir):
+  """Perform special processing for META/filesystem_config.txt
+
+  This function appends recovery information to META/filesystem_config.txt
+  so that recovery patch regeneration will succeed.
+
+  Args:
+    output_target_files_temp_dir: The name of a directory that will be used
+    to create the output target files package after all the special cases
+    are processed. We find filesystem_config.txt here.
+  """
+
+  filesystem_config_txt = os.path.join(
+      output_target_files_temp_dir,
+      'META',
+      'filesystem_config.txt')
+
+  with open(filesystem_config_txt, 'a') as f:
+    # TODO(bpeckham) this data is hard coded. It should be generated
+    # programmatically.
+    f.write(
+        'system/bin/install-recovery.sh 0 0 750 '
+        'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
+    f.write(
+        'system/recovery-from-boot.p 0 0 644 '
+        'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
+    f.write(
+        'system/etc/recovery.img 0 0 440 '
+        'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
+
+
+def process_misc_info_txt(
+    system_target_files_temp_dir,
+    other_target_files_temp_dir,
+    output_target_files_temp_dir,
+    system_misc_info_keys):
+  """Perform special processing for META/misc_info.txt
+
+  This function merges the contents of the META/misc_info.txt files from the
+  system directory and the other directory, placing the merged result in the
+  output directory. The precondition in that the files are already extracted.
+  The post condition is that the output META/misc_info.txt contains the merged
+  content.
+
+  Args:
+    system_target_files_temp_dir: The name of a directory containing the
+    special items extracted from the system target files package.
+
+    other_target_files_temp_dir: The name of a directory containing the
+    special items extracted from the other target files package.
+
+    output_target_files_temp_dir: The name of a directory that will be used
+    to create the output target files package after all the special cases
+    are processed.
+
+    system_misc_info_keys: A list of keys to obtain from the system instance
+    of META/misc_info.txt. The remaining keys from the other instance.
+  """
+
+  def read_helper(d):
+    misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
+    with open(misc_info_txt) as f:
+      return list(f.read().splitlines())
+
+  system_info_dict = common.LoadDictionaryFromLines(
+      read_helper(system_target_files_temp_dir))
+
+  # We take most of the misc info from the other target files.
+
+  merged_info_dict = common.LoadDictionaryFromLines(
+      read_helper(other_target_files_temp_dir))
+
+  # Replace certain values in merged_info_dict with values from
+  # system_info_dict.
+
+  for key in system_misc_info_keys:
+    merged_info_dict[key] = system_info_dict[key]
+
+  # Merge misc info keys used for Dynamic Partitions.
+  if (merged_info_dict.get('use_dynamic_partitions') == 'true') and (
+      system_info_dict.get('use_dynamic_partitions') == 'true'):
+    merged_info_dict['dynamic_partition_list'] = '%s %s' % (
+        system_info_dict.get('dynamic_partition_list', ''),
+        merged_info_dict.get('dynamic_partition_list', ''))
+    # Partition groups and group sizes are defined by the other (non-system)
+    # misc info file because these values may vary for each board that uses
+    # a shared system image.
+    for partition_group in merged_info_dict['super_partition_groups'].split(' '):
+      if ('super_%s_group_size' % partition_group) not in merged_info_dict:
+        raise common.ExternalError(
+            'Other META/misc_info.txt does not contain required key '
+            'super_%s_group_size.' % partition_group)
+      key = 'super_%s_partition_list' % partition_group
+      merged_info_dict[key] = '%s %s' % (
+        system_info_dict.get(key, ''),
+        merged_info_dict.get(key, ''))
+
+  output_misc_info_txt = os.path.join(
+      output_target_files_temp_dir,
+      'META', 'misc_info.txt')
+
+  sorted_keys = sorted(merged_info_dict.keys())
+
+  with open(output_misc_info_txt, 'w') as output:
+    for key in sorted_keys:
+      output.write('{}={}\n'.format(key, merged_info_dict[key]))
+
+
+def process_file_contexts_bin(temp_dir, output_target_files_temp_dir):
+  """Perform special processing for META/file_contexts.bin.
+
+  This function combines plat_file_contexts and vendor_file_contexts, which are
+  expected to already be extracted in temp_dir, to produce a merged
+  file_contexts.bin that will land in temp_dir at META/file_contexts.bin.
+
+  Args:
+    temp_dir: The name of a scratch directory that this function can use for
+    intermediate files generated during processing.
+
+    output_target_files_temp_dir: The name of the working directory that must
+    already contain plat_file_contexts and vendor_file_contexts (in the
+    appropriate sub directories), and to which META/file_contexts.bin will be
+    written.
+  """
+
+  # To create a merged file_contexts.bin file, we use the system and vendor
+  # file contexts files as input, the m4 tool to combine them, the sorting tool
+  # to sort, and finally the sefcontext_compile tool to generate the final
+  # output. We currently omit a checkfc step since the files had been checked
+  # as part of the build.
+
+  # The m4 step concatenates the two input files contexts files. Since m4
+  # writes to stdout, we receive that into an array of bytes, and then write it
+  # to a file.
+
+  # Collect the file contexts that we're going to combine from SYSTEM, VENDOR,
+  # PRODUCT, and ODM. We require SYSTEM and VENDOR, but others are optional.
+
+  file_contexts_list = []
+
+  for partition in ['SYSTEM', 'VENDOR', 'PRODUCT', 'ODM']:
+    prefix = 'plat' if partition == 'SYSTEM' else partition.lower()
+
+    file_contexts = os.path.join(
+        output_target_files_temp_dir,
+        partition, 'etc', 'selinux', prefix + '_file_contexts')
+
+    mandatory = partition in ['SYSTEM', 'VENDOR']
+
+    if mandatory or os.path.isfile(file_contexts):
+      file_contexts_list.append(file_contexts)
+    else:
+      logger.warning('file not found: %s', file_contexts)
+
+  command = ['m4', '--fatal-warnings', '-s'] + file_contexts_list
+
+  merged_content = common.RunAndCheckOutput(command, verbose=False)
+
+  merged_file_contexts_txt = os.path.join(temp_dir, 'merged_file_contexts.txt')
+
+  with open(merged_file_contexts_txt, 'wb') as f:
+    f.write(merged_content)
+
+  # The sort step sorts the concatenated file.
+
+  sorted_file_contexts_txt = os.path.join(temp_dir, 'sorted_file_contexts.txt')
+  command = ['fc_sort', merged_file_contexts_txt, sorted_file_contexts_txt]
+  common.RunAndWait(command, verbose=True)
+
+  # Finally, the compile step creates the final META/file_contexts.bin.
+
+  file_contexts_bin = os.path.join(
+      output_target_files_temp_dir,
+      'META', 'file_contexts.bin')
+
+  command = [
+      'sefcontext_compile',
+      '-o', file_contexts_bin,
+      sorted_file_contexts_txt,
+  ]
+
+  common.RunAndWait(command, verbose=True)
+
+
+def process_special_cases(
+    temp_dir,
+    system_target_files_temp_dir,
+    other_target_files_temp_dir,
+    output_target_files_temp_dir,
+    system_misc_info_keys,
+    rebuild_recovery
+):
+  """Perform special-case processing for certain target files items.
+
+  Certain files in the output target files package require special-case
+  processing. This function performs all that special-case processing.
+
+  Args:
+    temp_dir: The name of a scratch directory that this function can use for
+    intermediate files generated during processing.
+
+    system_target_files_temp_dir: The name of a directory containing the
+    special items extracted from the system target files package.
+
+    other_target_files_temp_dir: The name of a directory containing the
+    special items extracted from the other target files package.
+
+    output_target_files_temp_dir: The name of a directory that will be used
+    to create the output target files package after all the special cases
+    are processed.
+
+    system_misc_info_keys: A list of keys to obtain from the system instance
+    of META/misc_info.txt. The remaining keys from the other instance.
+
+    rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
+    devices and write it to the system image.
+  """
+
+  if 'ab_update' in system_misc_info_keys:
+    process_ab_partitions_txt(
+        system_target_files_temp_dir=system_target_files_temp_dir,
+        other_target_files_temp_dir=other_target_files_temp_dir,
+        output_target_files_temp_dir=output_target_files_temp_dir)
+
+  if rebuild_recovery:
+    append_recovery_to_filesystem_config(
+        output_target_files_temp_dir=output_target_files_temp_dir)
+
+  process_misc_info_txt(
+      system_target_files_temp_dir=system_target_files_temp_dir,
+      other_target_files_temp_dir=other_target_files_temp_dir,
+      output_target_files_temp_dir=output_target_files_temp_dir,
+      system_misc_info_keys=system_misc_info_keys)
+
+  process_file_contexts_bin(
+      temp_dir=temp_dir,
+      output_target_files_temp_dir=output_target_files_temp_dir)
+
+
+def merge_target_files(
+    temp_dir,
+    system_target_files,
+    system_item_list,
+    system_misc_info_keys,
+    other_target_files,
+    other_item_list,
+    output_target_files,
+    rebuild_recovery):
+  """Merge two target files packages together.
+
+  This function takes system and other target files packages as input, performs
+  various file extractions, special case processing, and finally creates a
+  merged zip archive as output.
+
+  Args:
+    temp_dir: The name of a directory we use when we extract items from the
+    input target files packages, and also a scratch directory that we use for
+    temporary files.
+
+    system_target_files: The name of the zip archive containing the system
+    partial target files package.
+
+    system_item_list: The list of items to extract from the partial system
+    target files package as is, meaning these items will land in the output
+    target files package exactly as they appear in the input partial system
+    target files package.
+
+    system_misc_info_keys: The list of keys to obtain from the system instance
+    of META/misc_info.txt. The remaining keys from the other instance.
+
+    other_target_files: The name of the zip archive containing the other
+    partial target files package.
+
+    other_item_list: The list of items to extract from the partial other
+    target files package as is, meaning these items will land in the output
+    target files package exactly as they appear in the input partial other
+    target files package.
+
+    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(
+      'starting: merge system %s and other %s into output %s',
+      system_target_files,
+      other_target_files,
+      output_target_files)
+
+  # Create directory names that we'll use when we extract files from system,
+  # and other, and for zipping the final output.
+
+  system_target_files_temp_dir = os.path.join(temp_dir, 'system')
+  other_target_files_temp_dir = os.path.join(temp_dir, 'other')
+  output_target_files_temp_dir = os.path.join(temp_dir, 'output')
+
+  # Extract "as is" items from the input system partial target files package.
+  # We extract them directly into the output temporary directory since the
+  # items do not need special case processing.
+
+  extract_items(
+      target_files=system_target_files,
+      target_files_temp_dir=output_target_files_temp_dir,
+      extract_item_list=system_item_list)
+
+  # Extract "as is" items from the input other partial target files package. We
+  # extract them directly into the output temporary directory since the items
+  # do not need special case processing.
+
+  extract_items(
+      target_files=other_target_files,
+      target_files_temp_dir=output_target_files_temp_dir,
+      extract_item_list=other_item_list)
+
+  # Extract "special" items from the input system partial target files package.
+  # We extract these items to different directory since they require special
+  # processing before they will end up in the output directory.
+
+  extract_items(
+      target_files=system_target_files,
+      target_files_temp_dir=system_target_files_temp_dir,
+      extract_item_list=system_extract_special_item_list)
+
+  # Extract "special" items from the input other partial target files package.
+  # We extract these items to different directory since they require special
+  # processing before they will end up in the output directory.
+
+  extract_items(
+      target_files=other_target_files,
+      target_files_temp_dir=other_target_files_temp_dir,
+      extract_item_list=other_extract_special_item_list)
+
+  # Now that the temporary directories contain all the extracted files, perform
+  # special case processing on any items that need it. After this function
+  # completes successfully, all the files we need to create the output target
+  # files package are in place.
+
+  process_special_cases(
+      temp_dir=temp_dir,
+      system_target_files_temp_dir=system_target_files_temp_dir,
+      other_target_files_temp_dir=other_target_files_temp_dir,
+      output_target_files_temp_dir=output_target_files_temp_dir,
+      system_misc_info_keys=system_misc_info_keys,
+      rebuild_recovery=rebuild_recovery)
+
+  # Regenerate IMAGES in the temporary directory.
+
+  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)
+
+  # Finally, create the output target files zip archive.
+
+  output_zip = os.path.abspath(output_target_files)
+  output_target_files_list = os.path.join(temp_dir, 'output.list')
+  output_target_files_meta_dir = os.path.join(
+      output_target_files_temp_dir, 'META')
+
+  command = [
+      'find',
+      output_target_files_meta_dir,
+  ]
+  # TODO(bpeckham): sort this to be more like build.
+  meta_content = common.RunAndCheckOutput(command, verbose=False)
+  command = [
+      'find',
+      output_target_files_temp_dir,
+      '-path',
+      output_target_files_meta_dir,
+      '-prune',
+      '-o',
+      '-print'
+  ]
+  # TODO(bpeckham): sort this to be more like build.
+  other_content = common.RunAndCheckOutput(command, verbose=False)
+
+  with open(output_target_files_list, 'wb') as f:
+    f.write(meta_content)
+    f.write(other_content)
+
+  command = [
+      'soong_zip',
+      '-d',
+      '-o', output_zip,
+      '-C', output_target_files_temp_dir,
+      '-l', output_target_files_list,
+  ]
+  logger.info('creating %s', output_target_files)
+  common.RunAndWait(command, verbose=True)
+
+
+def call_func_with_temp_dir(func, keep_tmp):
+  """Manage the creation and cleanup of the temporary directory.
+
+  This function calls the given function after first creating a temporary
+  directory. It also cleans up the temporary directory.
+
+  Args:
+    func: The function to call. Should accept one parameter, the path to
+    the temporary directory.
+
+    keep_tmp: Keep the temporary directory after processing is complete.
+  """
+
+  # Create a temporary directory. This will serve as the parent of directories
+  # we use when we extract items from the input target files packages, and also
+  # a scratch directory that we use for temporary files.
+
+  temp_dir = common.MakeTempDir(prefix='merge_target_files_')
+
+  try:
+    func(temp_dir)
+  except:
+    raise
+  finally:
+    if keep_tmp:
+      logger.info('keeping %s', temp_dir)
+    else:
+      common.Cleanup()
+
+
+def main():
+  """The main function.
+
+  Process command line arguments, then call merge_target_files to
+  perform the heavy lifting.
+  """
+
+  common.InitLogging()
+
+  def option_handler(o, a):
+    if o == '--system-target-files':
+      OPTIONS.system_target_files = a
+    elif o == '--system-item-list':
+      OPTIONS.system_item_list = a
+    elif o == '--system-misc-info-keys':
+      OPTIONS.system_misc_info_keys = a
+    elif o == '--other-target-files':
+      OPTIONS.other_target_files = a
+    elif o == '--other-item-list':
+      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:
+      return False
+    return True
+
+  args = common.ParseOptions(
+      sys.argv[1:], __doc__,
+      extra_long_opts=[
+          'system-target-files=',
+          'system-item-list=',
+          'system-misc-info-keys=',
+          'other-target-files=',
+          'other-item-list=',
+          'output-target-files=',
+          'rebuild_recovery',
+          'keep-tmp',
+      ],
+      extra_option_handler=option_handler)
+
+  if (len(args) != 0 or
+      OPTIONS.system_target_files is None or
+      OPTIONS.other_target_files is None or
+      OPTIONS.output_target_files is None):
+    common.Usage(__doc__)
+    sys.exit(1)
+
+  if OPTIONS.system_item_list:
+    system_item_list = read_config_list(OPTIONS.system_item_list)
+  else:
+    system_item_list = default_system_item_list
+
+  if OPTIONS.system_misc_info_keys:
+    system_misc_info_keys = read_config_list(OPTIONS.system_misc_info_keys)
+  else:
+    system_misc_info_keys = default_system_misc_info_keys
+
+  if OPTIONS.other_item_list:
+    other_item_list = read_config_list(OPTIONS.other_item_list)
+  else:
+    other_item_list = default_other_item_list
+
+  if not validate_config_lists(
+      system_item_list=system_item_list,
+      system_misc_info_keys=system_misc_info_keys,
+      other_item_list=other_item_list):
+    sys.exit(1)
+
+  call_func_with_temp_dir(
+      lambda temp_dir: merge_target_files(
+          temp_dir=temp_dir,
+          system_target_files=OPTIONS.system_target_files,
+          system_item_list=system_item_list,
+          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,
+          rebuild_recovery=OPTIONS.rebuild_recovery),
+      OPTIONS.keep_tmp)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 3fbcbcf..37f4e38 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -71,6 +71,13 @@
       partitions but the target build does. For A/B, when this flag is set,
       --skip_postinstall is implied.
 
+  --skip_compatibility_check
+      Skip adding the compatibility package to the generated OTA package.
+
+  --output_metadata_path
+      Write a copy of the metadata to a separate file. Therefore, users can
+      read the post build fingerprint without extracting the OTA package.
+
 Non-A/B OTA specific options
 
   -b  (--binary) <file>
@@ -221,13 +228,16 @@
 OPTIONS.key_passwords = []
 OPTIONS.skip_postinstall = False
 OPTIONS.retrofit_dynamic_partitions = False
+OPTIONS.skip_compatibility_check = False
+OPTIONS.output_metadata_path = None
 
 
 METADATA_NAME = 'META-INF/com/android/metadata'
 POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
 DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
-UNZIP_PATTERN = ['IMAGES/*', 'META/*']
-SUPER_SPLIT_PATTERN = ['OTA/super_*.img']
+AB_PARTITIONS = 'META/ab_partitions.txt'
+UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'RADIO/*']
+RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS]
 
 
 class BuildInfo(object):
@@ -259,6 +269,12 @@
     device: The device name, which could come from OEM dicts if applicable.
   """
 
+  _RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
+                               "ro.product.manufacturer", "ro.product.model",
+                               "ro.product.name"]
+  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "product_services",
+                                            "odm", "vendor", "system"]
+
   def __init__(self, info_dict, oem_dicts):
     """Initializes a BuildInfo instance with the given dicts.
 
@@ -325,11 +341,43 @@
 
   def GetBuildProp(self, prop):
     """Returns the inquired build property."""
+    if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
+      return self._ResolveRoProductBuildProp(prop)
+
     try:
       return self.info_dict.get("build.prop", {})[prop]
     except KeyError:
       raise common.ExternalError("couldn't find %s in build.prop" % (prop,))
 
+  def _ResolveRoProductBuildProp(self, prop):
+    """Resolves the inquired ro.product.* build property"""
+    prop_val = self.info_dict.get("build.prop", {}).get(prop)
+    if prop_val:
+      return prop_val
+
+    source_order_val = self.info_dict.get("build.prop", {}).get(
+      "ro.product.property_source_order")
+    if source_order_val:
+      source_order = source_order_val.split(",")
+    else:
+      source_order = BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
+
+    # Check that all sources in ro.product.property_source_order are valid
+    if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
+            for x in source_order]):
+      raise common.ExternalError(
+        "Invalid ro.product.property_source_order '{}'".format(source_order))
+
+    for source in source_order:
+      source_prop = prop.replace("ro.product", "ro.product.{}".format(source),
+                                 1)
+      prop_val = self.info_dict.get("{}.build.prop".format(source), {}).get(
+        source_prop)
+      if prop_val:
+        return prop_val
+
+    raise common.ExternalError("couldn't resolve {}".format(prop))
+
   def GetVendorBuildProp(self, prop):
     """Returns the inquired vendor build property."""
     try:
@@ -345,7 +393,18 @@
 
   def CalculateFingerprint(self):
     if self.oem_props is None:
-      return self.GetBuildProp("ro.build.fingerprint")
+      try:
+        return self.GetBuildProp("ro.build.fingerprint")
+      except common.ExternalError:
+        return "{}/{}/{}:{}/{}/{}:{}/{}".format(
+          self.GetBuildProp("ro.product.brand"),
+          self.GetBuildProp("ro.product.name"),
+          self.GetBuildProp("ro.product.device"),
+          self.GetBuildProp("ro.build.version.release"),
+          self.GetBuildProp("ro.build.id"),
+          self.GetBuildProp("ro.build.version.incremental"),
+          self.GetBuildProp("ro.build.type"),
+          self.GetBuildProp("ro.build.tags"))
     return "%s/%s/%s:%s" % (
         self.GetOemProperty("ro.product.brand"),
         self.GetOemProperty("ro.product.name"),
@@ -701,6 +760,11 @@
   if not HasTrebleEnabled(target_zip, target_info):
     return
 
+  # Skip adding the compatibility package as a workaround for b/114240221. The
+  # compatibility will always fail on devices without qualified kernels.
+  if OPTIONS.skip_compatibility_check:
+    return
+
   # Full OTA carries the info for system/vendor both.
   if source_info is None:
     AddCompatibilityArchive(True, True)
@@ -920,10 +984,22 @@
   FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
 
 
-def WriteMetadata(metadata, output_zip):
+def WriteMetadata(metadata, output):
+  """Writes the metadata to the zip archive or a file.
+
+  Args:
+    metadata: The metadata dict for the package.
+    output: A ZipFile object or a string of the output file path.
+  """
+
   value = "".join(["%s=%s\n" % kv for kv in sorted(metadata.iteritems())])
-  common.ZipWriteStr(output_zip, METADATA_NAME, value,
-                     compress_type=zipfile.ZIP_STORED)
+  if isinstance(output, zipfile.ZipFile):
+    common.ZipWriteStr(output, METADATA_NAME, value,
+                       compress_type=zipfile.ZIP_STORED)
+    return
+
+  with open(output, 'w') as f:
+    f.write(value)
 
 
 def HandleDowngradeMetadata(metadata, target_info, source_info):
@@ -985,6 +1061,9 @@
   if OPTIONS.wipe_user_data:
     metadata['ota-wipe'] = 'yes'
 
+  if OPTIONS.retrofit_dynamic_partitions:
+    metadata['ota-retrofit-dynamic-partitions'] = 'yes'
+
   is_incremental = source_info is not None
   if is_incremental:
     metadata['pre-build'] = source_info.fingerprint
@@ -1367,6 +1446,11 @@
     for property_files in needed_property_files:
       property_files.Verify(output_zip, metadata[property_files.name].strip())
 
+  # If requested, dump the metadata to a separate file.
+  output_metadata_path = OPTIONS.output_metadata_path
+  if output_metadata_path:
+    WriteMetadata(metadata, output_metadata_path)
+
 
 def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
   target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
@@ -1718,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':
@@ -1772,7 +1851,8 @@
 
 
 def GetTargetFilesZipForRetrofitDynamicPartitions(input_file,
-                                                  super_block_devices):
+                                                  super_block_devices,
+                                                  dynamic_partition_list):
   """Returns a target-files.zip for retrofitting dynamic partitions.
 
   This allows brillo_update_payload to generate an OTA based on the exact
@@ -1781,6 +1861,7 @@
   Args:
     input_file: The input target-files.zip filename.
     super_block_devices: The list of super block devices
+    dynamic_partition_list: The list of dynamic partitions
 
   Returns:
     The filename of target-files.zip with *.img replaced with super_*.img for
@@ -1797,8 +1878,34 @@
   with zipfile.ZipFile(input_file, 'r') as input_zip:
     namelist = input_zip.namelist()
 
+  input_tmp = common.UnzipTemp(input_file, RETROFIT_DAP_UNZIP_PATTERN)
+
+  # Remove partitions from META/ab_partitions.txt that is in
+  # dynamic_partition_list but not in super_block_devices so that
+  # brillo_update_payload won't generate update for those logical partitions.
+  ab_partitions_file = os.path.join(input_tmp, *AB_PARTITIONS.split('/'))
+  with open(ab_partitions_file) as f:
+    ab_partitions_lines = f.readlines()
+    ab_partitions = [line.strip() for line in ab_partitions_lines]
+  # Assert that all super_block_devices are in ab_partitions
+  super_device_not_updated = [partition for partition in super_block_devices
+                              if partition not in ab_partitions]
+  assert not super_device_not_updated, \
+      "{} is in super_block_devices but not in {}".format(
+          super_device_not_updated, AB_PARTITIONS)
+  # ab_partitions -= (dynamic_partition_list - super_block_devices)
+  new_ab_partitions = common.MakeTempFile(prefix="ab_partitions", suffix=".txt")
+  with open(new_ab_partitions, 'w') as f:
+    for partition in ab_partitions:
+      if (partition in dynamic_partition_list and
+          partition not in super_block_devices):
+          logger.info("Dropping %s from ab_partitions.txt", partition)
+          continue
+      f.write(partition + "\n")
+  to_delete = [AB_PARTITIONS]
+
   # Always skip postinstall for a retrofit update.
-  to_delete = [POSTINSTALL_CONFIG]
+  to_delete += [POSTINSTALL_CONFIG]
 
   # Delete dynamic_partitions_info.txt so that brillo_update_payload thinks this
   # is a regular update on devices without dynamic partitions support.
@@ -1810,7 +1917,6 @@
 
   common.ZipDelete(target_file, to_delete)
 
-  input_tmp = common.UnzipTemp(input_file, SUPER_SPLIT_PATTERN)
   target_zip = zipfile.ZipFile(target_file, 'a', allowZip64=True)
 
   # Write super_{foo}.img as {foo}.img.
@@ -1820,6 +1926,9 @@
     unzipped_file = os.path.join(input_tmp, *src.split('/'))
     common.ZipWrite(target_zip, unzipped_file, arcname=dst)
 
+  # Write new ab_partitions.txt file
+  common.ZipWrite(target_zip, new_ab_partitions, arcname=AB_PARTITIONS)
+
   common.ZipClose(target_zip)
 
   return target_file
@@ -1848,7 +1957,8 @@
 
   if OPTIONS.retrofit_dynamic_partitions:
     target_file = GetTargetFilesZipForRetrofitDynamicPartitions(
-        target_file, target_info.get("super_block_devices").strip().split())
+        target_file, target_info.get("super_block_devices").strip().split(),
+        target_info.get("dynamic_partition_list").strip().split())
   elif OPTIONS.skip_postinstall:
     target_file = GetTargetFilesZipWithoutPostinstallConfig(target_file)
 
@@ -1983,6 +2093,10 @@
       OPTIONS.skip_postinstall = True
     elif o == "--retrofit_dynamic_partitions":
       OPTIONS.retrofit_dynamic_partitions = True
+    elif o == "--skip_compatibility_check":
+      OPTIONS.skip_compatibility_check = True
+    elif o == "--output_metadata_path":
+      OPTIONS.output_metadata_path = a
     else:
       return False
     return True
@@ -2014,6 +2128,8 @@
                                  "extracted_input_target_files=",
                                  "skip_postinstall",
                                  "retrofit_dynamic_partitions",
+                                 "skip_compatibility_check",
+                                 "output_metadata_path=",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index a07f67f..c482a49 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -21,11 +21,17 @@
 Usage:  sign_target_files_apks [flags] input_target_files output_target_files
 
   -e  (--extra_apks)  <name,name,...=key>
-      Add extra APK name/key pairs as though they appeared in
-      apkcerts.txt (so mappings specified by -k and -d are applied).
-      Keys specified in -e override any value for that app contained
-      in the apkcerts.txt file.  Option may be repeated to give
-      multiple extra packages.
+      Add extra APK/APEX name/key pairs as though they appeared in apkcerts.txt
+      or apexkeys.txt (so mappings specified by -k and -d are applied). Keys
+      specified in -e override any value for that app contained in the
+      apkcerts.txt file, or the container key for an APEX. Option may be
+      repeated to give multiple extra packages.
+
+  --extra_apex_payload_key <name=key>
+      Add a mapping for APEX package name to payload signing key, which will
+      override the default payload signing key in apexkeys.txt. Note that the
+      container key should be overridden via the `--extra_apks` flag above.
+      Option may be repeated for multiple APEXes.
 
   --skip_apks_with_path_prefix  <prefix>
       Skip signing an APK if it has the matching prefix in its path. The prefix
@@ -85,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_{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.
@@ -102,6 +108,8 @@
 import copy
 import errno
 import gzip
+import itertools
+import logging
 import os
 import re
 import shutil
@@ -113,6 +121,7 @@
 from xml.etree import ElementTree
 
 import add_img_to_target_files
+import apex_utils
 import common
 
 
@@ -121,9 +130,12 @@
   sys.exit(1)
 
 
+logger = logging.getLogger(__name__)
+
 OPTIONS = common.OPTIONS
 
 OPTIONS.extra_apks = {}
+OPTIONS.extra_apex_payload_keys = {}
 OPTIONS.skip_apks_with_path_prefix = set()
 OPTIONS.key_map = {}
 OPTIONS.rebuild_recovery = False
@@ -151,6 +163,43 @@
   return certmap
 
 
+def GetApexKeys(keys_info, key_map):
+  """Gets APEX payload and container signing keys by applying the mapping rules.
+
+  Presigned payload / container keys will be set accordingly.
+
+  Args:
+    keys_info: A dict that maps from APEX filenames to a tuple of (payload_key,
+        container_key).
+    key_map: A dict that overrides the keys, specified via command-line input.
+
+  Returns:
+    A dict that contains the updated APEX key mapping, which should be used for
+    the current signing.
+  """
+  # 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():
+    if not key:
+      key = 'PRESIGNED'
+    keys_info[apex] = (key, keys_info[apex][1])
+
+  # Apply the key remapping to container keys.
+  for apex, (payload_key, container_key) in keys_info.items():
+    keys_info[apex] = (payload_key, key_map.get(container_key, container_key))
+
+  # Apply all the --extra_apks options to override the container keys.
+  for apex, key in OPTIONS.extra_apks.items():
+    # Skip non-APEX containers.
+    if apex not in keys_info:
+      continue
+    if not key:
+      key = 'PRESIGNED'
+    keys_info[apex] = (keys_info[apex][0], key_map.get(key, key))
+
+  return keys_info
+
+
 def GetApkFileInfo(filename, compressed_extension, skipped_prefixes):
   """Returns the APK info based on the given filename.
 
@@ -180,11 +229,8 @@
 
   # skipped_prefixes should be one of set/list/tuple types. Other types such as
   # str shouldn't be accepted.
-  assert (isinstance(skipped_prefixes, tuple) or
-          isinstance(skipped_prefixes, set) or
-          isinstance(skipped_prefixes, list)), \
-              "Invalid skipped_prefixes input type: {}".format(
-                  type(skipped_prefixes))
+  assert isinstance(skipped_prefixes, (set, list, tuple)), \
+      "Invalid skipped_prefixes input type: {}".format(type(skipped_prefixes))
 
   compressed_apk_extension = (
       ".apk" + compressed_extension if compressed_extension else None)
@@ -200,34 +246,72 @@
   return (True, is_compressed, should_be_skipped)
 
 
-def CheckAllApksSigned(input_tf_zip, apk_key_map, compressed_extension):
-  """Checks that all the APKs have keys specified, otherwise errors out.
+def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
+                                 compressed_extension, apex_keys):
+  """Checks that all the APKs and APEXes have keys specified.
 
   Args:
     input_tf_zip: An open target_files zip file.
-    apk_key_map: A dict of known signing keys key'd by APK names.
+    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.
+        '.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.
+    AssertionError: On finding unknown APKs and APEXes.
   """
-  unknown_apks = []
+  unknown_files = []
   for info in input_tf_zip.infolist():
+    # Handle APEXes first, e.g. SYSTEM/apex/com.android.tzdata.apex.
+    if (info.filename.startswith('SYSTEM/apex') and
+        info.filename.endswith('.apex')):
+      name = os.path.basename(info.filename)
+      if name not in known_keys:
+        unknown_files.append(name)
+      continue
+
+    # And APKs.
     (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
         info.filename, compressed_extension, OPTIONS.skip_apks_with_path_prefix)
     if not is_apk or should_be_skipped:
       continue
+
     name = os.path.basename(info.filename)
     if is_compressed:
       name = name[:-len(compressed_extension)]
-    if name not in apk_key_map:
-      unknown_apks.append(name)
+    if name not in known_keys:
+      unknown_files.append(name)
 
-  assert not unknown_apks, \
+  assert not unknown_files, \
       ("No key specified for:\n  {}\n"
        "Use '-e <apkname>=' to specify a key (which may be an empty string to "
-       "not sign this apk).".format("\n  ".join(unknown_apks)))
+       "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,
@@ -293,9 +377,80 @@
   return data
 
 
+def SignApex(apex_data, payload_key, container_key, container_pw,
+             codename_to_api_level_map, signing_args=None):
+  """Signs the current APEX with the given payload/container keys.
+
+  Args:
+    apex_data: Raw APEX data.
+    payload_key: The path to payload signing key (w/ extension).
+    container_key: The path to container signing key (w/o extension).
+    container_pw: The matching password of the container_key, or None.
+    codename_to_api_level_map: A dict that maps from codename to API level.
+    signing_args: Additional args to be passed to the payload signer.
+
+  Returns:
+    The path to the signed APEX file.
+  """
+  apex_file = common.MakeTempFile(prefix='apex-', suffix='.apex')
+  with open(apex_file, 'wb') as apex_fp:
+    apex_fp.write(apex_data)
+
+  APEX_PAYLOAD_IMAGE = 'apex_payload.img'
+  APEX_PUBKEY = 'apex_pubkey'
+
+  # 1a. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given
+  # payload_key.
+  payload_dir = common.MakeTempDir(prefix='apex-payload-')
+  with zipfile.ZipFile(apex_file) as apex_fd:
+    payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
+
+  payload_info = apex_utils.ParseApexPayloadInfo(payload_file)
+  apex_utils.SignApexPayload(
+      payload_file,
+      payload_key,
+      payload_info['apex.key'],
+      payload_info['Algorithm'],
+      payload_info['Salt'],
+      signing_args)
+
+  # 1b. Update the embedded payload public key.
+  payload_public_key = common.ExtractAvbPublicKey(payload_key)
+
+  common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
+  common.ZipDelete(apex_file, APEX_PUBKEY)
+  apex_zip = zipfile.ZipFile(apex_file, 'a')
+  common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
+  common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
+  common.ZipClose(apex_zip)
+
+  # 2. Align the files at page boundary (same as in apexer).
+  aligned_apex = common.MakeTempFile(
+      prefix='apex-container-', suffix='.apex')
+  common.RunAndCheckOutput(
+      ['zipalign', '-f', '4096', apex_file, aligned_apex])
+
+  # 3. Sign the APEX container with container_key.
+  signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
+
+  # Specify the 4K alignment when calling SignApk.
+  extra_signapk_args = OPTIONS.extra_signapk_args[:]
+  extra_signapk_args.extend(['-a', '4096'])
+
+  common.SignFile(
+      aligned_apex,
+      signed_apex,
+      container_key,
+      container_pw,
+      codename_to_api_level_map=codename_to_api_level_map,
+      extra_signapk_args=extra_signapk_args)
+
+  return signed_apex
+
+
 def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
-                       apk_key_map, key_passwords, platform_api_level,
-                       codename_to_api_level_map,
+                       apk_keys, apex_keys, key_passwords,
+                       platform_api_level, codename_to_api_level_map,
                        compressed_extension):
   # maxsize measures the maximum filename length, including the ones to be
   # skipped.
@@ -331,7 +486,7 @@
       if is_compressed:
         name = name[:-len(compressed_extension)]
 
-      key = apk_key_map[name]
+      key = apk_keys[name]
       if key not in common.SPECIAL_CERT_STRINGS:
         print("    signing: %-*s (%s)" % (maxsize, name, key))
         signed_data = SignApk(data, key, key_passwords[key], platform_api_level,
@@ -344,6 +499,39 @@
             "        (skipped due to special cert string)" % (name,))
         common.ZipWriteStr(output_tf_zip, out_info, data)
 
+    # Sign bundled APEX files.
+    elif filename.startswith("SYSTEM/apex") and filename.endswith(".apex"):
+      name = os.path.basename(filename)
+      payload_key, container_key = apex_keys[name]
+
+      # 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 = 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)
+
+      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
+          filename != 'SYSTEM/etc/security/apex/'):
+      continue
+
     # System properties.
     elif filename in ("SYSTEM/build.prop",
                       "VENDOR/build.prop",
@@ -402,6 +590,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)
@@ -726,6 +926,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',
   }
@@ -816,11 +1017,67 @@
   result = dict()
   for codename in codenames:
     codename = codename.strip()
-    if len(codename) > 0:
+    if codename:
       result[codename] = api_level
   return result
 
 
+def ReadApexKeysInfo(tf_zip):
+  """Parses the APEX keys info from a given target-files zip.
+
+  Given a target-files ZipFile, parses the META/apexkeys.txt entry and returns a
+  dict that contains the mapping from APEX names (e.g. com.android.tzdata) to a
+  tuple of (payload_key, container_key).
+
+  Args:
+    tf_zip: The input target_files ZipFile (already open).
+
+  Returns:
+    (payload_key, container_key): payload_key contains the path to the payload
+        signing key; container_key contains the path to the container signing
+        key.
+  """
+  keys = {}
+  for line in tf_zip.read("META/apexkeys.txt").split("\n"):
+    line = line.strip()
+    if not line:
+      continue
+    matches = re.match(
+        r'^name="(?P<NAME>.*)"\s+'
+        r'public_key="(?P<PAYLOAD_PUBLIC_KEY>.*)"\s+'
+        r'private_key="(?P<PAYLOAD_PRIVATE_KEY>.*)"\s+'
+        r'container_certificate="(?P<CONTAINER_CERT>.*)"\s+'
+        r'container_private_key="(?P<CONTAINER_PRIVATE_KEY>.*)"$',
+        line)
+    if not matches:
+      continue
+
+    name = matches.group('NAME')
+    payload_private_key = matches.group("PAYLOAD_PRIVATE_KEY")
+
+    def CompareKeys(pubkey, pubkey_suffix, privkey, privkey_suffix):
+      pubkey_suffix_len = len(pubkey_suffix)
+      privkey_suffix_len = len(privkey_suffix)
+      return (pubkey.endswith(pubkey_suffix) and
+              privkey.endswith(privkey_suffix) and
+              pubkey[:-pubkey_suffix_len] == privkey[:-privkey_suffix_len])
+
+    # Sanity check on the container key names, as we'll carry them without the
+    # extensions. This doesn't apply to payload keys though, which we will use
+    # full names only.
+    container_cert = matches.group("CONTAINER_CERT")
+    container_private_key = matches.group("CONTAINER_PRIVATE_KEY")
+    if not CompareKeys(
+        container_cert, OPTIONS.public_key_suffix,
+        container_private_key, OPTIONS.private_key_suffix):
+      raise ValueError("Failed to parse container keys: \n{}".format(line))
+
+    keys[name] = (payload_private_key,
+                  container_cert[:-len(OPTIONS.public_key_suffix)])
+
+  return keys
+
+
 def main(argv):
 
   key_mapping_options = []
@@ -831,6 +1088,9 @@
       names = names.split(",")
       for n in names:
         OPTIONS.extra_apks[n] = key
+    elif o == "--extra_apex_payload_key":
+      apex_name, key = a.split("=")
+      OPTIONS.extra_apex_payload_keys[apex_name] = key
     elif o == "--skip_apks_with_path_prefix":
       # Sanity check the prefix, which must be in all upper case.
       prefix = a.split('/')[0]
@@ -881,12 +1141,20 @@
       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":
       OPTIONS.avb_algorithms['vendor'] = a
     elif o == "--avb_vendor_extra_args":
       OPTIONS.avb_extra_args['vendor'] = a
+    elif o == "--avb_apex_extra_args":
+      OPTIONS.avb_extra_args['apex'] = a
     else:
       return False
     return True
@@ -896,6 +1164,7 @@
       extra_opts="e:d:k:ot:",
       extra_long_opts=[
           "extra_apks=",
+          "extra_apex_payload_key=",
           "skip_apks_with_path_prefix=",
           "default_key_mappings=",
           "key_mapping=",
@@ -904,6 +1173,7 @@
           "replace_verity_public_key=",
           "replace_verity_private_key=",
           "replace_verity_keyid=",
+          "avb_apex_extra_args=",
           "avb_vbmeta_algorithm=",
           "avb_vbmeta_key=",
           "avb_vbmeta_extra_args=",
@@ -916,6 +1186,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=",
@@ -926,6 +1199,8 @@
     common.Usage(__doc__)
     sys.exit(1)
 
+  common.InitLogging()
+
   input_zip = zipfile.ZipFile(args[0], "r")
   output_zip = zipfile.ZipFile(args[1], "w",
                                compression=zipfile.ZIP_DEFLATED,
@@ -935,18 +1210,26 @@
 
   BuildKeyMap(misc_info, key_mapping_options)
 
-  certmap, compressed_extension = common.ReadApkCerts(input_zip)
-  apk_key_map = GetApkCerts(certmap)
-  CheckAllApksSigned(input_zip, apk_key_map, compressed_extension)
+  apk_keys_info, compressed_extension = common.ReadApkCerts(input_zip)
+  apk_keys = GetApkCerts(apk_keys_info)
 
-  key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
+  apex_keys_info = ReadApexKeysInfo(input_zip)
+  apex_keys = GetApexKeys(apex_keys_info, apk_keys)
+
+  CheckApkAndApexKeysAvailable(
+      input_zip,
+      set(apk_keys.keys()) | set(apex_keys.keys()),
+      compressed_extension,
+      apex_keys)
+
+  key_passwords = common.GetKeyPasswords(
+      set(apk_keys.values()) | set(itertools.chain(*apex_keys.values())))
   platform_api_level, _ = GetApiLevelAndCodename(input_zip)
   codename_to_api_level_map = GetCodenameToApiLevelMap(input_zip)
 
   ProcessTargetFiles(input_zip, output_zip, misc_info,
-                     apk_key_map, key_passwords,
-                     platform_api_level,
-                     codename_to_api_level_map,
+                     apk_keys, apex_keys, key_passwords,
+                     platform_api_level, codename_to_api_level_map,
                      compressed_extension)
 
   common.ZipClose(input_zip)
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
index d2a274d..482f86c 100644
--- a/tools/releasetools/test_add_img_to_target_files.py
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -362,7 +362,7 @@
         (0xCAC3, 4),
         (0xCAC1, 6)])
     OPTIONS.info_dict = {
-        'system_image_blocks' : 12,
+        'system_image_size' : 53248,
     }
     name, care_map = GetCareMap('system', sparse_image)
     self.assertEqual('system', name)
@@ -377,6 +377,6 @@
         (0xCAC3, 4),
         (0xCAC1, 6)])
     OPTIONS.info_dict = {
-        'system_image_blocks' : -12,
+        'system_image_size' : -45056,
     }
     self.assertRaises(AssertionError, GetCareMap, 'system', sparse_image)
diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py
new file mode 100644
index 0000000..2f8ee49
--- /dev/null
+++ b/tools/releasetools/test_apex_utils.py
@@ -0,0 +1,87 @@
+#
+# 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.
+#
+
+import os
+import os.path
+
+import apex_utils
+import common
+import test_utils
+
+
+class ApexUtilsTest(test_utils.ReleaseToolsTestCase):
+
+  # echo "foo" | sha256sum
+  SALT = 'b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c'
+
+  def setUp(self):
+    self.testdata_dir = test_utils.get_testdata_dir()
+    # The default payload signing key.
+    self.payload_key = os.path.join(self.testdata_dir, 'testkey.key')
+
+  @staticmethod
+  def _GetTestPayload():
+    payload_file = common.MakeTempFile(prefix='apex-', suffix='.img')
+    with open(payload_file, 'wb') as payload_fp:
+      payload_fp.write(os.urandom(8192))
+    return payload_file
+
+  def test_ParseApexPayloadInfo(self):
+    payload_file = self._GetTestPayload()
+    apex_utils.SignApexPayload(
+        payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
+    payload_info = apex_utils.ParseApexPayloadInfo(payload_file)
+    self.assertEqual('SHA256_RSA2048', payload_info['Algorithm'])
+    self.assertEqual(self.SALT, payload_info['Salt'])
+    self.assertEqual('testkey', payload_info['apex.key'])
+
+  def test_SignApexPayload(self):
+    payload_file = self._GetTestPayload()
+    apex_utils.SignApexPayload(
+        payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
+    apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+
+  def test_SignApexPayload_withSignerHelper(self):
+    payload_file = self._GetTestPayload()
+    payload_signer_args = '--signing_helper_with_files {}'.format(
+        os.path.join(self.testdata_dir, 'signing_helper.sh'))
+    apex_utils.SignApexPayload(
+        payload_file,
+        self.payload_key,
+        'testkey', 'SHA256_RSA2048', self.SALT,
+        payload_signer_args)
+    apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+
+  def test_SignApexPayload_invalidKey(self):
+    self.assertRaises(
+        apex_utils.ApexSigningError,
+        apex_utils.SignApexPayload,
+        self._GetTestPayload(),
+        os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+        'testkey',
+        'SHA256_RSA2048',
+        self.SALT)
+
+  def test_VerifyApexPayload_wrongKey(self):
+    payload_file = self._GetTestPayload()
+    apex_utils.SignApexPayload(
+        payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
+    apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+    self.assertRaises(
+        apex_utils.ApexSigningError,
+        apex_utils.VerifyApexPayload,
+        payload_file,
+        os.path.join(self.testdata_dir, 'testkey_with_passwd.key'))
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index cfd070d..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."""
@@ -491,6 +575,13 @@
     wrong_input = os.path.join(self.testdata_dir, 'testkey.pk8')
     self.assertRaises(AssertionError, common.ExtractPublicKey, wrong_input)
 
+  def test_ExtractAvbPublicKey(self):
+    privkey = os.path.join(self.testdata_dir, 'testkey.key')
+    pubkey = os.path.join(self.testdata_dir, 'testkey.pubkey.pem')
+    with open(common.ExtractAvbPublicKey(privkey)) as privkey_fp, \
+        open(common.ExtractAvbPublicKey(pubkey)) as pubkey_fp:
+      self.assertEqual(privkey_fp.read(), pubkey_fp.read())
+
   def test_ParseCertificate(self):
     cert = os.path.join(self.testdata_dir, 'testkey.x509.pem')
 
@@ -1218,7 +1309,7 @@
       dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
 
     self.assertNotIn("block_image_update", str(self.script),
-        "Removed partition should not be patched.")
+                     "Removed partition should not be patched.")
 
     lines = self.get_op_list(self.output_path)
     self.assertEqual(lines, ["remove foo"])
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
new file mode 100644
index 0000000..bb9ce8e
--- /dev/null
+++ b/tools/releasetools/test_merge_target_files.py
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2017 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.
+#
+
+import os.path
+
+import common
+import test_utils
+from merge_target_files import (
+    read_config_list, validate_config_lists, default_system_item_list,
+    default_other_item_list, default_system_misc_info_keys)
+
+
+class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
+
+  def setUp(self):
+    self.testdata_dir = test_utils.get_testdata_dir()
+
+  def test_read_config_list(self):
+    system_item_list_file = os.path.join(self.testdata_dir,
+                                         'merge_config_system_item_list')
+    system_item_list = read_config_list(system_item_list_file)
+    expected_system_item_list = [
+        'META/apkcerts.txt',
+        'META/filesystem_config.txt',
+        'META/root_filesystem_config.txt',
+        'META/system_manifest.xml',
+        'META/system_matrix.xml',
+        'META/update_engine_config.txt',
+        'PRODUCT/*',
+        'ROOT/*',
+        'SYSTEM/*',
+    ]
+    self.assertItemsEqual(system_item_list, expected_system_item_list)
+
+  def test_validate_config_lists_ReturnsFalseIfMissingDefaultItem(self):
+    system_item_list = default_system_item_list[:]
+    system_item_list.remove('SYSTEM/*')
+    self.assertFalse(
+        validate_config_lists(system_item_list, default_system_misc_info_keys,
+                              default_other_item_list))
+
+  def test_validate_config_lists_ReturnsTrueIfDefaultItemInDifferentList(self):
+    system_item_list = default_system_item_list[:]
+    system_item_list.remove('ROOT/*')
+    other_item_list = default_other_item_list[:]
+    other_item_list.append('ROOT/*')
+    self.assertTrue(
+        validate_config_lists(system_item_list, default_system_misc_info_keys,
+                              other_item_list))
+
+  def test_validate_config_lists_ReturnsTrueIfExtraItem(self):
+    system_item_list = default_system_item_list[:]
+    system_item_list.append('MY_NEW_PARTITION/*')
+    self.assertTrue(
+        validate_config_lists(system_item_list, default_system_misc_info_keys,
+                              default_other_item_list))
+
+  def test_validate_config_lists_ReturnsFalseIfBadSystemMiscInfoKeys(self):
+    for bad_key in ['dynamic_partition_list', 'super_partition_groups']:
+      system_misc_info_keys = default_system_misc_info_keys[:]
+      system_misc_info_keys.append(bad_key)
+      self.assertFalse(
+          validate_config_lists(default_system_item_list, system_misc_info_keys,
+                                default_other_item_list))
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index 44703db..c2da907 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -415,6 +415,7 @@
     # Reset the global options as in ota_from_target_files.py.
     common.OPTIONS.incremental_source = None
     common.OPTIONS.downgrade = False
+    common.OPTIONS.retrofit_dynamic_partitions = False
     common.OPTIONS.timestamp = False
     common.OPTIONS.wipe_user_data = False
     common.OPTIONS.no_signing = False
@@ -517,6 +518,23 @@
         },
         metadata)
 
+  def test_GetPackageMetadata_retrofitDynamicPartitions(self):
+    target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    common.OPTIONS.retrofit_dynamic_partitions = True
+    metadata = GetPackageMetadata(target_info)
+    self.assertDictEqual(
+        {
+            'ota-retrofit-dynamic-partitions' : 'yes',
+            'ota-type' : 'BLOCK',
+            'post-build' : 'build-fingerprint-target',
+            'post-build-incremental' : 'build-version-incremental-target',
+            'post-sdk-level' : '27',
+            'post-security-patch-level' : '2017-12-01',
+            'post-timestamp' : '1500000000',
+            'pre-device' : 'product-device',
+        },
+        metadata)
+
   @staticmethod
   def _test_GetPackageMetadata_swapBuildTimestamps(target_info, source_info):
     (target_info['build.prop']['ro.build.date.utc'],
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 18762ee..6a4df1a 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -21,8 +21,8 @@
 import common
 import test_utils
 from sign_target_files_apks import (
-    CheckAllApksSigned, EditTags, GetApkFileInfo, ReplaceCerts,
-    ReplaceVerityKeyId, RewriteProps)
+    CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
+    ReplaceCerts, ReplaceVerityKeyId, RewriteProps)
 
 
 class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
@@ -33,6 +33,11 @@
   <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"
+"""
+
   def setUp(self):
     self.testdata_dir = test_utils.get_testdata_dir()
 
@@ -207,7 +212,7 @@
     }
     self.assertEqual(output_xml, ReplaceCerts(input_xml))
 
-  def test_CheckAllApksSigned(self):
+  def test_CheckApkAndApexKeysAvailable(self):
     input_file = common.MakeTempFile(suffix='.zip')
     with zipfile.ZipFile(input_file, 'w') as input_zip:
       input_zip.writestr('SYSTEM/app/App1.apk', "App1-content")
@@ -219,16 +224,50 @@
         'App3.apk' : 'key3',
     }
     with zipfile.ZipFile(input_file) as input_zip:
-      CheckAllApksSigned(input_zip, apk_key_map, None)
-      CheckAllApksSigned(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.
-      CheckAllApksSigned(input_zip, apk_key_map, None)
-      CheckAllApksSigned(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, CheckAllApksSigned, input_zip, apk_key_map, '.gz')
+          AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
+          '.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(
@@ -344,3 +383,81 @@
     self.assertRaises(
         AssertionError, GetApkFileInfo, "SYSTEM_OTHER/preloads/apps/Chats.apk",
         None, None)
+
+  def test_ReadApexKeysInfo(self):
+    target_files = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+      target_files_zip.writestr('META/apexkeys.txt', self.APEX_KEYS_TXT)
+
+    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)
+
+  def test_ReadApexKeysInfo_mismatchingContainerKeys(self):
+    # Mismatching payload public / private keys.
+    apex_keys = self.APEX_KEYS_TXT + (
+        'name="apex.apexd_test_different_app2.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/testkey2.pk8"')
+    target_files = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+      target_files_zip.writestr('META/apexkeys.txt', apex_keys)
+
+    with zipfile.ZipFile(target_files) as target_files_zip:
+      self.assertRaises(ValueError, ReadApexKeysInfo, target_files_zip)
+
+  def test_ReadApexKeysInfo_missingPayloadPrivateKey(self):
+    # Invalid lines will be skipped.
+    apex_keys = self.APEX_KEYS_TXT + (
+        'name="apex.apexd_test_different_app2.apex" '
+        'public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" '
+        'container_certificate="build/target/product/security/testkey.x509.pem" '
+        'container_private_key="build/target/product/security/testkey.pk8"')
+    target_files = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+      target_files_zip.writestr('META/apexkeys.txt', apex_keys)
+
+    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)
+
+  def test_ReadApexKeysInfo_missingPayloadPublicKey(self):
+    # Invalid lines will be skipped.
+    apex_keys = self.APEX_KEYS_TXT + (
+        'name="apex.apexd_test_different_app2.apex" '
+        '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"')
+    target_files = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+      target_files_zip.writestr('META/apexkeys.txt', apex_keys)
+
+    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)
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index a6a8876..5f619ec 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -19,11 +19,13 @@
 import os
 import os.path
 import shutil
+import zipfile
 
 import common
 import test_utils
-import verity_utils
-from validate_target_files import ValidateVerifiedBootImages
+from rangelib import RangeSet
+from validate_target_files import (ValidateVerifiedBootImages,
+                                   ValidateFileConsistency)
 from verity_utils import CreateVerityImageBuilder
 
 
@@ -107,7 +109,8 @@
         AssertionError, ValidateVerifiedBootImages, input_tmp, info_dict,
         options)
 
-  def _generate_system_image(self, output_file):
+  def _generate_system_image(self, output_file, system_root=None,
+                             file_map=None):
     prop_dict = {
         'partition_size': str(1024 * 1024),
         'verity': 'true',
@@ -120,9 +123,12 @@
     image_size = verity_image_builder.CalculateMaxImageSize()
 
     # Use an empty root directory.
-    system_root = common.MakeTempDir()
+    if not system_root:
+      system_root = common.MakeTempDir()
     cmd = ['mkuserimg_mke2fs', '-s', system_root, output_file, 'ext4',
            '/system', str(image_size), '-j', '0']
+    if file_map:
+      cmd.extend(['-B', file_map])
     proc = common.Run(cmd)
     stdoutdata, _ = proc.communicate()
     self.assertEqual(
@@ -155,3 +161,56 @@
         'verity_key_mincrypt' : verity_key_mincrypt,
     }
     ValidateVerifiedBootImages(input_tmp, info_dict, options)
+
+  def test_ValidateFileConsistency_incompleteRange(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    system_root = os.path.join(input_tmp, "SYSTEM")
+    os.mkdir(system_root)
+
+    # Write the test file that contain multiple blocks of zeros, and these
+    # zero blocks will be omitted by kernel. And the test files will occupy one
+    # block range each in the final system image.
+    with open(os.path.join(system_root, 'a'), 'w') as f:
+      f.write("aaa")
+      f.write('\0' * 4096 * 3)
+    with open(os.path.join(system_root, 'b'), 'w') as f:
+      f.write("bbb")
+      f.write('\0' * 4096 * 3)
+
+    raw_file_map = os.path.join(input_tmp, 'IMAGES', 'raw_system.map')
+    self._generate_system_image(system_image, system_root, raw_file_map)
+
+    # Parse the generated file map and update the block ranges for each file.
+    file_map_list = {}
+    image_ranges = RangeSet()
+    with open(raw_file_map, 'r') as f:
+      for line in f.readlines():
+        info = line.split()
+        self.assertEqual(2, len(info))
+        image_ranges = image_ranges.union(RangeSet(info[1]))
+        file_map_list[info[0]] = RangeSet(info[1])
+
+    # Add one unoccupied block as the shared block for all test files.
+    mock_shared_block = RangeSet("10-20").subtract(image_ranges).first(1)
+    with open(os.path.join(input_tmp, 'IMAGES', 'system.map'), 'w') as f:
+      for key in sorted(file_map_list.keys()):
+        line = "{} {}\n".format(
+            key, file_map_list[key].union(mock_shared_block))
+        f.write(line)
+
+    # Prepare for the target zip file
+    input_file = common.MakeTempFile()
+    all_entries = ['SYSTEM/', 'SYSTEM/b', 'SYSTEM/a', 'IMAGES/',
+                   'IMAGES/system.map', 'IMAGES/system.img']
+    with zipfile.ZipFile(input_file, 'w') as input_zip:
+      for name in all_entries:
+        input_zip.write(os.path.join(input_tmp, name), arcname=name)
+
+    input_zip = zipfile.ZipFile(input_file, 'r')
+    info_dict = {'extfs_sparse_flag': '-s'}
+
+    # Expect the validation to pass and both files are skipped due to
+    # 'incomplete' block range.
+    ValidateFileConsistency(input_zip, input_tmp, info_dict)
diff --git a/tools/releasetools/testdata/merge_config_system_item_list b/tools/releasetools/testdata/merge_config_system_item_list
new file mode 100644
index 0000000..36c2618
--- /dev/null
+++ b/tools/releasetools/testdata/merge_config_system_item_list
@@ -0,0 +1,9 @@
+META/apkcerts.txt
+META/filesystem_config.txt
+META/root_filesystem_config.txt
+META/system_manifest.xml
+META/system_matrix.xml
+META/update_engine_config.txt
+PRODUCT/*
+ROOT/*
+SYSTEM/*
diff --git a/target/product/treble_common_32.mk b/tools/releasetools/testdata/signing_helper.sh
old mode 100644
new mode 100755
similarity index 60%
copy from target/product/treble_common_32.mk
copy to tools/releasetools/testdata/signing_helper.sh
index 0023c3b..364e023
--- a/target/product/treble_common_32.mk
+++ b/tools/releasetools/testdata/signing_helper.sh
@@ -1,5 +1,6 @@
+#!/bin/sh
 #
-# Copyright (C) 2017 The Android Open-Source Project
+# Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,9 +15,7 @@
 # limitations under the License.
 #
 
-# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# treble_system.prop.
-
-include build/make/target/product/treble_common.mk
+tmpfile=$(mktemp)
+cat $3 | openssl rsautl -sign -inkey $2 -raw > $tmpfile
+cat $tmpfile > $3
+rm $tmpfile
diff --git a/tools/releasetools/testdata/testkey_with_passwd.key b/tools/releasetools/testdata/testkey_with_passwd.key
new file mode 100644
index 0000000..2f0a199
--- /dev/null
+++ b/tools/releasetools/testdata/testkey_with_passwd.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCwaAOHPqgkCmqU
+AFRnJW6LrAuSfy9EzWSRHSkltp811ByMIE0N6/Nttu8ZCL456lzArHNKt/zdoBik
+eLB6gN9CTvQ8n4LMdSEmkRl3uXBtOPJuVObJ6ZUILz6L7WofWcr8DT81j2At7nHi
+Wg8SkCsFXbFfpjljOlpqUG3Szt+48X8rcgG82s97BuRwNxUgfK1/8QzOiH9fDbMU
+h6XI2jo2VwuBYOsJadJJWOf6oRRHZonrts0FXpV46CXykpLvLT2u5GXg1Pxd7i1K
+v1P8bxZOzVbEVfkL2DnUCtUBAnP98r9UyjQDd4blk4Mwl+mzB5otPTacNzEGhmNK
+Et+HB/cdAgMBAAECggEATsn2IXa7tHUuivHmwLb4O8vY01KY8xrleubSVPTPAUS+
+h1t57ujerbcR7VV5WPay/J9JUyr/9qClwPfioqRikwQek+EOk3ERIF+YR1/8tdvE
+c8DZ337DQIeRYP/l8SCyx4bHH43tADbKiLV+m+TmQhxJt5XPdeE/NtK7andZdwkv
+xEoG9l2aONE4z9pY1x+c1SdDSsq92/iLHLgSkQJmWo+lrfeh6gshXgQgDY8n6rgY
+GsCgSawLphvd8Tvo86CL04l0pWtY1gEW3s6sdYo1YDkpWQzSRCtGm0GlhEt2fyq5
+coTK2sLHguE7NL5VZo4zlGtM3QBdvRksTO1mJOt6JQKBgQDaT4oGjZp1rtKdObvn
+ElaUo5EOyJjmXkRBBndrbiG3078eOqTJHXx45DJUv8hj9+g6vSULiIeFk1FiiMQD
+vcnsBEaGaSc886wXY6TQgIIzvVfzDHGYTuQydiYQbLClH6S28HLqdlZjUIlHwxb9
+wBm8JwmTiVeAEvO8LTzeEqfkLwKBgQDO3He8Ei8XDeqtIK0lzcZ83yw9OGP23/gK
+8GDaf8J+cOtOyYkDlcV0rBNFvE8+TzIpIUlo47b2RSaART3iPSfRJTaySZjKWCVo
+s2A0/zQcrj7GgD2gaHRrgI9bmnWW1j95a9n/6AUEyEIJ6K8tYK819Vl4GAyhNHEQ
+sRbxa69qcwKBgQC5F8jxx2tXLdM6JLIQtzabLZcWTrN8Vh5Od3oWpriF0EzxB02h
+ipN3OBsISdZQE+dcrfNTtP0aHo5ZGZX/ihFCP1nAKjVvczXMWtppQRujXHzOABXr
+ya+mrQ+Wy2B1j7+qr3DvI0gZSjYqltjOaeon4X04DrEWUHtAZ6Z8rpqUVwKBgQCB
+o8mmI/8/A4m/Vmss9fke6P5gn6aGYXah5GPOi6Loevv9NHCZvpMwu2aYnZtMAXX+
+MM5A3fUcAdpPKRXPY2RAvoG42kbXCMbpBwGUNRwDnW/aFySIEu5jMP6m+fYXwc2l
+2uGUb2Q1ywsYCqs+VQl5V3nquaewn5z8SP+H7WTR4QKBgQCO5CRpyNOjEwMxTPR1
+GYUKAEiVtmzknHAxUE6drTgGEZSquAXiau0B5+7+/G5gwqxCLGpnstMByI+dhkR6
++ybAc/bzb2aoGK4pZf/PuwxQQsHBnG0oaSFU6RZlbVV20j7FZ04+cYnKHwCYkKjN
+DwA1Ae+H+u95raB4vYhk7IzD4A==
+-----END PRIVATE KEY-----
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index eeb802b..1c856a8 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -84,11 +84,6 @@
       # bytes past the file length, which is expected to be padded with '\0's.
       ranges = image.file_map[entry]
 
-      incomplete = ranges.extra.get('incomplete', False)
-      if incomplete:
-        logging.warning('Skipping %s that has incomplete block list', entry)
-        continue
-
       # Use the original RangeSet if applicable, which includes the shared
       # blocks. And this needs to happen before checking the monotonicity flag.
       if ranges.extra.get('uses_shared_blocks'):
@@ -96,6 +91,11 @@
       else:
         file_ranges = ranges
 
+      incomplete = file_ranges.extra.get('incomplete', False)
+      if incomplete:
+        logging.warning('Skipping %s that has incomplete block list', entry)
+        continue
+
       # TODO(b/79951650): Handle files with non-monotonic ranges.
       if not file_ranges.monotonic:
         logging.warning(
@@ -318,9 +318,31 @@
   if info_dict.get("avb_enable") == "true":
     logging.info('Verifying Verified Boot 2.0 (AVB) images...')
 
-    # TODO(b/120517892): Temporarily disable the verification for AVB-signed
-    # images. Needing supporting changes in caller to pass in the desired keys.
-    logging.info('Temporarily disabled due to b/120517892')
+    key = options['verity_key']
+    if key is None:
+      key = info_dict['avb_vbmeta_key_path']
+
+    # avbtool verifies all the images that have descriptors listed in vbmeta.
+    image = os.path.join(input_tmp, 'IMAGES', 'vbmeta.img')
+    cmd = ['avbtool', 'verify_image', '--image', image, '--key', key]
+
+    # Append the args for chained partitions if any.
+    for partition in common.AVB_PARTITIONS:
+      key_name = 'avb_' + partition + '_key_path'
+      if info_dict.get(key_name) is not None:
+        chained_partition_arg = common.GetAvbChainedPartitionArg(
+            partition, info_dict, options[key_name])
+        cmd.extend(["--expected_chain_partition", chained_partition_arg])
+
+    proc = common.Run(cmd)
+    stdoutdata, _ = proc.communicate()
+    assert proc.returncode == 0, \
+        'Failed to verify {} with avbtool (key: {}):\n{}'.format(
+            image, key, stdoutdata)
+
+    logging.info(
+        'Verified %s with avbtool (key: %s):\n%s', image, key,
+        stdoutdata.rstrip())
 
 
 def main():
diff --git a/tools/test_extract_kernel.py b/tools/test_extract_kernel.py
new file mode 100644
index 0000000..1a1cfcb
--- /dev/null
+++ b/tools/test_extract_kernel.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+from extract_kernel import get_version, dump_version
+
+class ExtractKernelTest(unittest.TestCase):
+  def test_extract_version(self):
+    self.assertEqual("4.9.100", get_version(
+        b'Linux version 4.9.100-a123 (a@a) (a) a\n\x00', 0))
+    self.assertEqual("4.9.123", get_version(
+        b'Linux version 4.9.123 (@) () \n\x00', 0))
+
+  def test_dump_self(self):
+    self.assertEqual("4.9.1", dump_version(
+        b"trash\x00Linux version 4.8.8\x00trash\x00"
+        "other trash Linux version 4.9.1-g3 (2@s) (2) a\n\x00"))