Merge "Add x86 AVX2 and AVX512 supported architectures"
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/Changes.md b/Changes.md
index 2d5cd97..1fadcef 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,75 @@
 # 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
+around the Android build. Most of the time you shouldn't need to know the
+identity of the user running the build, but if you do, it's available in the
+make variable `BUILD_USERNAME` for now.
+
+Similarly, the `hostname` tool will also be returning a more consistent value
+of `android-build`. The real value is available as `BUILD_HOSTNAME`.
+
 ## `BUILD_NUMBER` removal from Android.mk  {#BUILD_NUMBER}
 
 `BUILD_NUMBER` should not be used directly in Android.mk files, as it would
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b06a87b..51139ed 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -529,6 +529,87 @@
 $(call add-clean-step, find system/app system/priv-app system/framework system_other -depth -type d -print0 | xargs -0 rmdir)
 $(call add-clean-step, rm -f .d)
 
+# Remove obsolete apps
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
+
+# Remove corrupt generated rule due to using toybox's sed
+$(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/.intermediates/system/core/init/generated_stub_builtin_function_map)
+
+# Clean up core JNI libraries moved to runtime apex
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib*/libjavacore.so)
+$(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)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/OWNERS b/OWNERS
index b9fee4e..77496f1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,8 +1,9 @@
+# Core build team (MTV)
 ccross@android.com
 dwillemsen@google.com
-nanzhang@google.com
 
-per-file * = ccross@android.com,dwillemsen@google.com,nanzhang@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 1b2b704..811282d 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).
@@ -317,7 +337,7 @@
 # The string used to uniquely identify the combined build and product; used by the OTA server.
 ifeq (,$(strip $(BUILD_FINGERPRINT)))
   ifeq ($(strip $(HAS_BUILD_NUMBER)),false)
-    BF_BUILD_NUMBER := $(USER)$$($(DATE_FROM_FILE) +%m%d%H%M)
+    BF_BUILD_NUMBER := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M)
   else
     BF_BUILD_NUMBER := $(file <$(BUILD_NUMBER_FILE))
   endif
@@ -410,16 +430,14 @@
 	$(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)" \
 	        DATE="$(DATE_FROM_FILE)" \
+	        BUILD_USERNAME="$(BUILD_USERNAME)" \
+	        BUILD_HOSTNAME="$(BUILD_HOSTNAME)" \
 	        BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
 	        BOARD_BUILD_SYSTEM_ROOT_IMAGE="$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)" \
 	        AB_OTA_UPDATER="$(AB_OTA_UPDATER)" \
@@ -433,7 +451,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)" \
@@ -472,9 +489,6 @@
 $(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop) $(INSTALLED_RECOVERYIMAGE_TARGET)
 	@echo "Target build info: $@"
 	$(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@
-ifdef INSTALLED_RECOVERYIMAGE_TARGET
-	$(hide) echo ro.expect.recovery_id=`cat $(RECOVERYIMAGE_ID_FILE)` >> $@
-endif
 
 # -----------------------------------------------------------------
 # vendor build.prop
@@ -578,7 +592,12 @@
 	$(hide) build/make/tools/post_process_props.py $@
 
 # -----------------------------------------------------------------
-# product_services build.prop
+# product_services build.prop (unless it's merged into /product)
+ifdef MERGE_PRODUCT_SERVICES_INTO_PRODUCT
+  ifneq (,$(PRODUCT_PRODUCT_SERVICES_PROPERTIES))
+    $(error PRODUCT_PRODUCT_SERVICES_PROPERTIES is not supported in this build.)
+  endif
+else
 INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT_SERVICES)/build.prop
 ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET)
 
@@ -586,7 +605,6 @@
     $(call collapse-pairs, $(PRODUCT_PRODUCT_SERVICES_PROPERTIES))
 FINAL_PRODUCT_SERVICES_PROPERTIES := $(call uniq-pairs-by-first-component, \
     $(FINAL_PRODUCT_SERVICES_PROPERTIES),=)
-
 $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH)
 	@echo Target product_services buildinfo: $@
 	@mkdir -p $(dir $@)
@@ -600,6 +618,7 @@
 	$(hide) $(foreach line,$(FINAL_PRODUCT_SERVICES_PROPERTIES), \
 	    echo "$(line)" >> $@;)
 	$(hide) build/make/tools/post_process_props.py $@
+endif # MERGE_PRODUCT_SERVICES_INTO_PRODUCT
 
 # ----------------------------------------------------------------
 
@@ -685,8 +704,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
@@ -831,8 +852,18 @@
 
 $(call dist-for-goals, sdk win_sdk sdk_addon, $(INSTALLED_FILES_FILE_ROOT))
 
+#------------------------------------------------------------------
+# dtb
+
+ifdef BOARD_PREBUILT_DTBIMAGE_DIR
+INSTALLED_DTBIMAGE_TARGET := $(PRODUCT_OUT)/dtb.img
+$(INSTALLED_DTBIMAGE_TARGET) : $(sort $(wildcard $(BOARD_PREBUILT_DTBIMAGE_DIR)/*.dtb))
+	cat $^ > $@
+endif
+
 # -----------------------------------------------------------------
 # the ramdisk
+ifdef BUILDING_RAMDISK_IMAGE
 INTERNAL_RAMDISK_FILES := $(filter $(TARGET_RAMDISK_OUT)/%, \
 	$(ALL_GENERATED_SOURCES) \
 	$(ALL_DEFAULT_INSTALLED_MODULES))
@@ -861,6 +892,9 @@
 	@echo "make $@: ignoring dependencies"
 	$(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RAMDISK_OUT) | $(MINIGZIP) > $(INSTALLED_RAMDISK_TARGET)
 
+endif # BUILDING_RAMDISK_IMAGE
+
+
 INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
 
 ifneq ($(strip $(TARGET_NO_KERNEL)),true)
@@ -871,6 +905,10 @@
 	$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
 	--kernel $(INSTALLED_KERNEL_TARGET)
 
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+  INTERNAL_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+endif
+
 ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
 INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
 endif
@@ -892,7 +930,7 @@
 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
@@ -983,7 +1021,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
@@ -1136,8 +1173,13 @@
 	$(copy-file-to-target)
 $(installed_product_notice_xml_gz): $(target_product_notice_file_xml_gz)
 	$(copy-file-to-target)
+
+# No notice file for product_services if its contents are merged into /product.
+# The notices will be part of the /product notice file.
+ifndef MERGE_PRODUCT_SERVICES_INTO_PRODUCT
 $(installed_product_services_notice_xml_gz): $(target_product_services_notice_file_xml_gz)
 	$(copy-file-to-target)
+endif
 
 # if we've been run my mm, mmm, etc, don't reinstall this every time
 ifeq ($(ONE_SHOT_MAKEFILE),)
@@ -1222,15 +1264,12 @@
 
 INTERNAL_USERIMAGES_EXT_VARIANT :=
 ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
-INTERNAL_USERIMAGES_USE_EXT := true
 INTERNAL_USERIMAGES_EXT_VARIANT := ext2
 else
 ifeq ($(TARGET_USERIMAGES_USE_EXT3),true)
-INTERNAL_USERIMAGES_USE_EXT := true
 INTERNAL_USERIMAGES_EXT_VARIANT := ext3
 else
 ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
-INTERNAL_USERIMAGES_USE_EXT := true
 INTERNAL_USERIMAGES_EXT_VARIANT := ext4
 endif
 endif
@@ -1247,13 +1286,11 @@
   INTERNAL_USERIMAGES_SPARSE_EXT_FLAG := -s
 endif
 
-ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true)
 INTERNAL_USERIMAGES_DEPS := $(SIMG2IMG)
 INTERNAL_USERIMAGES_DEPS += $(MKEXTUSERIMG) $(MAKE_EXT4FS) $(E2FSCK) $(TUNE2FS)
 ifeq ($(TARGET_USERIMAGES_USE_F2FS),true)
 INTERNAL_USERIMAGES_DEPS += $(MKF2FSUSERIMG) $(MAKE_F2FS)
 endif
-endif
 
 ifeq ($(BOARD_AVB_ENABLE),true)
 INTERNAL_USERIMAGES_DEPS += $(AVBTOOL)
@@ -1280,9 +1317,7 @@
 
 INTERNAL_USERIMAGES_DEPS += $(BLK_ALLOC_TO_BASE_FS)
 
-ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true)
 INTERNAL_USERIMAGES_DEPS += $(MKE2FS_CONF)
-endif
 
 ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
 
@@ -1301,6 +1336,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))
@@ -1410,6 +1446,13 @@
         $(hide) echo "avb_system_key_path=$(BOARD_AVB_SYSTEM_KEY_PATH)" >> $(1)
         $(hide) echo "avb_system_algorithm=$(BOARD_AVB_SYSTEM_ALGORITHM)" >> $(1)
         $(hide) echo "avb_system_rollback_index_location=$(BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_other_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_other_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),\
+    $(if $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH),\
+        $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)
+        $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)
+        $(hide) echo "avb_system_extract_system_other_key=true" >> $(1)))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),\
@@ -1513,13 +1556,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
@@ -1773,11 +1814,18 @@
   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
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+  INTERNAL_RECOVERYIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+endif
 
 # Keys authorized to sign OTA packages this build will accept.  The
 # build always uses dev-keys for this; release packaging tools will
@@ -1862,11 +1910,18 @@
 $(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
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+$(INSTALLED_BOOTIMAGE_TARGET): $(INSTALLED_DTBIMAGE_TARGET)
+endif
 
 $(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \
 	    $(INTERNAL_ROOT_FILES) \
@@ -1885,11 +1940,18 @@
 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
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+$(INSTALLED_RECOVERYIMAGE_TARGET): $(INSTALLED_DTBIMAGE_TARGET)
+endif
 
 $(INSTALLED_RECOVERYIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \
 	    $(INTERNAL_ROOT_FILES) \
@@ -1980,6 +2042,8 @@
 	        sed "s/^/-i /" | tr '\n' ' ') -o $@
 
 # -----------------------------------------------------------------
+ifdef BUILDING_SYSTEM_IMAGE
+
 # installed file list
 # Depending on anything that $(BUILT_SYSTEMIMAGE) depends on.
 # We put installed-files.txt ahead of image itself in the dependency graph
@@ -2124,6 +2188,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))
@@ -2145,6 +2222,8 @@
 endif
 endif
 
+endif # BUILDING_SYSTEM_IMAGE
+
 .PHONY: sync syncsys
 sync syncsys: $(INTERNAL_SYSTEMIMAGE_FILES)
 
@@ -2235,16 +2314,16 @@
 	echo "-D $(TARGET_OUT)" >> $@.lst
 	echo "-D $(TARGET_OUT_NOTICE_FILES)" >> $@.lst
 	echo "$(addprefix -f $(TARGET_OUT_UNSTRIPPED)/,$(PDK_SYMBOL_FILES_LIST))" >> $@.lst
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_VENDOR_IMAGE
 	echo "-D $(TARGET_OUT_VENDOR)" >> $@.lst
 endif
-ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_IMAGE
 	echo "-D $(TARGET_OUT_PRODUCT)" >> $@.lst
 endif
-ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_SERVICES_IMAGE
 	echo "-D $(TARGET_OUT_PRODUCT_SERVICES)" >> $@.lst
 endif
-ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_ODM_IMAGE
 	echo "-D $(TARGET_OUT_ODM)" >> $@.lst
 endif
 ifneq ($(PDK_PLATFORM_JAVA_ZIP_CONTENTS),)
@@ -2312,15 +2391,7 @@
 INTERNAL_USERDATAIMAGE_FILES := \
     $(filter $(TARGET_OUT_DATA)/%,$(ALL_DEFAULT_INSTALLED_MODULES))
 
-# Don't build userdata.img if it's extfs but no partition size
-skip_userdata.img :=
-ifdef INTERNAL_USERIMAGES_EXT_VARIANT
-ifndef BOARD_USERDATAIMAGE_PARTITION_SIZE
-skip_userdata.img := true
-endif
-endif
-
-ifneq ($(skip_userdata.img),true)
+ifdef BUILDING_USERDATA_IMAGE
 userdataimage_intermediates := \
     $(call intermediates-dir-for,PACKAGING,userdata)
 BUILT_USERDATAIMAGE_TARGET := $(PRODUCT_OUT)/userdata.img
@@ -2349,8 +2420,7 @@
 userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
 	$(build-userdataimage-target)
 
-endif # not skip_userdata.img
-skip_userdata.img :=
+endif # BUILDING_USERDATA_IMAGE
 
 # ASAN libraries in the system image - build rule.
 ASAN_OUT_DIRS_FOR_SYSTEM_INSTALL := $(sort $(patsubst $(PRODUCT_OUT)/%,%,\
@@ -2424,7 +2494,7 @@
 
 # -----------------------------------------------------------------
 # cache partition image
-ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_CACHE_IMAGE
 INTERNAL_CACHEIMAGE_FILES := \
     $(filter $(TARGET_OUT_CACHE)/%,$(ALL_DEFAULT_INSTALLED_MODULES))
 
@@ -2452,16 +2522,15 @@
 cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
 	$(build-cacheimage-target)
 
-else # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+else # BUILDING_CACHE_IMAGE
 # we need to ignore the broken cache link when doing the rsync
 IGNORE_CACHE_LINK := --exclude=cache
-endif # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+endif # BUILDING_CACHE_IMAGE
 
 # -----------------------------------------------------------------
 # system_other partition image
+ifdef BUILDING_SYSTEM_OTHER_IMAGE
 ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
-BOARD_USES_SYSTEM_OTHER := true
-
 # Marker file to identify that odex files are installed
 INSTALLED_SYSTEM_OTHER_ODEX_MARKER := $(TARGET_OUT_SYSTEM_OTHER)/system-other-odex-marker
 ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_OTHER_ODEX_MARKER)
@@ -2469,7 +2538,6 @@
 	$(hide) touch $@
 endif
 
-ifdef BOARD_USES_SYSTEM_OTHER
 INTERNAL_SYSTEMOTHERIMAGE_FILES := \
     $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,\
       $(ALL_DEFAULT_INSTALLED_MODULES)\
@@ -2489,6 +2557,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
@@ -2505,7 +2584,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.
@@ -2520,12 +2599,12 @@
 systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
 	$(build-systemotherimage-target)
 
-endif # BOARD_USES_SYSTEM_OTHER
+endif # BUILDING_SYSTEM_OTHER_IMAGE
 
 
 # -----------------------------------------------------------------
 # vendor partition image
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_VENDOR_IMAGE
 INTERNAL_VENDORIMAGE_FILES := \
     $(filter $(TARGET_OUT_VENDOR)/%,\
       $(ALL_DEFAULT_INSTALLED_MODULES)\
@@ -2538,19 +2617,79 @@
 ifdef BUILT_VENDOR_MANIFEST
 BUILT_ASSEMBLED_VENDOR_MANIFEST := $(PRODUCT_OUT)/verified_assembled_vendor_manifest.xml
 ifeq (true,$(strip $(PRODUCT_ENFORCE_VINTF_MANIFEST)))
-ifdef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
-# TODO(b/65028233): turn this on globally
+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
+endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
 endif # PRODUCT_ENFORCE_VINTF_MANIFEST
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(HOST_OUT_EXECUTABLES)/assemble_vintf
 $(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 ] && \
@@ -2612,7 +2751,7 @@
 
 # -----------------------------------------------------------------
 # product partition image
-ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_IMAGE
 INTERNAL_PRODUCTIMAGE_FILES := \
     $(filter $(TARGET_OUT_PRODUCT)/%,\
       $(ALL_DEFAULT_INSTALLED_MODULES)\
@@ -2667,7 +2806,7 @@
 
 # -----------------------------------------------------------------
 # product_services partition image
-ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_SERVICES_IMAGE
 INTERNAL_PRODUCT_SERVICESIMAGE_FILES := \
     $(filter $(TARGET_OUT_PRODUCT_SERVICES)/%,\
       $(ALL_DEFAULT_INSTALLED_MODULES)\
@@ -2722,7 +2861,7 @@
 
 # -----------------------------------------------------------------
 # odm partition image
-ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_ODM_IMAGE
 INTERNAL_ODMIMAGE_FILES := \
     $(filter $(TARGET_OUT_ODM)/%,\
       $(ALL_DEFAULT_INSTALLED_MODULES)\
@@ -2819,6 +2958,27 @@
 BOARD_AVB_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
 endif
 
+# AVB signing for system_other.img.
+ifdef BUILDING_SYSTEM_OTHER_IMAGE
+ifdef BOARD_AVB_SYSTEM_OTHER_KEY_PATH
+$(if $(BOARD_AVB_SYSTEM_OTHER_ALGORITHM),,$(error BOARD_AVB_SYSTEM_OTHER_ALGORITHM is not defined))
+else
+# If key path isn't specified, use the same key as BOARD_AVB_KEY_PATH.
+BOARD_AVB_SYSTEM_OTHER_KEY_PATH := $(BOARD_AVB_KEY_PATH)
+BOARD_AVB_SYSTEM_OTHER_ALGORITHM := $(BOARD_AVB_ALGORITHM)
+endif
+
+# To extract the public key of SYSTEM_OTHER_KEY_PATH will into system.img:
+# /system/etc/security/avb/system_other.avbpubkey.
+FULL_SYSTEMIMAGE_DEPS += $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)
+
+ifndef BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX
+BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+endif
+
+BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS += --rollback_index $(BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX)
+endif # end of AVB for BUILDING_SYSTEM_OTHER_IMAGE
+
 INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES := \
     $(BOARD_AVB_VBMETA_SYSTEM) \
     $(BOARD_AVB_VBMETA_VENDOR)
@@ -2828,6 +2988,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
@@ -3080,6 +3267,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
@@ -3113,8 +3312,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) )); \
@@ -3122,7 +3323,7 @@
   else \
     echo "The sum of sizes of [$(strip $(3))] is within $(strip $(1)):"; \
     echo $${sum_sizes_expr} '==' $$(( $${sum_sizes_expr} )) '<=' "$(2)" '==' $$(( $(2) )); \
-  fi
+  fi;
 endef
 
 define check-all-partition-sizes-target
@@ -3240,6 +3441,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) \
@@ -3327,6 +3530,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) \
@@ -3426,6 +3630,8 @@
   echo "lpmake=$(notdir $(LPMAKE))" >> $(1)
   $(if $(filter true,$(PRODUCT_BUILD_SUPER_PARTITION)), $(if $(BOARD_SUPER_PARTITION_SIZE), \
     echo "build_super_partition=true" >> $(1)))
+  $(if $(filter true,$(BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE)), \
+    echo "build_retrofit_dynamic_partitions_ota_package=true" >> $(1))
   echo "super_metadata_device=$(BOARD_SUPER_PARTITION_METADATA_DEVICE)" >> $(1)
   $(if $(BOARD_SUPER_PARTITION_BLOCK_DEVICES), \
     echo "super_block_devices=$(BOARD_SUPER_PARTITION_BLOCK_DEVICES)" >> $(1))
@@ -3462,6 +3668,7 @@
 	    $(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) \
@@ -3471,6 +3678,7 @@
 	    $(LPMAKE) \
 	    $(SELINUX_FC) \
 	    $(APKCERTS_FILE) \
+	    $(SOONG_APEX_KEYS_FILE) \
 	    $(SOONG_ZIP) \
 	    $(HOST_OUT_EXECUTABLES)/fs_config \
 	    $(HOST_OUT_EXECUTABLES)/imgdiff \
@@ -3501,11 +3709,18 @@
 	$(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
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+	$(hide) cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/dtb
+endif
 ifdef INTERNAL_KERNEL_CMDLINE
 	$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
 endif
@@ -3533,6 +3748,9 @@
 ifdef INSTALLED_2NDBOOTLOADER_TARGET
 	$(hide) cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
 endif
+ifdef INSTALLED_DTBIMAGE_TARGET
+	$(hide) cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/BOOT/dtb
+endif
 ifdef INTERNAL_KERNEL_CMDLINE
 	$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
 endif
@@ -3546,33 +3764,37 @@
 	$(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),\
 	            mkdir -p $(zip_root)/RADIO; \
 	            cp $(t) $(zip_root)/RADIO/$(notdir $(t));)
+ifdef BUILDING_SYSTEM_IMAGE
 	@# Contents of the system image
 	$(hide) $(call package_files-copy-root, \
 	    $(SYSTEMIMAGE_SOURCE_DIR),$(zip_root)/SYSTEM)
+endif
+ifdef BUILDING_USERDATA_IMAGE
 	@# Contents of the data image
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_DATA),$(zip_root)/DATA)
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+endif
+ifdef BUILDING_VENDOR_IMAGE
 	@# Contents of the vendor image
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_VENDOR),$(zip_root)/VENDOR)
 endif
-ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_IMAGE
 	@# Contents of the product image
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_PRODUCT),$(zip_root)/PRODUCT)
 endif
-ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_SERVICES_IMAGE
 	@# Contents of the product_services image
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_PRODUCT_SERVICES),$(zip_root)/PRODUCT_SERVICES)
 endif
-ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_ODM_IMAGE
 	@# Contents of the odm image
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_ODM),$(zip_root)/ODM)
 endif
-ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET
+ifdef BUILDING_SYSTEM_OTHER_IMAGE
 	@# Contents of the system_other image
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_SYSTEM_OTHER),$(zip_root)/SYSTEM_OTHER)
@@ -3590,6 +3812,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
@@ -3654,7 +3877,7 @@
 	$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH) \
 	  $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ODM_BASE_FS_PATH))
 endif
-ifneq ($(strip $(SANITIZE_TARGET)),)
+ifneq (,$(filter address, $(SANITIZE_TARGET)))
 	# We need to create userdata.img with real data because the instrumented libraries are in userdata.img.
 	$(hide) echo "userdata_img_with_data=true" >> $(zip_root)/META/misc_info.txt
 endif
@@ -3771,17 +3994,19 @@
 	    echo $(part) >> $(zip_root)/META/pack_radioimages.txt;)
 	@# Run fs_config on all the system, vendor, boot ramdisk,
 	@# and recovery ramdisk files in the zip, and save the output
+ifdef BUILDING_SYSTEM_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/SYSTEM,system/) > $(zip_root)/META/filesystem_config.txt
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+endif
+ifdef BUILDING_VENDOR_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/VENDOR,vendor/) > $(zip_root)/META/vendor_filesystem_config.txt
 endif
-ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/PRODUCT,product/) > $(zip_root)/META/product_filesystem_config.txt
 endif
-ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_PRODUCT_SERVICES_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/PRODUCT_SERVICES,product_services/) > $(zip_root)/META/product_services_filesystem_config.txt
 endif
-ifdef BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+ifdef BUILDING_ODM_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/ODM,odm/) > $(zip_root)/META/odm_filesystem_config.txt
 endif
 	@# ROOT always contains the files for the root under normal boot.
@@ -3797,7 +4022,7 @@
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
 	$(hide) $(call fs_config,$(zip_root)/RECOVERY/RAMDISK,) > $(zip_root)/META/recovery_filesystem_config.txt
 endif
-ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET
+ifdef BUILDING_SYSTEM_OTHER_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/SYSTEM_OTHER,system/) > $(zip_root)/META/system_other_filesystem_config.txt
 endif
 	@# Metadata for compatibility verification.
@@ -3870,6 +4095,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)
@@ -3878,15 +4105,17 @@
 $(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)
 
-ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
+ifeq ($(BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE),true)
 name := $(TARGET_PRODUCT)
 ifeq ($(TARGET_BUILD_TYPE),debug)
   name := $(name)_debug
@@ -3912,7 +4141,7 @@
 
 otapackage otardppackage: $(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET)
 
-endif # PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
+endif # BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE
 
 endif    # build_ota_package
 
@@ -4088,6 +4317,13 @@
 # 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): extracted_input_target_files := $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE))
@@ -4095,7 +4331,22 @@
 	$(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))
 
@@ -4105,10 +4356,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 $@
 
@@ -4123,47 +4371,50 @@
 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)
-ifeq ($(BOARD_USES_VENDORIMAGE),true)
+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)
 endif
-ifeq ($(BOARD_USES_PRODUCTIMAGE),true)
+ifdef INSTALLED_PRODUCTIMAGE_TARGET
 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)
 endif
-ifeq ($(BOARD_USES_PRODUCT_SERVICESIMAGE),true)
+ifdef INSTALLED_PRODUCT_SERVICESIMAGE_TARGET
 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)
 endif
-ifeq ($(BOARD_USES_ODMIMAGE),true)
+ifdef INSTALLED_ODMIMAGE_TARGET
 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)
@@ -4389,9 +4640,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/OWNERS b/core/OWNERS
index 570ede8..750f1fa 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -1 +1,3 @@
 per-file dex_preopt*.mk = ngeoffray@google.com,calin@google.com,mathewi@google.com,dbrazdil@google.com
+per-file construct_context.sh = ngeoffray@google.com,calin@google.com,mathieuc@google.com
+per-file verify_uses_libraries.sh = ngeoffray@google.com,calin@google.com,mathieuc@google.com
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index ed759c5..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)
@@ -72,8 +62,20 @@
     my_manifest_fixer_flags += --uses-non-sdk-api
 endif
 
-ifeq (true,$(LOCAL_PREFER_CODE_INTEGRITY))
-    my_manifest_fixer_flags += --prefer-code-integrity
+ifeq (true,$(LOCAL_USE_EMBEDDED_DEX))
+    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)
diff --git a/target/board/treble_common_32.mk b/core/android_vts_host_config.mk
similarity index 65%
copy from target/board/treble_common_32.mk
copy to core/android_vts_host_config.mk
index b66c41e..38ba19d 100644
--- a/target/board/treble_common_32.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,4 +14,13 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common.mk
+LOCAL_MODULE_CLASS := FAKE
+LOCAL_IS_HOST_MODULE := true
+LOCAL_COMPATIBILITY_SUITE := vts
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE):
+	@echo "VTS host-driven test target: $(PRIVATE_MODULE)"
+	$(hide) touch $@
+
diff --git a/core/app_certificate_validate.mk b/core/app_certificate_validate.mk
new file mode 100644
index 0000000..6d3fdc8
--- /dev/null
+++ b/core/app_certificate_validate.mk
@@ -0,0 +1,10 @@
+
+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)),,\
+        $(call pretty-error,The module in product partition cannot be signed with certificate in system.))
+    endif
+  endif
+endif
\ No newline at end of file
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 cb9c35a..742119f 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -96,6 +96,12 @@
 $(call pretty-error,Only one of LOCAL_PROPRIETARY_MODULE[$(LOCAL_PROPRIETARY_MODULE)] and LOCAL_VENDOR_MODULE[$(LOCAL_VENDOR_MODULE)] may be set, or they must be equal)
 endif
 
+non_system_module := $(filter true, \
+   $(LOCAL_PRODUCT_MODULE) \
+   $(LOCAL_PRODUCT_SERVICES_MODULE) \
+   $(LOCAL_VENDOR_MODULE) \
+   $(LOCAL_PROPRIETARY_MODULE))
+
 include $(BUILD_SYSTEM)/local_vndk.mk
 include $(BUILD_SYSTEM)/local_systemsdk.mk
 
@@ -156,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.
@@ -223,6 +242,33 @@
   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 :=
+ifdef ENABLE_DEFAULT_TEST_LOCATION
+  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
+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))
@@ -230,6 +276,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
@@ -305,7 +361,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)
@@ -383,7 +441,7 @@
 # We name both BUILT and INSTALLED in case
 # LOCAL_UNINSTALLABLE_MODULE is set.
 .PHONY: $(my_all_targets)
-$(my_all_targets): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE)
+$(my_all_targets): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE) $(LOCAL_ADDITIONAL_CHECKED_MODULE)
 
 .PHONY: $(my_register_name)
 $(my_register_name): $(my_all_targets)
@@ -410,12 +468,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.
@@ -479,6 +546,8 @@
   my_checked_module := $(LOCAL_BUILT_MODULE)
 endif
 
+my_checked_module += $(LOCAL_ADDITIONAL_CHECKED_MODULE)
+
 # If they request that this module not be checked, then don't.
 # PLEASE DON'T SET THIS.  ANY PLACES THAT SET THIS WITHOUT
 # GOOD REASON WILL HAVE IT REMOVED.
@@ -523,20 +592,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.
 ###########################################################
@@ -554,11 +609,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)), \
@@ -650,6 +718,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))) \
@@ -659,6 +738,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 :=
diff --git a/core/binary.mk b/core/binary.mk
index c3878f9..ad3d76b 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -72,8 +72,11 @@
 else
   my_native_coverage := false
 endif
+ifneq ($(NATIVE_COVERAGE),true)
+  my_native_coverage := false
+endif
 
-ifeq ($(strip $(ENABLE_XOM)),true)
+ifneq ($(strip $(ENABLE_XOM)),false)
   ifndef LOCAL_IS_HOST_MODULE
     my_xom := true
     # Disable XOM in excluded paths.
@@ -254,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),)
@@ -287,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
 
@@ -312,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
 
@@ -427,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
@@ -470,144 +469,6 @@
 my_asflags += -D__ASSEMBLY__
 
 ###########################################################
-## Define PRIVATE_ variables from global vars
-###########################################################
-ifndef LOCAL_IS_HOST_MODULE
-ifdef LOCAL_USE_VNDK
-my_target_global_c_includes := \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES)
-my_target_global_c_system_includes := \
-    $(TARGET_OUT_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES)
-else ifdef LOCAL_SDK_VERSION
-my_target_global_c_includes :=
-my_target_global_c_system_includes := $(my_ndk_stl_include_path) $(my_ndk_sysroot_include)
-else ifdef BOARD_VNDK_VERSION
-my_target_global_c_includes := $(SRC_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
-my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
-else
-my_target_global_c_includes := $(SRC_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
-my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) $(TARGET_OUT_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
-endif
-
-my_target_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CFLAGS)
-my_target_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CONLYFLAGS) $(my_c_std_conlyflags)
-my_target_global_cppflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CPPFLAGS) $(my_cpp_std_cppflags)
-ifeq ($(my_use_clang_lld),true)
-  my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LLDFLAGS)
-  include $(BUILD_SYSTEM)/pack_dyn_relocs_setup.mk
-  ifeq ($(my_pack_module_relocations),false)
-    my_target_global_ldflags += -Wl,--pack-dyn-relocs=none
-  endif
-else
-  my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LDFLAGS)
-endif # my_use_clang_lld
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_INCLUDES := $(my_target_global_c_includes)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_SYSTEM_INCLUDES := $(my_target_global_c_system_includes)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(my_target_global_cflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CONLYFLAGS := $(my_target_global_conlyflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CPPFLAGS := $(my_target_global_cppflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_LDFLAGS := $(my_target_global_ldflags)
-
-else # LOCAL_IS_HOST_MODULE
-
-my_host_global_c_includes := $(SRC_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
-my_host_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
-
-my_host_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CFLAGS)
-my_host_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CONLYFLAGS) $(my_c_std_conlyflags)
-my_host_global_cppflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CPPFLAGS) $(my_cpp_std_cppflags)
-ifeq ($(my_use_clang_lld),true)
-  my_host_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LLDFLAGS)
-else
-  my_host_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LDFLAGS)
-endif # my_use_clang_lld
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_INCLUDES := $(my_host_global_c_includes)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_SYSTEM_INCLUDES := $(my_host_global_c_system_includes)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CFLAGS := $(my_host_global_cflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CONLYFLAGS := $(my_host_global_conlyflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CPPFLAGS := $(my_host_global_cppflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_LDFLAGS := $(my_host_global_ldflags)
-endif # LOCAL_IS_HOST_MODULE
-
-# To enable coverage for a given module, set LOCAL_NATIVE_COVERAGE=true and
-# build with NATIVE_COVERAGE=true in your enviornment. Note that the build
-# system is not sensitive to changes to NATIVE_COVERAGE, so you should do a
-# clean build of your module after toggling it.
-ifeq ($(NATIVE_COVERAGE),true)
-    ifeq ($(my_native_coverage),true)
-        # Note that clang coverage doesn't play nicely with acov out of the box.
-        # Clang apparently generates .gcno files that aren't compatible with
-        # gcov-4.8.  This can be solved by installing gcc-4.6 and invoking lcov
-        # with `--gcov-tool /usr/bin/gcov-4.6`.
-        #
-        # http://stackoverflow.com/questions/17758126/clang-code-coverage-invalid-output
-        my_cflags += --coverage -O0
-        my_ldflags += --coverage
-    endif
-
-    my_coverage_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)LIBPROFILE_RT)
-
-    $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_COVERAGE_LIB := $(my_coverage_lib)
-    $(LOCAL_INTERMEDIATE_TARGETS): $(my_coverage_lib)
-else
-    my_native_coverage := false
-endif
-
-###########################################################
-## Define PRIVATE_ variables used by multiple module types
-###########################################################
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_NO_DEFAULT_COMPILER_FLAGS := \
-    $(strip $(LOCAL_NO_DEFAULT_COMPILER_FLAGS))
-
-ifeq ($(strip $(WITH_STATIC_ANALYZER)),)
-  LOCAL_NO_STATIC_ANALYZER := true
-endif
-
-ifneq ($(strip $(LOCAL_IS_HOST_MODULE)),)
-  my_syntax_arch := host
-else
-  my_syntax_arch := $($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
-endif
-
-ifeq ($(strip $(my_cc)),)
-  my_cc := $(my_cc_wrapper) $(CLANG)
-endif
-
-SYNTAX_TOOLS_PREFIX := \
-    $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/libexec
-
-ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
-  my_cc := CCC_CC=$(CLANG) CLANG=$(CLANG) \
-           $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer
-endif
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CC := $(my_cc)
-
-ifeq ($(strip $(my_cxx)),)
-  my_cxx := $(my_cxx_wrapper) $(CLANG_CXX)
-endif
-
-ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
-  my_cxx := CCC_CXX=$(CLANG_CXX) CLANG_CXX=$(CLANG_CXX) \
-            $(SYNTAX_TOOLS_PREFIX)/c++-analyzer
-endif
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LINKER := $(my_linker)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CXX := $(my_cxx)
-
 # TODO: support a mix of standard extensions so that this isn't necessary
 LOCAL_CPP_EXTENSION := $(strip $(LOCAL_CPP_EXTENSION))
 ifeq ($(LOCAL_CPP_EXTENSION),)
@@ -642,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
 
@@ -793,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) \
@@ -848,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
@@ -913,8 +778,6 @@
 # Thus we'll actually generate source for each architecture.
 $(foreach s,$(vts_src),\
     $(eval $(call define-vts-cpp-rule,$(s),$(vts_gen_cpp_root),vts_gen_cpp)))
-$(foreach cpp,$(vts_gen_cpp), \
-    $(call include-depfile,$(addsuffix .vts.P,$(basename $(cpp))),$(cpp)))
 $(call track-src-file-gen,$(vts_src),$(vts_gen_cpp))
 
 $(vts_gen_cpp) : PRIVATE_MODULE := $(LOCAL_MODULE)
@@ -991,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 :=
@@ -1017,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: \
@@ -1035,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.
@@ -1047,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: \
@@ -1095,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 :=
@@ -1119,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 \
@@ -1136,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.
@@ -1148,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 \
@@ -1445,6 +1274,8 @@
 
 all_objects := $(normal_objects) $(gen_o_objects)
 
+LOCAL_INTERMEDIATE_TARGETS += $(all_objects)
+
 # Cleanup file tracking
 $(foreach f,$(my_tracked_gen_files),$(eval my_src_file_gen_$(s):=))
 my_tracked_gen_files :=
@@ -1738,6 +1569,141 @@
 # (start-group/end-group), so append after the check above.
 my_ldlibs += $(my_cxx_ldlibs)
 
+###########################################################
+## Define PRIVATE_ variables from global vars
+###########################################################
+ifndef LOCAL_IS_HOST_MODULE
+ifdef LOCAL_USE_VNDK
+my_target_global_c_includes := \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES)
+my_target_global_c_system_includes := \
+    $(TARGET_OUT_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES)
+else ifdef LOCAL_SDK_VERSION
+my_target_global_c_includes :=
+my_target_global_c_system_includes := $(my_ndk_stl_include_path) $(my_ndk_sysroot_include)
+else ifdef BOARD_VNDK_VERSION
+my_target_global_c_includes := $(SRC_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
+my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
+else
+my_target_global_c_includes := $(SRC_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
+my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) $(TARGET_OUT_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
+endif
+
+my_target_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CFLAGS)
+my_target_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CONLYFLAGS) $(my_c_std_conlyflags)
+my_target_global_cppflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CPPFLAGS) $(my_cpp_std_cppflags)
+ifeq ($(my_use_clang_lld),true)
+  my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LLDFLAGS)
+  include $(BUILD_SYSTEM)/pack_dyn_relocs_setup.mk
+  ifeq ($(my_pack_module_relocations),false)
+    my_target_global_ldflags += -Wl,--pack-dyn-relocs=none
+  endif
+else
+  my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LDFLAGS)
+endif # my_use_clang_lld
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_INCLUDES := $(my_target_global_c_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_SYSTEM_INCLUDES := $(my_target_global_c_system_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(my_target_global_cflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CONLYFLAGS := $(my_target_global_conlyflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CPPFLAGS := $(my_target_global_cppflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_LDFLAGS := $(my_target_global_ldflags)
+
+else # LOCAL_IS_HOST_MODULE
+
+my_host_global_c_includes := $(SRC_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
+my_host_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
+
+my_host_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CFLAGS)
+my_host_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CONLYFLAGS) $(my_c_std_conlyflags)
+my_host_global_cppflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CPPFLAGS) $(my_cpp_std_cppflags)
+ifeq ($(my_use_clang_lld),true)
+  my_host_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LLDFLAGS)
+else
+  my_host_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LDFLAGS)
+endif # my_use_clang_lld
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_INCLUDES := $(my_host_global_c_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_SYSTEM_INCLUDES := $(my_host_global_c_system_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CFLAGS := $(my_host_global_cflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CONLYFLAGS := $(my_host_global_conlyflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CPPFLAGS := $(my_host_global_cppflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_LDFLAGS := $(my_host_global_ldflags)
+endif # LOCAL_IS_HOST_MODULE
+
+# To enable coverage for a given module, set LOCAL_NATIVE_COVERAGE=true and
+# build with NATIVE_COVERAGE=true in your enviornment.
+ifeq ($(NATIVE_COVERAGE),true)
+    ifeq ($(my_native_coverage),true)
+        # Note that clang coverage doesn't play nicely with acov out of the box.
+        # Clang apparently generates .gcno files that aren't compatible with
+        # gcov-4.8.  This can be solved by installing gcc-4.6 and invoking lcov
+        # with `--gcov-tool /usr/bin/gcov-4.6`.
+        #
+        # http://stackoverflow.com/questions/17758126/clang-code-coverage-invalid-output
+        my_cflags += --coverage -O0
+        my_ldflags += --coverage
+    endif
+
+    my_coverage_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)LIBPROFILE_RT)
+
+    $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_COVERAGE_LIB := $(my_coverage_lib)
+    $(LOCAL_INTERMEDIATE_TARGETS): $(my_coverage_lib)
+endif
+
+###########################################################
+## Define PRIVATE_ variables used by multiple module types
+###########################################################
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_NO_DEFAULT_COMPILER_FLAGS := \
+    $(strip $(LOCAL_NO_DEFAULT_COMPILER_FLAGS))
+
+ifeq ($(strip $(WITH_STATIC_ANALYZER)),)
+  LOCAL_NO_STATIC_ANALYZER := true
+endif
+
+ifneq ($(strip $(LOCAL_IS_HOST_MODULE)),)
+  my_syntax_arch := host
+else
+  my_syntax_arch := $($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+endif
+
+ifeq ($(strip $(my_cc)),)
+  my_cc := $(my_cc_wrapper) $(CLANG)
+endif
+
+SYNTAX_TOOLS_PREFIX := \
+    $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/libexec
+
+ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
+  my_cc := CCC_CC=$(CLANG) CLANG=$(CLANG) \
+           $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CC := $(my_cc)
+
+ifeq ($(strip $(my_cxx)),)
+  my_cxx := $(my_cxx_wrapper) $(CLANG_CXX)
+endif
+
+ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
+  my_cxx := CCC_CXX=$(CLANG_CXX) CLANG_CXX=$(CLANG_CXX) \
+            $(SYNTAX_TOOLS_PREFIX)/c++-analyzer
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LINKER := $(my_linker)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CXX := $(my_cxx)
+
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_YACCFLAGS := $(LOCAL_YACCFLAGS)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASFLAGS := $(my_asflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CONLYFLAGS := $(my_conlyflags)
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..c3daf6e 100644
--- a/core/build_rro_package.mk
+++ b/core/build_rro_package.mk
@@ -18,12 +18,12 @@
 partition :=
 ifeq ($(LOCAL_ODM_MODULE),true)
   partition := $(TARGET_OUT_ODM)
-else ifeq ($(LOCAL_PRODUCT_MODULE),true)
-  partition := $(TARGET_OUT_PRODUCT)
+else ifeq ($(LOCAL_VENDOR_MODULE),true)
+  partition := $(TARGET_OUT_VENDOR)
 else ifeq ($(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
new file mode 100644
index 0000000..0faaadd
--- /dev/null
+++ b/core/check_elf_file.mk
@@ -0,0 +1,49 @@
+# Check the correctness of the prebuilt ELF files
+#
+# This check ensures that DT_SONAME matches with the filename, DT_NEEDED
+# matches the shared libraries specified in LOCAL_SHARED_LIBRARIES, and all
+# undefined symbols in the prebuilt binary can be found in one of the shared
+# libraries specified in LOCAL_SHARED_LIBRARIES.
+#
+# Inputs:
+# - LOCAL_ALLOW_UNDEFINED_SYMBOLS
+# - LOCAL_BUILT_MODULE
+# - LOCAL_IS_HOST_MODULE
+# - LOCAL_MODULE_CLASS
+# - 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)
+# 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 $@
+	$(hide) $(CHECK_ELF_FILE) \
+	    --skip-bad-elf-magic \
+	    --skip-unknown-elf-machine \
+	    $(if $(PRIVATE_SONAME),--soname $(PRIVATE_SONAME)) \
+	    $(foreach l,$(PRIVATE_SHARED_LIBRARY_FILES),--shared-lib $(l)) \
+	    $(if $(PRIVATE_ALLOW_UNDEFINED_SYMBOLS),--allow-undefined-symbols) \
+	    --llvm-readobj=$(LLVM_READOBJ) \
+	    $<
+	$(hide) touch $@
+
+ifneq ($(PRODUCT_CHECK_ELF_FILES)$(CHECK_ELF_FILES),)
+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
+endif  # PRODUCT_CHECK_ELF_FILES or CHECK_ELF_FILES
+
+endif  # SHARED_LIBRARIES, EXECUTABLES, NATIVE_TESTS
+endif  # !LOCAL_IS_HOST_MODULE
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 ca3a1fa..28a75ec 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -1,5 +1,7 @@
 ## Clang configurations.
 
+LLVM_READOBJ := $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/bin/llvm-readobj
+
 LLVM_RTLIB_PATH := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/lib64/clang/$(LLVM_RELEASE_VERSION)/lib/linux/
 
 define convert-to-clang-flags
@@ -42,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 d3cadb5..1883743 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -10,6 +10,7 @@
 LOCAL_AAPT_INCLUDE_ALL_RESOURCES:=
 LOCAL_AAPT_NAMESPACES:=
 LOCAL_ADDITIONAL_CERTIFICATES:=
+LOCAL_ADDITIONAL_CHECKED_MODULE:=
 LOCAL_ADDITIONAL_DEPENDENCIES:=
 LOCAL_ADDITIONAL_HTML_DIR:=
 LOCAL_ADDITIONAL_JAVA_DIR:=
@@ -51,11 +52,9 @@
 LOCAL_CTS_TEST_RUNNER:=
 LOCAL_CXX:=
 LOCAL_CXX_STL := default
-LOCAL_DATA_BINDING:=
 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:=
@@ -213,7 +209,8 @@
 LOCAL_PREBUILT_OBJ_FILES:=
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
 LOCAL_PREBUILT_STRIP_COMMENTS:=
-LOCAL_PREFER_CODE_INTEGRITY:=
+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:=
@@ -268,6 +265,7 @@
 LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
 LOCAL_SOONG_RRO_DIRS :=
 LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=
+LOCAL_SOONG_SYMBOL_PATH :=
 LOCAL_SOONG_TOC :=
 LOCAL_SOONG_UNSTRIPPED_BINARY :=
 # '',true
@@ -305,6 +303,7 @@
 LOCAL_WHOLE_STATIC_LIBRARIES:=
 LOCAL_XOM:=
 LOCAL_YACCFLAGS:=
+LOCAL_CHECK_ELF_FILES:=
 # TODO: deprecate, it does nothing
 OVERRIDE_BUILT_MODULE_PATH:=
 
@@ -407,31 +406,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:=
@@ -495,6 +473,7 @@
 LOCAL_IS_AUX_MODULE :=
 
 full_android_manifest :=
+non_system_module :=
 
 # Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
 # iterate over thousands of entries every time.
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index 4e83dc4..deed943 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -26,5 +26,5 @@
 
 # $(1): The file to check
 define get-file-size
-stat --format "%s" "$(1)" | tr -d '\n'
+stat -c "%s" "$(1)" | tr -d '\n'
 endef
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index c31906a..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 exynos-m1 exynos-m2
+KNOWN_ARMv8_CORES += kryo kryo385 exynos-m1 exynos-m2
 
-KNOWN_ARMv82a_CORES := cortex-a55 cortex-a75
+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/arm/armv7-a.mk b/core/combo/arch/arm/armv7-a.mk
deleted file mode 100644
index 0c2f04d..0000000
--- a/core/combo/arch/arm/armv7-a.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-# Configuration for Linux on ARM.
-# Generating binaries for the ARMv7-a architecture and higher
-#
-ARCH_ARM_HAVE_ARMV7A            := true
-ARCH_ARM_HAVE_VFP               := 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_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/config.mk b/core/config.mk
index 59b8de0..cca6200 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,12 +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:
@@ -206,24 +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 \
-
-# Default to remove the org.apache.http.legacy from bootclasspath
-ifeq ($(REMOVE_OAHL_FROM_BCP),)
-REMOVE_OAHL_FROM_BCP := true
-endif
-
-# ###############################################################
-# Broken build defaults
-# ###############################################################
-BUILD_BROKEN_ANDROIDMK_EXPORTS :=
-BUILD_BROKEN_DUP_COPY_HEADERS :=
-BUILD_BROKEN_DUP_RULES :=
-BUILD_BROKEN_PHONY_TARGETS :=
-
 # ###############################################################
 # Include sub-configuration files
 # ###############################################################
@@ -304,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
@@ -328,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
@@ -376,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
@@ -687,7 +566,7 @@
 else
 AVBTOOL := $(BOARD_CUSTOM_AVBTOOL)
 endif
-APICHECK := $(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)
+APICHECK := $(HOST_OUT_JAVA_LIBRARIES)/metalava$(COMMON_JAVA_PACKAGE_SUFFIX)
 FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
 MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
 MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs
@@ -706,10 +585,13 @@
 DATA_BINDING_COMPILER := $(HOST_OUT_JAVA_LIBRARIES)/databinding-compiler.jar
 FAT16COPY := build/make/tools/fat16copy.py
 CHECK_LINK_TYPE := build/make/tools/check_link_type.py
+CHECK_ELF_FILE := build/make/tools/check_elf_file.py
 LPMAKE := $(HOST_OUT_EXECUTABLES)/lpmake$(HOST_EXECUTABLE_SUFFIX)
 BUILD_SUPER_IMAGE := build/make/tools/releasetools/build_super_image.py
 
-PROGUARD := external/proguard/bin/proguard.sh
+PROGUARD_HOME := external/proguard
+PROGUARD := $(PROGUARD_HOME)/bin/proguard.sh
+PROGUARD_DEPS := $(PROGUARD) $(PROGUARD_HOME)/lib/proguard.jar
 JAVATAGS := build/make/tools/java-event-log-tags.py
 MERGETAGS := build/make/tools/merge-event-log-tags.py
 BUILD_IMAGE_SRCS := $(wildcard build/make/tools/releasetools/*.py)
@@ -725,14 +607,14 @@
 
 DEXDUMP := $(HOST_OUT_EXECUTABLES)/dexdump2$(BUILD_EXECUTABLE_SUFFIX)
 PROFMAN := $(HOST_OUT_EXECUTABLES)/profman
-HIDDENAPI := $(HOST_OUT_EXECUTABLES)/hiddenapi
-CLASS2GREYLIST := $(HOST_OUT_EXECUTABLES)/class2greylist
 
 FINDBUGS_DIR := external/owasp/sanitizer/tools/findbugs/bin
 FINDBUGS := $(FINDBUGS_DIR)/findbugs
 
 JETIFIER := prebuilts/sdk/tools/jetifier/jetifier-standalone/bin/jetifier-standalone
 
+EXTRACT_KERNEL := build/make/tools/extract_kernel.py
+
 COLUMN:= column
 
 USE_OPENJDK9 := true
@@ -755,13 +637,7 @@
 MD5SUM:=md5sum
 endif
 
-APICHECK_CLASSPATH_ENTRIES := \
-    $(HOST_OUT_JAVA_LIBRARIES)/apicheck$(COMMON_JAVA_PACKAGE_SUFFIX) \
-    $(HOST_JDK_TOOLS_JAR) \
-    )
-APICHECK_CLASSPATH := $(subst $(space),:,$(strip $(APICHECK_CLASSPATH_ENTRIES)))
-
-APICHECK_COMMAND := $(APICHECK) -JXmx1024m -J"classpath $(APICHECK_CLASSPATH)"
+APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK) --no-banner --compatible-output=yes
 
 # Boolean variable determining if the whitelist for compatible properties is enabled
 PRODUCT_COMPATIBLE_PROPERTY := false
@@ -890,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))
@@ -956,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),)
@@ -1005,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.
@@ -1016,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
@@ -1043,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)
 
@@ -1062,33 +952,54 @@
 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
+
+# If "vendor" is listed as one of the dynamic partitions but without its image available (e.g. an
+# AOSP target built without vendor image), don't build the retrofit full OTA package. Because we
+# won't be able to build meaningful super_* images for retrofitting purpose.
+ifneq (,$(filter vendor,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
+ifndef BUILDING_VENDOR_IMAGE
+ifndef BOARD_PREBUILT_VENDORIMAGE
+BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE :=
+endif # BOARD_PREBUILT_VENDORIMAGE
+endif # BUILDING_VENDOR_IMAGE
+endif # BOARD_SUPER_PARTITION_PARTITION_LIST
 
 else # PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
 
-# These should not be specified on devices launching with dynamic partition support.
-ifdef BOARD_SUPER_PARTITION_BLOCK_DEVICES
-$(error BOARD_SUPER_PARTITION_BLOCK_DEVICES can only be used if PRODUCT_RETROFIT_DYNAMIC_PARTITIONS is true.)
-endif
-ifdef BOARD_SUPER_PARTITION_METADATA_DEVICE
-$(error BOARD_SUPER_PARTITION_METADATA_DEVICE can only be used if PRODUCT_RETROFIT_DYNAMIC_PARTITIONS is true.)
-endif
-
 # For normal devices, we populate BOARD_SUPER_PARTITION_BLOCK_DEVICES so the
 # build can handle both cases consistently.
-BOARD_SUPER_PARTITION_BLOCK_DEVICES := super
+ifeq ($(BOARD_SUPER_PARTITION_METADATA_DEVICE),)
 BOARD_SUPER_PARTITION_METADATA_DEVICE := super
-BOARD_SUPER_PARTITION_SUPER_DEVICE_SIZE := $(BOARD_SUPER_PARTITION_SIZE)
+endif
+
+ifeq ($(BOARD_SUPER_PARTITION_BLOCK_DEVICES),)
+BOARD_SUPER_PARTITION_BLOCK_DEVICES := $(BOARD_SUPER_PARTITION_METADATA_DEVICE)
+endif
+
+# If only one super block device, default to super partition size.
+ifeq ($(word 2,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES)),)
+BOARD_SUPER_PARTITION_$(call to-upper,$(strip $(BOARD_SUPER_PARTITION_BLOCK_DEVICES)))_DEVICE_SIZE ?= \
+    $(BOARD_SUPER_PARTITION_SIZE)
+endif
+
+ifneq ($(BOARD_SUPER_PARTITION_METADATA_DEVICE),super)
+INTERNAL_KERNEL_CMDLINE += androidboot.super_partition=$(BOARD_SUPER_PARTITION_METADATA_DEVICE)
+endif
+BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE :=
 
 endif # PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
 endif # BOARD_SUPER_PARTITION_SIZE
 .KATI_READONLY := BOARD_SUPER_PARTITION_BLOCK_DEVICES
 .KATI_READONLY := BOARD_SUPER_PARTITION_METADATA_DEVICE
+.KATI_READONLY := BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE
 
 $(foreach device,$(call to-upper,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES)), \
     $(eval BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE := $(strip $(BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE))) \
     $(if $(BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE),, \
-        $(error $(BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE must not be empty))) \
+        $(error BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE must not be empty)) \
     $(eval .KATI_READONLY := BOARD_SUPER_PARTITION_$(device)_DEVICE_SIZE))
 
 endif # PRODUCT_BUILD_SUPER_PARTITION
@@ -1121,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
 
@@ -1210,11 +1123,6 @@
 INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-private-dex.txt
 endif
 
-INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-public-list.txt
-INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-private-list.txt
-INTERNAL_PLATFORM_HIDDENAPI_FLAGS := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-flags.csv
-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
@@ -1275,4 +1183,12 @@
 include $(BUILD_SYSTEM)/soong_config.mk
 endif
 
+# If ENABLE_DEFAULT_TEST_LOCATION is true, move default install path from
+# $(my_prefix)OUT_DATA to $(my_prefix)OUT_TESTCASES
+ENABLE_DEFAULT_TEST_LOCATION := true
+-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 := ENABLE_DEFAULT_TEST_LOCATION DEFAULT_DATA_OUT_MODULES
+
 include $(BUILD_SYSTEM)/dumpvar.mk
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 6c9caa8..a8a7443 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 ($(strip $(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 768403c..e880fa5 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -77,6 +77,9 @@
 # GPL module license files
 ALL_GPL_MODULE_LICENSE_FILES:=
 
+# Packages with certificate violation
+CERTIFICATE_VIOLATION_MODULES :=
+
 # Target and host installed module's dependencies on shared libraries.
 # They are list of "<module_name>:<installed_file>:lib1,lib2...".
 TARGET_DEPENDENCIES_ON_SHARED_LIBRARIES :=
@@ -1023,7 +1026,7 @@
 @mkdir -p $(dir $@)
 @mkdir -p $(PRIVATE_HEADER_OUTPUT_DIR)
 @echo "Generating C++ from VTS: $(PRIVATE_MODULE) <= $<"
-$(hide) $(VTSC) -d$(basename $@).vts.P $(PRIVATE_VTS_FLAGS) \
+$(hide) $(VTSC) -TODO_b/120496070 $(PRIVATE_VTS_FLAGS) \
     $< $(PRIVATE_HEADER_OUTPUT_DIR) $@
 endef
 
@@ -2192,13 +2195,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) \
@@ -2248,24 +2275,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
 
@@ -2333,7 +2351,7 @@
   mv $@ $@.unaligned; \
   $(ZIPALIGN) \
     -f \
-    $(ZIPALIGN_PAGE_ALIGN_FLAGS) \
+    -p \
     4 \
     $@.unaligned $@.aligned; \
   mv $@.aligned $@; \
@@ -2370,7 +2388,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 \
@@ -2460,14 +2478,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)))
@@ -2661,79 +2701,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_PRIVATE_LIST): $(1)
-$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST): 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_PUBLIC_LIST)
-	$(CLASS2GREYLIST) --public-api-list $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) $(1) \
-	    --write-flags-csv $(2)
-
-$(3): $(1) $(CLASS2GREYLIST) $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST)
-	$(CLASS2GREYLIST) --public-api-list $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) $(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): $(5)
-$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): \
-    PRIVATE_METADATA_INPUTS := $$(PRIVATE_METADATA_INPUTS) $(5)
-
-endif
-endef
-
-# File names for intermediate dex files of `hiddenapi-copy-soong-jar`.
-hiddenapi-soong-input-dex = $(dir $(1))/hiddenapi/dex-input/classes.dex
-hiddenapi-soong-output-dex = $(dir $(1))/hiddenapi/dex-output/classes.dex
-
-# Decompress a JAR with dex files, invoke $(HIDDENAPI) on them and compress again.
-define hiddenapi-copy-soong-jar
-$(call hiddenapi-soong-input-dex,$(2)): $(1)
-	@rm -rf `dirname $$@`
-	@mkdir -p `dirname $$@`
-	unzip -o -q $(1) 'classes*.dex' -d `dirname $$@`
-	find `dirname $$@` -maxdepth 1 -name 'classes*.dex' | xargs touch
-
-$(call hiddenapi-copy-dex-files,\
-    $(call hiddenapi-soong-input-dex,$(2)),\
-    $(call hiddenapi-soong-output-dex,$(2)))
-
-$(2): OUTPUT_DIR := $(dir $(call hiddenapi-soong-output-dex,$(2)))
-$(2): OUTPUT_JAR := $(dir $(call hiddenapi-soong-output-dex,$(2)))classes.jar
-$(2): $(1) $(call hiddenapi-soong-output-dex,$(2)) | $(SOONG_ZIP) $(MERGE_ZIPS)
-	$(SOONG_ZIP) -o $${OUTPUT_JAR} -C $${OUTPUT_DIR} -f "$${OUTPUT_DIR}/classes*.dex"
-	$(MERGE_ZIPS) -D -zipToNotStrip $${OUTPUT_JAR} -stripFile "classes*.dex" $(2) $${OUTPUT_JAR} $(1)
-endef
-
 
 ###########################################################
 ## Commands to call R8
@@ -2749,7 +2716,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,,$@) \
@@ -2845,17 +2813,18 @@
 #  $(5): New LOCAL_CERTIFICATE value.
 #  $(6): New LOCAL_INSTRUMENTATION_FOR value.
 #  $(7): New LOCAL_MANIFEST_INSTRUMENTATION_FOR value.
+#  $(8): New LOCAL_COMPATIBILITY_SUITE value.
 #
 # Note that LOCAL_PACKAGE_OVERRIDES is NOT cleared in
 # clear_vars.mk.
 ###########################################################
 define inherit-package
-  $(eval $(call inherit-package-internal,$(1),$(2),$(3),$(4),$(5),$(6),$(7)))
+  $(eval $(call inherit-package-internal,$(1),$(2),$(3),$(4),$(5),$(6),$(7),$(8)))
 endef
 
 define inherit-package-internal
   LOCAL_PACKAGE_OVERRIDES \
-      := $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||&&$(strip $(5))||&&$(strip $(6))||&&$(strip $(7)) $(LOCAL_PACKAGE_OVERRIDES)
+      := $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||&&$(strip $(5))||&&$(strip $(6))||&&$(strip $(7))||&&$(strip $(8)) $(LOCAL_PACKAGE_OVERRIDES)
   include $(1)
   LOCAL_PACKAGE_OVERRIDES \
       := $(wordlist 1,$(words $(LOCAL_PACKAGE_OVERRIDES)), $(LOCAL_PACKAGE_OVERRIDES))
@@ -2880,6 +2849,7 @@
     $(call keep-or-override,LOCAL_CERTIFICATE,$(patsubst &&%,%,$(word 5,$(_o)))) \
     $(call keep-or-override,LOCAL_INSTRUMENTATION_FOR,$(patsubst &&%,%,$(word 6,$(_o)))) \
     $(call keep-or-override,LOCAL_MANIFEST_INSTRUMENTATION_FOR,$(patsubst &&%,%,$(word 7,$(_o)))) \
+    $(call keep-or-override,LOCAL_COMPATIBILITY_SUITE,$(patsubst &&%,%,$(word 8,$(_o)))) \
     $(eval LOCAL_OVERRIDES_PACKAGES := $(sort $(LOCAL_OVERRIDES_PACKAGES) $(word 2,$(_o)))) \
     true \
   ,)
@@ -2904,7 +2874,7 @@
 define check-api
 $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp: $(2) $(3) $(4) $(APICHECK) $(9)
 	@echo "Checking API:" $(1)
-	$(hide) ( $(APICHECK_COMMAND) $(6) $(2) $(3) $(4) $(5) || ( $(7) ; exit 38 ) )
+	$(hide) ( $(APICHECK_COMMAND) --check-api-files $(6) $(2) $(3) $(4) $(5) || ( $(7) ; exit 38 ) )
 	$(hide) mkdir -p $$(dir $$@)
 	$(hide) touch $$@
 $(8): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 59346ed..d43158e 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -13,91 +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)
-
-# 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.
-# Inputs are filled with `hiddenapi-copy-dex-files` rules.
-.KATI_RESTAT: \
-	$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \
-	$(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST): PRIVATE_HIDDENAPI_STUBS := $(HIDDENAPI_STUBS)
-$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST): PRIVATE_HIDDENAPI_STUBS_SYSTEM := $(HIDDENAPI_STUBS_SYSTEM)
-$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST): PRIVATE_HIDDENAPI_STUBS_TEST := $(HIDDENAPI_STUBS_TEST)
-$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST): \
-    .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST): $(HIDDENAPI) $(HIDDENAPI_STUBS) \
-                                             $(HIDDENAPI_STUBS_SYSTEM) $(HIDDENAPI_STUBS_TEST)
-	for INPUT_DEX in $(PRIVATE_DEX_INPUTS); do \
-		find `dirname $${INPUT_DEX}` -maxdepth 1 -name "classes*.dex"; \
-	done | sort | sed 's/^/--boot-dex=/' | xargs $(HIDDENAPI) list \
-	    --stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS)) \
-	    --stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS_SYSTEM)) \
-	    --stub-classpath=$(call normalize-path-list, $(PRIVATE_HIDDENAPI_STUBS_TEST)) \
-	    --out-public=$(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST).tmp \
-	    --out-private=$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST).tmp
-	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST))
-	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST))
-
-
+$(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 := \
-  $(foreach m,$(DEXPREOPT_BOOT_JARS_MODULES),$(PRODUCT_OUT)/system/framework/$(m).jar) \
-  $(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 cc45689..13e4634 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -1,26 +1,5 @@
 DEX_PREOPT_CONFIG := $(PRODUCT_OUT)/dexpreopt.config
 
-# list of boot classpath jars for dexpreopt
-DEXPREOPT_BOOT_JARS := $(subst $(space),:,$(PRODUCT_BOOT_JARS))
-DEXPREOPT_BOOT_JARS_MODULES := $(PRODUCT_BOOT_JARS)
-PRODUCT_BOOTCLASSPATH := $(subst $(space),:,$(foreach m,$(DEXPREOPT_BOOT_JARS_MODULES),/system/framework/$(m).jar))
-
-PRODUCT_SYSTEM_SERVER_CLASSPATH := $(subst $(space),:,$(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),/system/framework/$(m).jar))
-
-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
-
 # The default value for LOCAL_DEX_PREOPT
 DEX_PREOPT_DEFAULT ?= true
 
@@ -34,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
@@ -64,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)
@@ -105,14 +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_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, BootJars,                           $(DEXPREOPT_BOOT_JARS_MODULES))
+  $(call add_json_str,  ProfileDir,                         $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
+  $(call add_json_list, BootJars,                           $(PRODUCT_BOOT_JARS))
+  $(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))
@@ -120,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)))
@@ -133,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
@@ -154,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)
@@ -184,17 +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 631db0a..edd82df 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -1,98 +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 := $(foreach jar,$(LIBART_TARGET_BOOT_JARS),/$(DEXPREOPT_BOOT_JAR_DIR)/$(jar).jar)
-LIBART_TARGET_BOOT_DEX_FILES := $(foreach jar,$(LIBART_TARGET_BOOT_JARS),$(call intermediates-dir-for,JAVA_LIBRARIES,$(jar),,COMMON)/javalib.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 156ce02..34b8526 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -1,118 +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
-	@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
-	$(hide) $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) $(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
-		--avoid-storing-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 \
-		--abort-on-soft-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 17eeb8a..85ddbfa 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -1,9 +1,8 @@
 # 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_PREFER_CODE_INTEGRITY))
+ifeq (true,$(LOCAL_USE_EMBEDDED_DEX))
   LOCAL_UNCOMPRESS_DEX := true
 else
   LOCAL_UNCOMPRESS_DEX :=
@@ -117,13 +116,28 @@
 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.
-    my_filtered_lib_name := $(patsubst %.impl,%,$(LOCAL_MODULE))
-    ifeq (,$(filter $(JAVA_SDK_LIBRARIES),$(my_filtered_lib_name)))
+    ifeq (,$(filter $(JAVA_SDK_LIBRARIES),$(LOCAL_MODULE)))
       # For a Java library, by default we build odex for both 1st arch and 2nd arch.
       # But it can be overridden with "LOCAL_MULTILIB := first".
       ifneq (,$(filter $(PRODUCT_SYSTEM_SERVER_JARS),$(LOCAL_MODULE)))
@@ -140,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
@@ -154,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
@@ -176,34 +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, PreferCodeIntegrity,           $(filter true,$(LOCAL_PREFER_CODE_INTEGRITY)))
-  $(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.impl android.hidl.base-V1.0-java android.hidl.manager-V1.0-java),\
+  $(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_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.impl android.hidl.base-V1.0-java android.hidl.manager-V1.0-java),\
+    $(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..ad734b5 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)
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 f5babb6..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 core-simple 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,211 +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
-
-###########################################
-# 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
-
-###########################################
-# 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
-
-###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT_SERVICES
-ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),$(_product_services_path_placeholder))
-TARGET_COPY_OUT_PRODUCT_SERVICES := system/product_services
-else ifeq ($(filter product_services system/product_services,$(TARGET_COPY_OUT_PRODUCT_SERVICES)),)
-$(error TARGET_COPY_OUT_PRODUCT_SERVICES must be either 'product_services' or 'system/product_services', seeing '$(TARGET_COPY_OUT_PRODUCT_SERVICES)'.)
-endif
-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
-
-###########################################
-# 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
-
-###########################################
-# 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)
@@ -540,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)
@@ -549,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 \
@@ -564,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 \
@@ -659,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
@@ -692,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)
@@ -711,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 \
@@ -725,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..6c95983 100644
--- a/core/generate_enforce_rro.mk
+++ b/core/generate_enforce_rro.mk
@@ -26,11 +26,16 @@
 
 LOCAL_AAPT_FLAGS += --auto-add-overlay
 LOCAL_RESOURCE_DIR := $(enforce_rro_source_overlays)
+LOCAL_PRODUCT_MODULE := true
 
-ifeq (framework-res__auto_generated_rro,$(enforce_rro_module))
-LOCAL_PRIVATE_PLATFORM_APIS := true
+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__auto_generated_rro,$(enforce_rro_module))
+  LOCAL_PRIVATE_PLATFORM_APIS := true
 else
-LOCAL_SDK_VERSION := current
+  LOCAL_SDK_VERSION := current
 endif
 
 include $(BUILD_RRO_PACKAGE)
diff --git a/core/goma.mk b/core/goma.mk
index 3787dfd..c265259 100644
--- a/core/goma.mk
+++ b/core/goma.mk
@@ -16,41 +16,18 @@
 
 # Notice: this works only with Google's Goma build infrastructure.
 ifneq ($(filter-out false,$(USE_GOMA)),)
-  # Goma requires a lot of processes and file descriptors.
-  ifeq ($(shell echo $$(($$(ulimit -u) < 2500 || $$(ulimit -n) < 16000))),1)
-    $(warning Max user processes and/or open files are insufficient)
-    ifeq ($(shell uname),Darwin)
-      $(error See go/ma/how-to-use-goma/how-to-use-goma-for-android to relax the limit)
-    else
-      $(error Adjust the limit by ulimit -u and ulimit -n)
-    endif
-  endif
-
   ifdef GOMA_DIR
     goma_dir := $(GOMA_DIR)
   else
     goma_dir := $(HOME)/goma
   endif
-  goma_ctl := $(goma_dir)/goma_ctl.py
   GOMA_CC := $(goma_dir)/gomacc
 
-  $(if $(wildcard $(goma_ctl)),, \
-   $(warning You should have goma in $$GOMA_DIR or $(HOME)/goma) \
-   $(error See go/ma/how-to-use-goma/how-to-use-goma-for-android for detail))
-
   # Append gomacc to existing *_WRAPPER variables so it's possible to
   # use both ccache and gomacc.
   CC_WRAPPER := $(strip $(CC_WRAPPER) $(GOMA_CC))
   CXX_WRAPPER := $(strip $(CXX_WRAPPER) $(GOMA_CC))
   JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(GOMA_CC))
 
-  # gomacc can start goma client's daemon process automatically, but
-  # it is safer and faster to start up it beforehand. We run this as a
-  # background process so this won't slow down the build.
-  ifndef NOSTART_GOMA
-    $(shell ( $(goma_ctl) ensure_start ) &> /dev/null &)
-  endif
-
-  goma_ctl :=
   goma_dir :=
 endif
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 e786691..e0f1ad4 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -57,7 +57,7 @@
 
 # Create symlink in the app specific lib path
 # Skip creating this symlink when running the second part of a target sanitization build.
-ifndef SANITIZE_TARGET
+ifeq ($(filter address,$(SANITIZE_TARGET)),)
 ifdef LOCAL_POST_INSTALL_CMD
 # Add a shell command separator
 LOCAL_POST_INSTALL_CMD += ;
diff --git a/core/jacoco.mk b/core/jacoco.mk
index 6406df4..148bb04 100644
--- a/core/jacoco.mk
+++ b/core/jacoco.mk
@@ -51,7 +51,7 @@
 	  -d $(PRIVATE_UNZIPPED_PATH) \
 	  $(PRIVATE_INCLUDE_ARGS)
 	(cd $(PRIVATE_UNZIPPED_PATH) && rm -rf $(PRIVATE_EXCLUDE_ARGS))
-	(cd $(PRIVATE_UNZIPPED_PATH) && find -not -name "*.class" -type f | xargs --no-run-if-empty rm)
+	(cd $(PRIVATE_UNZIPPED_PATH) && find -not -name "*.class" -type f -exec rm {} \;)
 	touch $(PRIVATE_UNZIPPED_TIMESTAMP_PATH)
 # Unfortunately in the previous task above,
 # 'rm -rf $(PRIVATE_EXCLUDE_ARGS)' needs to be a separate
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_common.mk b/core/java_common.mk
index ac26e5e..f5da120 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -280,7 +280,7 @@
       sdk_libs := $(foreach lib_name,$(LOCAL_SDK_LIBRARIES),$(call resolve-prebuilt-sdk-module,system_current,$(lib_name)))
     else
       # When SDK libraries are referenced from modules built without SDK, provide the all APIs to them
-      sdk_libs := $(foreach lib_name,$(LOCAL_SDK_LIBRARIES),$(lib_name).impl)
+      sdk_libs := $(foreach lib_name,$(LOCAL_SDK_LIBRARIES),$(lib_name))
     endif
   else
     ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
@@ -386,6 +386,7 @@
   endif # USE_CORE_LIB_BOOTCLASSPATH
 endif # !LOCAL_IS_HOST_MODULE
 
+ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) $(full_java_bootclasspath_libs)
 
 # Export the SDK libs. The sdk library names listed in LOCAL_SDK_LIBRARIES are first exported.
 # Then sdk library names exported from dependencies are all re-exported.
diff --git a/core/java_library.mk b/core/java_library.mk
index 3e54b0e..c706cea 100644
--- a/core/java_library.mk
+++ b/core/java_library.mk
@@ -85,23 +85,14 @@
 .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
-$(LOCAL_BUILT_MODULE): | $(DEXPREOPT_GEN_DEPS)
+$(LOCAL_BUILT_MODULE): | $(DEXPREOPT_STRIP_DEPS)
 $(LOCAL_BUILT_MODULE): .KATI_DEPFILE := $(LOCAL_BUILT_MODULE).d
 $(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/java_renderscript.mk b/core/java_renderscript.mk
index 406d679..13a6f8e 100644
--- a/core/java_renderscript.mk
+++ b/core/java_renderscript.mk
@@ -82,8 +82,8 @@
 $(rs_generated_src_jar): $(renderscript_sources_fullpath) $(LOCAL_RENDERSCRIPT_CC) $(SOONG_ZIP)
 	$(transform-renderscripts-to-java-and-bc)
 
-# include the dependency files (.d/.P) generated by llvm-rs-cc.
-$(call include-depfile,$(rs_generated_src_jar).P,$(rs_generated_src_jar))
+# include the dependency files (.d) generated by llvm-rs-cc.
+$(call include-depfile,$(rs_generated_src_jar).d,$(rs_generated_src_jar))
 
 ifneq ($(LOCAL_RENDERSCRIPT_COMPATIBILITY),)
 
diff --git a/core/local_systemsdk.mk b/core/local_systemsdk.mk
index 7acb57a..0f1271f 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,$(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 9fd1c35..605b265 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -80,7 +80,7 @@
 ifeq ($(strip $(HAS_BUILD_NUMBER)),false)
   # BUILD_NUMBER has a timestamp in it, which means that
   # it will change every time.  Pick a stable value.
-  FILE_NAME_TAG := eng.$(USER)
+  FILE_NAME_TAG := eng.$(BUILD_USERNAME)
 else
   FILE_NAME_TAG := $(file <$(BUILD_NUMBER_FILE))
 endif
@@ -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))
@@ -583,6 +577,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;
@@ -786,9 +796,43 @@
 $(call resolve-shared-libs-depes,HOST_CROSS_,,true)
 endif
 
+# Pass the shared libraries dependencies to prebuilt ELF file check.
+define add-elf-file-check-shared-lib
+$(1): PRIVATE_SHARED_LIBRARY_FILES += $(2)
+$(1): $(2)
+endef
+
+define resolve-shared-libs-for-elf-file-check
+$(foreach m,$($(if $(2),$($(1)2ND_ARCH_VAR_PREFIX))$(1)DEPENDENCIES_ON_SHARED_LIBRARIES),\
+  $(eval p := $(subst :,$(space),$(m)))\
+  $(eval mod := $(firstword $(p)))\
+  \
+  $(eval deps := $(subst $(comma),$(space),$(lastword $(p))))\
+  $(if $(2),$(eval deps := $(addsuffix $($(1)2ND_ARCH_MODULE_SUFFIX),$(deps))))\
+  $(eval root := $(1)OUT$(if $(call streq,$(1),TARGET_),_ROOT))\
+  $(eval deps := $(filter $($(root))/%$($(1)SHLIB_SUFFIX),$(call module-built-files,$(deps))))\
+  \
+  $(eval r := $(firstword $(filter \
+    $($(if $(2),$($(1)2ND_ARCH_VAR_PREFIX))TARGET_OUT_INTERMEDIATES)/EXECUTABLES/%\
+    $($(if $(2),$($(1)2ND_ARCH_VAR_PREFIX))TARGET_OUT_INTERMEDIATES)/NATIVE_TESTS/%\
+    $($(if $(2),$($(1)2ND_ARCH_VAR_PREFIX))TARGET_OUT_INTERMEDIATES)/SHARED_LIBRARIES/%,\
+    $(call module-built-files,$(mod)))))\
+  \
+  $(if $(r),\
+    $(eval stamp := $(dir $(r))check_elf_files.timestamp)\
+    $(eval $(call add-elf-file-check-shared-lib,$(stamp),$(deps)))\
+  ))
+endef
+
+$(call resolve-shared-libs-for-elf-file-check,TARGET_)
+ifdef TARGET_2ND_ARCH
+$(call resolve-shared-libs-for-elf-file-check,TARGET_,true)
+endif
+
 m :=
 r :=
 p :=
+stamp :=
 deps :=
 add-required-deps :=
 
@@ -996,6 +1040,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
@@ -1007,6 +1061,16 @@
           $(foreach p,$(1),$(call append-path,$(PRODUCT_OUT),$(p)$(2)))))))
 endef
 
+# Returns modules included automatically as a result of certain BoardConfig
+# variables being set.
+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
+
 # Lists most of the files a particular product installs, including:
 # - PRODUCT_PACKAGES, and their LOCAL_REQUIRED_MODULES
 # - PRODUCT_COPY_FILES
@@ -1030,7 +1094,7 @@
     $(if $(filter debug,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_DEBUG)) \
     $(if $(filter tests,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_TESTS)) \
     $(if $(filter asan,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_DEBUG_ASAN)) \
-    $(if $(BOARD_VNDK_VERSION),vndk_package) \
+    $(call auto-included-modules) \
   ) \
   $(eval ### Filter out the overridden packages and executables before doing expansion) \
   $(eval _pif_overrides := $(call module-overrides,$(_pif_modules))) \
@@ -1051,6 +1115,23 @@
     $(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
@@ -1078,17 +1159,57 @@
 endif
 
 ifdef FULL_BUILD
-  product_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
+  # Check to ensure that all modules in PRODUCT_HOST_PACKAGES exist
+  #
+  # Many host modules are Linux-only, so skip this check on Mac. If we ever have Mac-only modules,
+  # maybe it would make sense to have PRODUCT_HOST_PACKAGES_LINUX/_DARWIN?
+  ifneq ($(HOST_OS),darwin)
+    ifneq (true,$(ALLOW_MISSING_DEPENDENCIES))
+      _modules := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_HOST_PACKAGES)
+      _nonexistant_modules := $(foreach m,$(_modules),\
+        $(if $(filter FAKE,$(ALL_MODULES.$(m).CLASS))$(filter $(HOST_OUT_ROOT)/%,$(ALL_MODULES.$(m).INSTALLED)),,$(m)))
+      $(call maybe-print-list-and-error,$(_nonexistant_modules),\
+        $(INTERNAL_PRODUCT) includes non-existant modules in PRODUCT_HOST_PACKAGES)
+    endif
+  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)
 
+  # Verify that PRODUCT_HOST_PACKAGES is complete
+  # This is a temporary requirement during migration
+  # Ignore libraries, since they shouldn't need to be in PRODUCT_PACKAGES for the most part anyway.
+  host_files_in_target_FILES := $(filter-out \
+    $(HOST_OUT_SHARED_LIBRARIES)/% \
+    $($(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)/%,\
+      $(filter $(HOST_OUT_ROOT)/%,$(product_target_FILES)))
+  ifneq (,$(filter-out $(product_host_FILES),$(host_files_in_target_FILES)))
+    packages := $(foreach f,$(filter-out $(product_host_FILES),$(host_files_in_target_FILES)), \
+      $(or $(INSTALLABLE_FILES.$(f).MODULE),$(f)))
+    $(warning Missing modules from PRODUCT_HOST_PACKAGES)
+    $(warning See $(CHANGES_URL)#PRODUCT_HOST_PACKAGES for more information)
+    $(foreach f,$(sort $(packages)),$(warning _ $(f)))
+    $(error stop)
+  endif
+  host_files_in_target_FILES :=
+
   # Verify the artifact path requirements made by included products.
   is_asan := $(if $(filter address,$(SANITIZE_TARGET)),true)
   ifneq (true,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS)))
-  # Fakes don't get installed, and host files are irrelevant.
-  static_whitelist_patterns := $(TARGET_OUT_FAKE)/% $(HOST_OUT)/%
+  # 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
+  # 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.
+  # The path can be considered as a fake path, as the shared libraries
+  # are installed there just to have symbols files for them under
+  # $(PRODUCT_OUT)/symbols/apex for debugging purpose. The /apex directory
+  # is never compiled into a filesystem image.
+  static_whitelist_patterns += $(PRODUCT_OUT)/apex/%
   ifeq (true,$(BOARD_USES_SYSTEM_OTHER_ODEX))
     # Allow system_other odex space optimization.
     static_whitelist_patterns += \
@@ -1096,6 +1217,13 @@
       $(TARGET_OUT_SYSTEM_OTHER)/%.vdex \
       $(TARGET_OUT_SYSTEM_OTHER)/%.art
   endif
+
+CERTIFICATE_VIOLATION_MODULES_FILENAME := $(PRODUCT_OUT)/certificate_violation_modules.txt
+$(CERTIFICATE_VIOLATION_MODULES_FILENAME):
+	rm -f $@
+	$(foreach m,$(sort $(CERTIFICATE_VIOLATION_MODULES)), echo $(m) >> $@;)
+$(call dist-for-goals,droidcore,$(CERTIFICATE_VIOLATION_MODULES_FILENAME))
+
   all_offending_files :=
   $(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
     $(eval requirements := $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENTS)) \
@@ -1109,7 +1237,7 @@
     $(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)) \
@@ -1134,14 +1262,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) \
   )
@@ -1298,8 +1428,8 @@
 
 # Build files and then package it into the rom formats
 .PHONY: droidcore
-droidcore: files \
-    systemimage \
+droidcore: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \
+    $(INSTALLED_SYSTEMIMAGE_TARGET) \
     $(INSTALLED_RAMDISK_TARGET) \
     $(INSTALLED_BOOTIMAGE_TARGET) \
     $(INSTALLED_RECOVERYIMAGE_TARGET) \
@@ -1330,6 +1460,8 @@
     $(INSTALLED_FILES_JSON_ROOT) \
     $(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.
@@ -1395,6 +1527,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) \
@@ -1449,17 +1582,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
@@ -1518,8 +1655,18 @@
 .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:
 
 #xxx scrape this from ALL_MODULE_NAME_TAGS
 .PHONY: modules
@@ -1528,15 +1675,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..4750649 100644
--- a/core/native_benchmark.mk
+++ b/core/native_benchmark.mk
@@ -6,8 +6,10 @@
 
 LOCAL_STATIC_LIBRARIES += libgoogle-benchmark
 
+ifndef ENABLE_DEFAULT_TEST_LOCATION
 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)
+endif
 
 ifndef LOCAL_MULTILIB
 ifndef LOCAL_32_BIT_ONLY
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 a46d76a..3be4635 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -87,6 +87,23 @@
   LOCAL_RESOURCE_DIR := $(foreach d,$(LOCAL_RESOURCE_DIR),$(call clean-path,$(d)))
 endif
 
+# If LOCAL_MODULE matches a rule in PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES,
+# override the manifest package name by the (first) rule matched
+override_manifest_name := $(strip $(word 1,\
+  $(foreach rule,$(PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES),\
+    $(eval _pkg_name_pat := $(call word-colon,1,$(rule)))\
+    $(eval _manifest_name_pat := $(call word-colon,2,$(rule)))\
+    $(if $(filter $(_pkg_name_pat),$(LOCAL_MODULE)),\
+      $(patsubst $(_pkg_name_pat),$(_manifest_name_pat),$(LOCAL_MODULE))\
+     )\
+   )\
+))
+
+ifneq (,$(override_manifest_name))
+# Note: this can override LOCAL_MANIFEST_PACKAGE_NAME value set in Android.mk
+LOCAL_MANIFEST_PACKAGE_NAME := $(override_manifest_name)
+endif
+
 include $(BUILD_SYSTEM)/force_aapt2.mk
 
 # Process Support Library dependencies.
@@ -309,29 +326,18 @@
 
 rs_compatibility_jni_libs :=
 
-ifeq ($(LOCAL_DATA_BINDING),true)
-data_binding_intermediates := $(intermediates.COMMON)/data-binding
-
-LOCAL_JAVACFLAGS += -processorpath $(DATA_BINDING_COMPILER) -s $(data_binding_intermediates)/anno-src
-
-LOCAL_STATIC_JAVA_LIBRARIES += databinding-baselibrary
-LOCAL_STATIC_JAVA_AAR_LIBRARIES += databinding-library databinding-adapters
-
-data_binding_res_in := $(LOCAL_RESOURCE_DIR)
-data_binding_res_out := $(data_binding_intermediates)/res
-
-# Replace with the processed merged res dir.
-LOCAL_RESOURCE_DIR := $(data_binding_res_out)
-
-LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.android.databinding.library
-endif  # LOCAL_DATA_BINDING
-
 # 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
 
+# 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 :=
@@ -460,34 +466,6 @@
 $(LOCAL_INTERMEDIATE_TARGETS): \
     PRIVATE_ANDROID_MANIFEST := $(full_android_manifest)
 
-ifeq ($(LOCAL_DATA_BINDING),true)
-data_binding_stamp := $(data_binding_intermediates)/data-binding.stamp
-$(data_binding_stamp): PRIVATE_INTERMEDIATES := $(data_binding_intermediates)
-$(data_binding_stamp): PRIVATE_MANIFEST := $(full_android_manifest)
-# Generate code into $(LOCAL_INTERMEDIATE_SOURCE_DIR) so that the generated .java files
-# will be automatically picked up by function compile-java.
-$(data_binding_stamp): PRIVATE_SRC_OUT := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/data-binding
-$(data_binding_stamp): PRIVATE_XML_OUT := $(data_binding_intermediates)/xml
-$(data_binding_stamp): PRIVATE_RES_OUT := $(data_binding_res_out)
-$(data_binding_stamp): PRIVATE_RES_IN := $(data_binding_res_in)
-$(data_binding_stamp): PRIVATE_ANNO_SRC_DIR := $(data_binding_intermediates)/anno-src
-
-$(data_binding_stamp) : $(all_res_assets) $(full_android_manifest) \
-    $(DATA_BINDING_COMPILER)
-	@echo "Data-binding process: $@"
-	@rm -rf $(PRIVATE_INTERMEDIATES) $(PRIVATE_SRC_OUT) && \
-	  mkdir -p $(PRIVATE_INTERMEDIATES) $(PRIVATE_SRC_OUT) \
-	      $(PRIVATE_XML_OUT) $(PRIVATE_RES_OUT) $(PRIVATE_ANNO_SRC_DIR)
-	$(hide) $(JAVA) -classpath $(DATA_BINDING_COMPILER) android.databinding.tool.MakeCopy \
-	  $(PRIVATE_MANIFEST) $(PRIVATE_SRC_OUT) $(PRIVATE_XML_OUT) $(PRIVATE_RES_OUT) $(PRIVATE_RES_IN)
-	$(hide) touch $@
-
-# Make sure the data-binding process happens before javac and generation of R.java.
-$(R_file_stamp): $(data_binding_stamp)
-$(java_source_list_file): $(data_binding_stamp)
-$(full_classes_compiled_jar): $(data_binding_stamp)
-endif  # LOCAL_DATA_BINDING
-
 framework_res_package_export :=
 
 ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
@@ -563,6 +541,7 @@
 ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)
     LOCAL_CERTIFICATE := $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))$(LOCAL_CERTIFICATE)
 endif
+include $(BUILD_SYSTEM)/app_certificate_validate.mk
 private_key := $(LOCAL_CERTIFICATE).pk8
 certificate := $(LOCAL_CERTIFICATE).x509.pem
 additional_certificates := $(foreach c,$(LOCAL_ADDITIONAL_CERTIFICATES), $(c).x509.pem $(c).pk8)
@@ -601,13 +580,13 @@
 # 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,$(filter true, \
-   $(LOCAL_PRODUCT_MODULE) $(LOCAL_PRODUCT_SERVICES_MODULE) \
-   $(LOCAL_VENDOR_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
+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)
@@ -636,9 +615,10 @@
 ifdef LOCAL_DEX_PREOPT
 $(LOCAL_BUILT_MODULE) : PRIVATE_STRIP_SCRIPT := $(intermediates)/strip.sh
 $(LOCAL_BUILT_MODULE) : $(intermediates)/strip.sh
-$(LOCAL_BUILT_MODULE) : | $(DEXPREOPT_GEN_DEPS)
+$(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
@@ -649,7 +629,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.
@@ -678,8 +658,8 @@
 	@# Keep a copy of apk with classes.dex unstripped
 	$(hide) cp -f $@ $(dir $@)package.dex.apk
 endif  # BUILD_PLATFORM_ZIP
-	$(PRIVATE_STRIP_SCRIPT) $@ $@.tmp
-	mv -f $@.tmp $@
+	mv -f $@ $@.tmp
+	$(PRIVATE_STRIP_SCRIPT) $@.tmp $@
 endif  # LOCAL_DEX_PREOPT
 	$(sign-package)
 ifdef LOCAL_COMPRESSED_MODULE
@@ -788,10 +768,17 @@
 
 ifdef LOCAL_COMPATIBILITY_SUITE
 
+ifndef ENABLE_DEFAULT_TEST_LOCATION
 $(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))))
+else
+$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+  $(eval my_compat_dist_$(suite) := $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
+    $(foreach s,$(my_split_suffixes),\
+      $(call compat-copy-pair,$(intermediates)/package_$(s).apk,$(dir)/$(LOCAL_MODULE)_$(s).apk)))))
+endif
 
 $(call create-suite-dependencies)
 
diff --git a/core/pdk_config.mk b/core/pdk_config.mk
index b2c9e9e..ce78ece 100644
--- a/core/pdk_config.mk
+++ b/core/pdk_config.mk
@@ -20,9 +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/core-simple_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 013497f..e505945 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -39,6 +39,13 @@
 
 LOCAL_CHECKED_MODULE := $(my_prebuilt_src_file)
 
+ifeq (APPS,$(LOCAL_MODULE_CLASS))
+include $(BUILD_SYSTEM)/app_prebuilt_internal.mk
+else
+#
+# Non-APPS prebuilt modules handling almost to the end of the file
+#
+
 my_strip_module := $(firstword \
   $(LOCAL_STRIP_MODULE_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) \
   $(LOCAL_STRIP_MODULE))
@@ -69,44 +76,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,$(filter true, \
-   $(LOCAL_PRODUCT_MODULE) $(LOCAL_PRODUCT_SERVICES_MODULE) \
-   $(LOCAL_VENDOR_MODULE) $(LOCAL_PROPRIETARY_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
@@ -123,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)
@@ -173,8 +153,26 @@
 # 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
@@ -184,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))
@@ -218,254 +219,27 @@
 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
-
-# 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
-ifdef LOCAL_DEX_PREOPT
-$(built_module) : PRIVATE_STRIP_SCRIPT := $(intermediates)/strip.sh
-$(built_module) : $(intermediates)/strip.sh
-$(built_module) : | $(DEXPREOPT_GEN_DEPS)
-$(built_module) : .KATI_DEPFILE := $(built_module).d
-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
-	$(PRIVATE_STRIP_SCRIPT) $@ $@.tmp
-	mv -f $@.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
-$(built_module): | $(DEXPREOPT_GEN_DEPS)
+$(built_module): | $(DEXPREOPT_STRIP_DEPS)
 $(built_module): .KATI_DEPFILE := $(built_module).d
 $(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)
@@ -672,6 +446,8 @@
 
 endif # JAVA_LIBRARIES
 
+endif # APPS
+
 $(built_module) : $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
 my_prebuilt_src_file :=
diff --git a/core/product.mk b/core/product.mk
index 8497b28..a367a6b 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
@@ -117,6 +117,7 @@
     PRODUCT_AAPT_CONFIG \
     PRODUCT_AAPT_PREF_CONFIG \
     PRODUCT_AAPT_PREBUILT_DPI \
+    PRODUCT_HOST_PACKAGES \
     PRODUCT_PACKAGES \
     PRODUCT_PACKAGES_DEBUG \
     PRODUCT_PACKAGES_DEBUG_ASAN \
@@ -180,6 +181,7 @@
     PRODUCT_DEX_PREOPT_PROFILE_DIR \
     PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION \
     PRODUCT_DEX_PREOPT_GENERATE_DM_FILES \
+    PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING \
     PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE \
     PRODUCT_SYSTEM_SERVER_COMPILER_FILTER \
     PRODUCT_SANITIZER_MODULE_CONFIGS \
@@ -201,9 +203,12 @@
     PRODUCT_ADB_KEYS \
     PRODUCT_CFI_INCLUDE_PATHS \
     PRODUCT_CFI_EXCLUDE_PATHS \
+    PRODUCT_DISABLE_SCUDO \
     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_USE_DYNAMIC_PARTITION_SIZE \
@@ -213,12 +218,27 @@
     PRODUCT_RETROFIT_DYNAMIC_PARTITIONS \
     PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS \
     PRODUCT_XOM_EXCLUDE_PATHS \
+    PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES \
+    PRODUCT_PACKAGE_NAME_OVERRIDES \
+    PRODUCT_CERTIFICATE_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 \
 
 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
@@ -347,82 +367,18 @@
 $(strip $(call _resolve-short-product-name,$(1)))
 endef
 
-
-_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 \
-
-
-_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)
+_product_stash_var_list := $(_product_var_list)
+# TODO: Move this to board_config.mk when no longer set in product makefiles
+_product_stash_var_list += WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
+_product_strip_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)) \
+  $(eval $(v) ?=) \
+  $(eval .KATI_READONLY := $(v)) \
  )
 endef
 
diff --git a/core/product_config.mk b/core/product_config.mk
index f0f7da1..cff42db 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.
 #
@@ -253,6 +257,8 @@
 
 # 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))
@@ -346,6 +352,7 @@
 # used for adding properties to default.prop
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
+
 .KATI_READONLY := PRODUCT_DEFAULT_PROPERTY_OVERRIDES
 
 # A list of property assignments, like "key = value", with zero or more
@@ -362,6 +369,11 @@
     $(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 '='.
@@ -400,6 +412,8 @@
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
 PRODUCT_DEX_PREOPT_PROFILE_DIR := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_PROFILE_DIR))
+PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING := \
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING))
 
 # Boot image options.
 PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE := \
@@ -465,6 +479,11 @@
 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))
@@ -495,6 +514,10 @@
 PRODUCT_CFI_INCLUDE_PATHS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_INCLUDE_PATHS))
 
+# Whether the Scudo hardened allocator is disabled platform-wide
+PRODUCT_DISABLE_SCUDO := \
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DISABLE_SCUDO))
+
 # 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))
@@ -549,3 +572,41 @@
 # 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
+PRODUCT_$(1)_OVERRIDES := $$(strip $$(PRODUCTS.$$(INTERNAL_PRODUCT).PRODUCT_$(1)_OVERRIDES))
+.KATI_READONLY := PRODUCT_$(1)_OVERRIDES
+$$(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
+
+$(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
+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
+endef
+
+# Copy and check the value of each PRODUCT_BUILD_*_IMAGE variable
+$(foreach image, \
+    SYSTEM \
+    SYSTEM_OTHER \
+    VENDOR \
+    PRODUCT \
+    PRODUCT_SERVICES \
+    ODM \
+    CACHE \
+    RAMDISK \
+    USERDATA, \
+  $(eval $(call product-build-image-config,$(image))))
+
+product-build-image-config :=
diff --git a/core/proguard_basic_keeps.flags b/core/proguard_basic_keeps.flags
index 4de5221..3c25e89 100644
--- a/core/proguard_basic_keeps.flags
+++ b/core/proguard_basic_keeps.flags
@@ -1,7 +1,3 @@
-# see http://sourceforge.net/tracker/?func=detail&aid=2787465&group_id=54750&atid=474707
--optimizations !code/simplification/arithmetic
--optimizations !code/simplification/cast
-
 # To prevent name conflict in incremental obfuscation.
 -useuniqueclassmembernames
 
diff --git a/core/python_binary_host_test_config_template.xml b/core/python_binary_host_test_config_template.xml
new file mode 100644
index 0000000..0f63953
--- /dev/null
+++ b/core/python_binary_host_test_config_template.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config to run {MODULE} unittests">
+    <test class="com.android.tradefed.testtype.python.PythonBinaryHostTest" >
+        <option name="par-file-name" value="{MODULE}" />
+        <option name="test-timeout" value="5m" />
+    </test>
+</configuration>
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index 73d934b..a9169eb 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -19,16 +19,52 @@
 LOCAL_MODULE_SUFFIX := .apk
 LOCAL_BUILT_MODULE_STEM := package.apk
 
-#######################################
-include $(BUILD_SYSTEM)/base_rules.mk
-#######################################
+intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
 full_classes_jar := $(intermediates.COMMON)/classes.jar
 full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
 full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
 
-$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
-$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
+ifdef LOCAL_SOONG_CLASSES_JAR
+  $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
+  $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
+  $(eval $(call add-dependency,$(LOCAL_BUILT_MODULE),$(full_classes_jar)))
+
+  ifneq ($(TURBINE_ENABLED),false)
+    ifdef LOCAL_SOONG_HEADER_JAR
+      $(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
+    else
+      $(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
+    endif
+  endif # TURBINE_ENABLED != false
+endif
+
+# Run veridex on product, product_services and vendor modules.
+# We skip it for unbundled app builds where we cannot build veridex.
+module_run_appcompat :=
+ifeq (true,$(non_system_module))
+ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))  # ! unbundled app build
+ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
+  module_run_appcompat := true
+endif
+endif
+endif
+
+ifeq ($(module_run_appcompat),true)
+  $(LOCAL_BUILT_MODULE): $(appcompat-files)
+  $(LOCAL_BUILT_MODULE): PRIVATE_INSTALLED_MODULE := $(LOCAL_INSTALLED_MODULE)
+  $(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE)
+	@echo "Copy: $@"
+	$(copy-file-to-target)
+	$(call appcompat-header, aapt2)
+	$(run-appcompat)
+else
+  $(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
+endif
 
 ifdef LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
   $(eval $(call copy-one-file,$(LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR),\
@@ -44,15 +80,6 @@
     $(intermediates.COMMON)/proguard_dictionary)
 endif
 
-ifneq ($(TURBINE_ENABLED),false)
-ifdef LOCAL_SOONG_HEADER_JAR
-$(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
-else
-$(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
-endif
-endif # TURBINE_ENABLED != false
-
-
 ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
 resource_export_package := $(intermediates.COMMON)/package-export.apk
 resource_export_stamp := $(intermediates.COMMON)/src/R.stamp
@@ -60,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))
@@ -74,14 +101,12 @@
   $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(dir $(LOCAL_BUILT_MODULE))package.dex.apk))
 endif
 
-$(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
-
 my_built_installed := $(foreach f,$(LOCAL_SOONG_BUILT_INSTALLED),\
   $(call word-colon,1,$(f)):$(PRODUCT_OUT)$(call word-colon,2,$(f)))
 my_installed := $(call copy-many-files, $(my_built_installed))
 ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed)
 ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(my_built_installed)
-$(my_register_name): $(my_installed)
+$(my_all_targets): $(my_installed)
 
 # embedded JNI will already have been handled by soong
 my_embed_jni :=
@@ -108,7 +133,7 @@
   PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE)
   PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(patsubst %.x509.pem,%.pk8,$(LOCAL_CERTIFICATE))
 endif
-
+include $(BUILD_SYSTEM)/app_certificate_validate.mk
 PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 
 ifdef LOCAL_SOONG_BUNDLE
@@ -139,7 +164,7 @@
       $(my_register_name), \
       false, \
       $(LOCAL_FULL_MANIFEST_FILE), \
-      $(LOCAL_EXPORT_PACKAGE_RESOURCES), \
+      $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
       $(LOCAL_SOONG_RRO_DIRS))
 endif
 
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index 088b076..8d248af 100644
--- a/core/soong_cc_prebuilt.mk
+++ b/core/soong_cc_prebuilt.mk
@@ -93,6 +93,12 @@
   name_without_suffix :=
 endif
 
+# Check prebuilt ELF binaries.
+ifneq ($(LOCAL_CHECK_ELF_FILES),)
+my_prebuilt_src_file := $(LOCAL_PREBUILT_MODULE_FILE)
+include $(BUILD_SYSTEM)/check_elf_file.mk
+endif
+
 # 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
@@ -115,14 +121,17 @@
 
 ifndef LOCAL_IS_HOST_MODULE
   ifdef LOCAL_SOONG_UNSTRIPPED_BINARY
+    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_module_path))
+    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))
+      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) ($@)"
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 85be1e7..3c82e88 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -83,10 +83,12 @@
 $(call add_json_bool, EnableCFI,                         $(call invert_bool,$(filter false,$(ENABLE_CFI))))
 $(call add_json_list, CFIExcludePaths,                   $(CFI_EXCLUDE_PATHS) $(PRODUCT_CFI_EXCLUDE_PATHS))
 $(call add_json_list, CFIIncludePaths,                   $(CFI_INCLUDE_PATHS) $(PRODUCT_CFI_INCLUDE_PATHS))
-$(call add_json_bool, EnableXOM,                         $(filter true,$(ENABLE_XOM)))
+$(call add_json_bool, EnableXOM,                         $(call invert_bool,$(filter false,$(ENABLE_XOM))))
 $(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))
 
@@ -111,15 +113,15 @@
 $(call add_json_bool, UncompressPrivAppDex,              $(call invert_bool,$(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS))))
 $(call add_json_list, ModulesLoadedByPrivilegedModules,  $(PRODUCT_LOADED_BY_PRIVILEGED_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_list, BootJars,                          $(PRODUCT_BOOT_JARS))
 
 $(call add_json_bool, Product_is_iot,                    $(filter true,$(PRODUCT_IOT)))
 
 $(call add_json_bool, Treble_linker_namespaces,          $(filter true,$(PRODUCT_TREBLE_LINKER_NAMESPACES)))
 $(call add_json_bool, Enforce_vintf_manifest,            $(filter true,$(PRODUCT_ENFORCE_VINTF_MANIFEST)))
 
+$(call add_json_bool, Check_elf_files,                   $(filter true,$(PRODUCT_CHECK_ELF_FILES)))
+
 $(call add_json_bool, Uml,                               $(filter true,$(TARGET_USER_MODE_LINUX)))
 $(call add_json_bool, Use_lmkd_stats_log,                $(filter true,$(TARGET_LMKD_STATS_LOG)))
 $(call add_json_str,  VendorPath,                        $(TARGET_COPY_OUT_VENDOR))
@@ -144,6 +146,17 @@
 
 $(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_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),\
   $(call add_json_map, $(namespace))\
diff --git a/core/soong_droiddoc_prebuilt.mk b/core/soong_droiddoc_prebuilt.mk
index 08df019..bf1f10b 100644
--- a/core/soong_droiddoc_prebuilt.mk
+++ b/core/soong_droiddoc_prebuilt.mk
@@ -16,8 +16,9 @@
 $(eval $(call copy-one-file,$(LOCAL_DROIDDOC_DOC_ZIP),$(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip))
 $(call dist-for-goals,docs,$(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip)
 
-.PHONY: $(LOCAL_MODULE)-docs.zip
-$(LOCAL_MODULE)-docs.zip : $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
+.PHONY: $(LOCAL_MODULE) $(LOCAL_MODULE)-docs.zip
+$(LOCAL_MODULE) $(LOCAL_MODULE)-docs.zip : $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
+ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
 endif
 
 ifdef LOCAL_DROIDDOC_ANNOTATIONS_ZIP
@@ -34,6 +35,6 @@
 
 ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip
 
-.PHONY: $(LOCAL_MODULE)-jdiff
-$(LOCAL_MODULE)-jdiff : $(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip
+.PHONY: $(LOCAL_MODULE) $(LOCAL_MODULE)-jdiff
+$(LOCAL_MODULE) $(LOCAL_MODULE)-jdiff : $(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip
 endif
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index a62590d..9692a99 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -13,19 +13,36 @@
 LOCAL_MODULE_SUFFIX := .jar
 LOCAL_BUILT_MODULE_STEM := javalib.jar
 
-#######################################
-include $(BUILD_SYSTEM)/base_rules.mk
-#######################################
+intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
 full_classes_jar := $(intermediates.COMMON)/classes.jar
 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
 
-$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
-$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
+ifdef LOCAL_SOONG_AAR
+  LOCAL_ADDITIONAL_CHECKED_MODULE += $(LOCAL_SOONG_AAR)
+endif
+
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
+ifdef LOCAL_SOONG_CLASSES_JAR
+  $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
+  $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
+  $(eval $(call add-dependency,$(LOCAL_BUILT_MODULE),$(full_classes_jar)))
+
+  ifneq ($(TURBINE_ENABLED),false)
+    ifdef LOCAL_SOONG_HEADER_JAR
+      $(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
+    else
+      $(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
+    endif
+  endif # TURBINE_ENABLED != false
+endif
+
+$(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
 
 ifdef LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
   $(eval $(call copy-one-file,$(LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR),\
@@ -64,64 +81,39 @@
   $(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_static_library_android_manifest))
 endif # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
 
-ifneq ($(TURBINE_ENABLED),false)
-ifdef LOCAL_SOONG_HEADER_JAR
-$(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
-else
-$(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
-endif
-endif # TURBINE_ENABLED != false
 
 ifdef LOCAL_SOONG_DEX_JAR
-  ifneq ($(LOCAL_UNINSTALLABLE_MODULE),true)
-    ifndef LOCAL_IS_HOST_MODULE
-      ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),)  # is_boot_jar
-        # Derive greylist from classes.jar.
-        # We use full_classes_jar here, which is the post-proguard jar (on the basis that we also
-        # have a full_classes_pre_proguard_jar). This is consistent with the equivalent code in
-        # java.mk.
-        $(eval $(call hiddenapi-generate-csv,$(full_classes_jar),$(hiddenapi_flags_csv),$(hiddenapi_metadata_csv)))
-        $(eval $(call hiddenapi-copy-soong-jar,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
+  ifndef LOCAL_IS_HOST_MODULE
+    ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),)  # is_boot_jar
+      ifeq (true,$(WITH_DEXPREOPT))
+        # For libart, the boot jars' odex files are replaced by $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE).
+        # We use this installed_odex trick to get boot.art installed.
+        installed_odex := $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)
+        # Append the odex for the 2nd arch if we have one.
+        installed_odex += $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)
+        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
 
-        ifeq (true,$(WITH_DEXPREOPT))
-          # For libart, the boot jars' odex files are replaced by $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE).
-          # We use this installed_odex trick to get boot.art installed.
-          installed_odex := $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)
-          # Append the odex for the 2nd arch if we have one.
-          installed_odex += $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)
-          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)
-        endif
-      else # !is_boot_jar
-        $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
-      endif # is_boot_jar
-      $(eval $(call add-dependency,$(common_javalib.jar),$(full_classes_jar) $(full_classes_header_jar)))
-
-      $(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
-      $(eval $(call add-dependency,$(LOCAL_BUILT_MODULE),$(common_javalib.jar)))
-    else # LOCAL_IS_HOST_MODULE
-      $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(LOCAL_BUILT_MODULE)))
-      $(eval $(call add-dependency,$(LOCAL_BUILT_MODULE),$(full_classes_jar) $(full_classes_header_jar)))
-    endif
-
-    java-dex : $(LOCAL_BUILT_MODULE)
-  else  # LOCAL_UNINSTALLABLE_MODULE
-
-    ifneq ($(filter $(LOCAL_MODULE),$(HIDDENAPI_EXTRA_APP_USAGE_JARS)),)
-      # Derive greylist from classes.jar.
-      # We use full_classes_jar here, which is the post-proguard jar (on the basis that we also
-      # have a full_classes_pre_proguard_jar). This is consistent with the equivalent code in
-      # java.mk.
-      $(eval $(call hiddenapi-generate-csv,$(full_classes_jar),$(hiddenapi_flags_csv),$(hiddenapi_metadata_csv)))
-    endif
-
-    $(eval $(call copy-one-file,$(full_classes_jar),$(LOCAL_BUILT_MODULE)))
     $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
-    java-dex : $(common_javalib.jar)
-  endif  # LOCAL_UNINSTALLABLE_MODULE
+    $(eval $(call add-dependency,$(LOCAL_BUILT_MODULE),$(common_javalib.jar)))
+    $(eval $(call add-dependency,$(common_javalib.jar),$(full_classes_jar)))
+    ifneq ($(TURBINE_ENABLED),false)
+      $(eval $(call add-dependency,$(common_javalib.jar),$(full_classes_header_jar)))
+    endif
+  endif
+
+  java-dex : $(LOCAL_BUILT_MODULE)
 else  # LOCAL_SOONG_DEX_JAR
-  $(eval $(call copy-one-file,$(full_classes_jar),$(LOCAL_BUILT_MODULE)))
+  ifndef LOCAL_UNINSTALLABLE_MODULE
+    ifndef LOCAL_IS_HOST_MODULE
+      $(call pretty-error,Installable device module must have LOCAL_SOONG_DEX_JAR set)
+    endif
+  endif
 endif  # LOCAL_SOONG_DEX_JAR
 
 my_built_installed := $(foreach f,$(LOCAL_SOONG_BUILT_INSTALLED),\
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..1ed1195 100644
--- a/core/target_test_internal.mk
+++ b/core/target_test_internal.mk
@@ -29,6 +29,15 @@
 $(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_64 when building test $(LOCAL_MODULE))
 endif
 
+use_testcase_folder := false
+ifdef ENABLE_DEFAULT_TEST_LOCATION
+  ifneq ($(LOCAL_MODULE),$(filter $(LOCAL_MODULE),$(DEFAULT_DATA_OUT_MODULES)))
+    use_testcase_folder := true
+  endif
+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/module-info.mk b/core/tasks/module-info.mk
index 9eb3ab3..2c56162 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -25,7 +25,7 @@
 # If ONE_SHOT_MAKEFILE is set, our view of the world is smaller, so don't
 # rewrite the file in that came.
 ifndef ONE_SHOT_MAKEFILE
-files: $(MODULE_INFO_JSON)
+droidcore: $(MODULE_INFO_JSON)
 endif
 
 $(call dist-for-goals, general-tests, $(MODULE_INFO_JSON))
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/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 0fd40db..6923698 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -252,7 +252,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 := 2018-12-05
+      PLATFORM_SECURITY_PATCH := 2019-03-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
@@ -314,7 +314,7 @@
   # If no BUILD_NUMBER is set, create a useful "I am an engineering build
   # from this date/time" value.  Make it start with a non-digit so that
   # anyone trying to parse it as an integer will probably get "0".
-  BUILD_NUMBER := eng.$(shell echo $${USER:0:6}).$(shell $(DATE) +%Y%m%d.%H%M%S)
+  BUILD_NUMBER := eng.$(shell echo $${BUILD_USERNAME:0:6}).$(shell $(DATE) +%Y%m%d.%H%M%S)
   HAS_BUILD_NUMBER := false
 endif
 .KATI_READONLY := BUILD_NUMBER HAS_BUILD_NUMBER
diff --git a/envsetup.sh b/envsetup.sh
index 62a64b6..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,44 +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 "$@"
-        ;;
-    *)
-        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/Android.mk b/target/Android.mk
deleted file mode 100644
index 9929b00..0000000
--- a/target/Android.mk
+++ /dev/null
@@ -1,23 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-# Only if this Android.mk was included not by a symlink should it be used.
-# This facilitates the transition away from symlinks: b/64397960
-ifeq ($(LOCAL_PATH),build/make/target)
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
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 38f79fd..3e8d342 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -20,15 +20,13 @@
 # the GLES renderer disables itself if host GL acceleration isn't available.
 USE_OPENGL_RENDERER := true
 
-TARGET_COPY_OUT_VENDOR := vendor
-
-# ~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
-BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
+
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 73af020..68d29c8 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -6,6 +6,9 @@
 
 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 :=
 
@@ -14,17 +17,32 @@
 # we explicit specify this need below (even though it's the current default).
 TARGET_USERIMAGES_SPARSE_EXT_DISABLED := false
 
+# system.img is always ext4 with sparse option
+# GSI also includes make_f2fs to support userdata parition in f2fs
+# for some devices
+TARGET_USERIMAGES_USE_F2FS := true
+
 # Enable dynamic system image size and reserved 64MB in it.
 BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE := 67108864
 
+# GSI forces product packages to /system for now.
+TARGET_COPY_OUT_PRODUCT := system/product
+
+# 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
@@ -32,16 +50,21 @@
 BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
 BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
 
+# 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
 
-# Android generic system image always create metadata partition
-BOARD_USES_METADATA_PARTITION := true
-
 # Set this to create /cache mount point for non-A/B devices that mounts /cache.
 # The partition size doesn't matter, just to make build pass.
 BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
 BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
+# 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 ec3c74f..e13317f 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -8,6 +8,10 @@
 
 TARGET_USERIMAGES_USE_EXT4 := true
 
+# Mainline devices must have /vendor and /product partitions.
+TARGET_COPY_OUT_VENDOR := vendor
+TARGET_COPY_OUT_PRODUCT := product
+
 # system-as-root is mandatory from Android P
 TARGET_NO_RECOVERY := true
 BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
@@ -17,6 +21,9 @@
 # Required flag for non-64 bit devices from P.
 TARGET_USES_64_BIT_BINDER := true
 
+# 64 bit mediadrmserver
+TARGET_ENABLE_MEDIADRM_64 := true
+
 # Puts odex files on system_other, as well as causing dex files not to get
 # stripped from APKs.
 BOARD_USES_SYSTEM_OTHER_ODEX := true
@@ -24,5 +31,11 @@
 # 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
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index 738c037..b61a7fd 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -16,31 +16,15 @@
 # arm emulator specific definitions
 TARGET_ARCH := arm
 
-# Note: Before Pi, we built the platform images for ARMv7-A _without_ NEON.
+# Note: Before P, we built the platform images for ARMv7-A _without_ NEON.
+# Note: Before Q, we built the CTS and SDK images for ARMv7-A _without_ NEON.
+# Note: Before Q, we built unbundled apps for ARMv7-A _without_ NEON.
 #
-ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk,$(MAKECMDGOALS)),)
-# DO NOT USE
-#
-# This architecture variant should NOT be used for 32 bit arm platform
-# builds. It is the lowest common denominator required to build
-# an unbundled application for all supported 32 platforms.
-# cts for 32 bit arm is built using aosp_arm64 product.
-#
-# If you are building a 32 bit platform (and not an application),
-# you should set the following as 2nd arch variant:
-#
-# TARGET_ARCH_VARIANT := armv7-a-neon
-#
-# DO NOT USE
-TARGET_ARCH_VARIANT := armv7-a
-# DO NOT USE
-else
 # Starting from Pi, System image of aosp_arm products is the new GSI
 # for real devices newly launched for Pi. These devices are usualy not
 # as performant as the mainstream 64-bit devices and the performance
 # provided by NEON is important for them to pass related CTS tests.
 TARGET_ARCH_VARIANT := armv7-a-neon
-endif
 TARGET_CPU_VARIANT := generic
 TARGET_CPU_ABI := armeabi-v7a
 TARGET_CPU_ABI2 := armeabi
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 1b6429c..3f83edb 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -23,7 +23,7 @@
 TARGET_2ND_CPU_ABI := armeabi-v7a
 TARGET_2ND_CPU_ABI2 := armeabi
 
-ifneq ($(TARGET_BUILD_APPS)$(filter cts vts sdk,$(MAKECMDGOALS)),)
+ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk vts,$(MAKECMDGOALS)),)
 # DO NOT USE
 # DO NOT USE
 #
@@ -41,7 +41,7 @@
 #
 # DO NOT USE
 # DO NOT USE
-TARGET_2ND_ARCH_VARIANT := armv7-a
+TARGET_2ND_ARCH_VARIANT := armv7-a-neon
 # DO NOT USE
 # DO NOT USE
 TARGET_2ND_CPU_VARIANT := generic
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
index 34a8ac0..68aedfc 100644
--- a/target/board/generic_arm64_a/BoardConfig.mk
+++ b/target/board/generic_arm64_a/BoardConfig.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_64.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_ARCH := arm64
 TARGET_ARCH_VARIANT := armv8-a
@@ -27,3 +27,6 @@
 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_arm64_ab/BoardConfig.mk b/target/board/generic_arm64_ab/BoardConfig.mk
index 88b90a8..6e54d81 100644
--- a/target/board/generic_arm64_ab/BoardConfig.mk
+++ b/target/board/generic_arm64_ab/BoardConfig.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_64.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_ARCH := arm64
 TARGET_ARCH_VARIANT := armv8-a
@@ -28,21 +28,12 @@
 TARGET_2ND_CPU_ABI2 := armeabi
 TARGET_2ND_CPU_VARIANT := generic
 
-# Enable A/B update
-TARGET_NO_RECOVERY := true
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
-
 # TODO(jiyong) These might be SoC specific.
 BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
 BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
 BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
 BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
 
-# Set this to create /cache mount point for non-A/B devices that mounts /cache.
-# The partition size doesn't matter, just to make build pass.
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
-
 # TODO(b/36764215): remove this setting when the generic system image
 # no longer has QCOM-specific directories under /.
 BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_arm_a/BoardConfig.mk b/target/board/generic_arm_a/BoardConfig.mk
index 57a5196..464a74f 100644
--- a/target/board/generic_arm_a/BoardConfig.mk
+++ b/target/board/generic_arm_a/BoardConfig.mk
@@ -14,10 +14,16 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_32.mk
+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_arm_ab/BoardConfig.mk b/target/board/generic_arm_ab/BoardConfig.mk
index 3d14842..9100094 100644
--- a/target/board/generic_arm_ab/BoardConfig.mk
+++ b/target/board/generic_arm_ab/BoardConfig.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_32.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_ARCH := arm
 TARGET_ARCH_VARIANT := armv7-a-neon
@@ -22,9 +22,8 @@
 TARGET_CPU_ABI2 := armeabi
 TARGET_CPU_VARIANT := generic
 
-# Enable A/B update
-TARGET_NO_RECOVERY := true
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
+# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
+TARGET_USES_64_BIT_BINDER := false
 
 # TODO(jiyong) These might be SoC specific.
 BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
@@ -32,11 +31,6 @@
 BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
 BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
 
-# Set this to create /cache mount point for non-A/B devices that mounts /cache.
-# The partition size doesn't matter, just to make build pass.
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
-
 # TODO(b/36764215): remove this setting when the generic system image
 # no longer has QCOM-specific directories under /.
 BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 0a32415..83cbd54 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,11 +14,15 @@
 # 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_PACKAGES += \
+	bios.bin \
+	vgabios-cirrus.bin \
+
+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..83cbd54 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -14,11 +14,15 @@
 # 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_PACKAGES += \
+	bios.bin \
+	vgabios-cirrus.bin \
+
+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
index 2c02604..07eef4f 100644
--- a/target/board/generic_x86_64_a/BoardConfig.mk
+++ b/target/board/generic_x86_64_a/BoardConfig.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_64.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_CPU_ABI := x86_64
 TARGET_ARCH := x86_64
@@ -23,3 +23,6 @@
 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/generic_x86_64_ab/BoardConfig.mk b/target/board/generic_x86_64_ab/BoardConfig.mk
index a098dfe..1dd5e48 100644
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/generic_x86_64_ab/BoardConfig.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_64.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_CPU_ABI := x86_64
 TARGET_ARCH := x86_64
@@ -23,12 +23,3 @@
 TARGET_2ND_CPU_ABI := x86
 TARGET_2ND_ARCH := x86
 TARGET_2ND_ARCH_VARIANT := x86_64
-
-# Set this to create /cache mount point for non-A/B devices that mounts /cache.
-# The partition size doesn't matter, just to make build pass.
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
-
-# Enable A/B update
-TARGET_NO_RECOVERY := true
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_x86_a/BoardConfig.mk b/target/board/generic_x86_a/BoardConfig.mk
index 67cb07d..e3e8a3a 100644
--- a/target/board/generic_x86_a/BoardConfig.mk
+++ b/target/board/generic_x86_a/BoardConfig.mk
@@ -14,8 +14,14 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_32.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_CPU_ABI := x86
 TARGET_ARCH := x86
 TARGET_ARCH_VARIANT := x86
+
+# 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_ab/BoardConfig.mk b/target/board/generic_x86_ab/BoardConfig.mk
index db4dacd..53acffd 100644
--- a/target/board/generic_x86_ab/BoardConfig.mk
+++ b/target/board/generic_x86_ab/BoardConfig.mk
@@ -14,17 +14,11 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common_32.mk
+include build/make/target/board/BoardConfigGsiCommon.mk
 
 TARGET_CPU_ABI := x86
 TARGET_ARCH := x86
 TARGET_ARCH_VARIANT := x86
 
-# Set this to create /cache mount point for non-A/B devices that mounts /cache.
-# The partition size doesn't matter, just to make build pass.
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
-
-# Enable A/B update
-TARGET_NO_RECOVERY := true
-BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
+# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
+TARGET_USES_64_BIT_BINDER := false
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index 8e70b25..ab2089d 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -21,7 +21,7 @@
 TARGET_2ND_ARCH := arm
 TARGET_2ND_CPU_ABI := armeabi-v7a
 TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_ARCH_VARIANT := armv7-a
+TARGET_2ND_ARCH_VARIANT := armv7-a-neon
 TARGET_2ND_CPU_VARIANT := generic
 
 TARGET_CPU_ABI_LIST := x86 armeabi-v7a armeabi
diff --git a/target/board/gsi_arm64/BoardConfig.mk b/target/board/gsi_arm64/BoardConfig.mk
new file mode 100644
index 0000000..90ddd0d
--- /dev/null
+++ b/target/board/gsi_arm64/BoardConfig.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 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
+
+# TODO(b/111434759, b/111287060) SoC specific hacks
+BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
+BOARD_ROOT_EXTRA_SYMLINKS += /mnt/vendor/persist:/persist
+BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt:/firmware
+
+# TODO(b/36764215): remove this setting when the generic system image
+# no longer has QCOM-specific directories under /.
+BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
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/treble_system.prop b/target/board/gsi_system_user.prop
similarity index 65%
rename from target/board/treble_system.prop
rename to target/board/gsi_system_user.prop
index 0c04a95..becb783 100644
--- a/target/board/treble_system.prop
+++ b/target/board/gsi_system_user.prop
@@ -1,8 +1,8 @@
 # GSI always generate dex pre-opt in system image
 ro.cp_system_other_odex=0
 
-# 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/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/board/treble_common.mk b/target/board/treble_common.mk
deleted file mode 100644
index eda5b37..0000000
--- a/target/board/treble_common.mk
+++ /dev/null
@@ -1,69 +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.
-#
-
-# Common boardconfig settings for generic AOSP products targetting mobile
-# (phone/table) devices.
-
-# VNDK
-BOARD_VNDK_VERSION := current
-
-# Properties
-TARGET_SYSTEM_PROP := build/make/target/board/treble_system.prop
-BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
-
-# Bootloader, kernel and recovery are not part of generic AOSP image
-TARGET_NO_BOOTLOADER := true
-TARGET_NO_KERNEL := true
-
-# system.img is always ext4 with sparse option
-# GSI also includes make_f2fs to support userdata parition in f2fs
-# for some devices
-TARGET_USERIMAGES_USE_EXT4 := true
-TARGET_USERIMAGES_USE_F2FS := true
-TARGET_USERIMAGES_SPARSE_EXT_DISABLED := false
-
-# Enable dynamic system image size and reserved 64MB in it.
-BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE := 67108864
-
-# Generic AOSP image always requires separate vendor.img
-TARGET_COPY_OUT_VENDOR := vendor
-
-# Android generic system image always create metadata partition
-BOARD_USES_METADATA_PARTITION := true
-
-# Set emulator framebuffer display device buffer count to 3
-NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
-
-# Audio
-USE_XML_AUDIO_POLICY_CONF := 1
-
-# Android Verified Boot (AVB):
-#   1) Sets BOARD_AVB_ENABLE to sign the GSI image.
-#   2) Sets AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED (--flag 2) in
-#      vbmeta.img to disable AVB verification.
-#
-# 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_ENABLE := true
-BOARD_AVB_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
-BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flag 2
-
-# Enable chain partition for system.
-BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
-BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
-BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
-BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
diff --git a/target/board/treble_common_64.mk b/target/board/treble_common_64.mk
deleted file mode 100644
index 8980dfd..0000000
--- a/target/board/treble_common_64.mk
+++ /dev/null
@@ -1,20 +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/treble_common.mk
-
-# Enable 64-bits binder
-TARGET_USES_64_BIT_BINDER := true
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 480b395..12fd99a 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -60,6 +60,7 @@
     $(LOCAL_DIR)/full_x86.mk \
     $(LOCAL_DIR)/generic.mk \
     $(LOCAL_DIR)/generic_x86.mk \
+    $(LOCAL_DIR)/gsi_arm64.mk \
     $(LOCAL_DIR)/mainline_arm64.mk \
     $(LOCAL_DIR)/mainline_system_arm64.mk \
     $(LOCAL_DIR)/sdk_arm64.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
index 3c7af33..e45229d 100644
--- a/target/product/aosp_arm64_a.mk
+++ b/target/product/aosp_arm64_a.mk
@@ -17,9 +17,27 @@
 # 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.
+# gsi_system.prop.
 
-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 mainline checking for excat this product name
+ifeq (aosp_arm64_a,$(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_a
 PRODUCT_DEVICE := generic_arm64_a
diff --git a/target/product/aosp_arm64_ab.mk b/target/product/aosp_arm64_ab.mk
index d389c74..f707a39 100644
--- a/target/product/aosp_arm64_ab.mk
+++ b/target/product/aosp_arm64_ab.mk
@@ -17,21 +17,32 @@
 # 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.
+# gsi_system.prop.
 
 # aosp_arm64_ab-userdebug is a Legacy GSI for the devices with:
 # - ARM 64 bits user space
 # - 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
index 3060fa9..249ad2c 100644
--- a/target/product/aosp_arm_a.mk
+++ b/target/product/aosp_arm_a.mk
@@ -17,9 +17,14 @@
 # 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.
+# gsi_system.prop.
 
-include build/make/target/product/treble_common_32.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
+
+# Enable mainline checking for excat this product name
+ifeq (aosp_arm_a,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
 PRODUCT_NAME := aosp_arm_a
 PRODUCT_DEVICE := generic_arm_a
diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk
index 5845d3b..e760932 100644
--- a/target/product/aosp_arm_ab.mk
+++ b/target/product/aosp_arm_ab.mk
@@ -17,21 +17,19 @@
 # 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.
+# gsi_system.prop.
 
 # aosp_arm_ab-userdebug is a Legacy GSI for the devices with:
 # - ARM 32 bits user space
 # - 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
index a7fb740..f40b9a9 100644
--- a/target/product/aosp_x86_64_a.mk
+++ b/target/product/aosp_x86_64_a.mk
@@ -17,9 +17,27 @@
 # 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.
+# gsi_system.prop.
 
-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 mainline checking for excat this product name
+ifeq (aosp_x86_64_a,$(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_a
 PRODUCT_DEVICE := generic_x86_64_a
diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk
index d9163d7..dfb7b49 100644
--- a/target/product/aosp_x86_64_ab.mk
+++ b/target/product/aosp_x86_64_ab.mk
@@ -17,21 +17,32 @@
 # 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.
+# gsi_system.prop.
 
 # aosp_x86_64_ab-userdebug is a Legacy GSI for the devices with:
 # - x86 64 bits user space
 # - 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
index 9ed2995..743e0b9 100644
--- a/target/product/aosp_x86_a.mk
+++ b/target/product/aosp_x86_a.mk
@@ -17,9 +17,14 @@
 # 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.
+# gsi_system.prop.
 
-include build/make/target/product/treble_common_32.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
+
+# Enable mainline checking for excat this product name
+ifeq (aosp_x86_a,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
 PRODUCT_NAME := aosp_x86_a
 PRODUCT_DEVICE := generic_x86_a
diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk
index 4fff3d1..d07351c 100644
--- a/target/product/aosp_x86_ab.mk
+++ b/target/product/aosp_x86_ab.mk
@@ -17,21 +17,19 @@
 # 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.
+# gsi_system.prop.
 
 # aosp_x86_ab-userdebug is a Legacy GSI for the devices with:
 # - x86 32 bits user space
 # - 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.mk b/target/product/base.mk
index 1ecbf4a..804a2ee 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -18,3 +18,4 @@
 # up by partition.
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/base_product.mk)
diff --git a/target/board/treble_common_32.mk b/target/product/base_product.mk
similarity index 72%
copy from target/board/treble_common_32.mk
copy to target/product/base_product.mk
index b66c41e..1ed9e83 100644
--- a/target/board/treble_common_32.mk
+++ b/target/product/base_product.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,4 +14,8 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common.mk
+# Base modules and settings for the product partition.
+PRODUCT_PACKAGES += \
+    healthd \
+    ModuleMetadata \
+    product_compatibility_matrix.xml \
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 6e8e79b..83a84f7 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -16,6 +16,7 @@
 
 # Base modules and settings for the system partition.
 PRODUCT_PACKAGES += \
+    abb \
     adb \
     adbd \
     am \
@@ -33,6 +34,7 @@
     appops \
     app_process \
     appwidget \
+    ashmemd \
     atest \
     atrace \
     audioserver \
@@ -48,6 +50,7 @@
     bu \
     bugreport \
     bugreportz \
+    cgroups.json \
     charger \
     cmd \
     com.android.conscrypt \
@@ -61,6 +64,7 @@
     CtsShimPrivPrebuilt \
     debuggerd\
     DefaultContainerService \
+    dmctl \
     dnsmasq \
     DownloadProvider \
     dpm \
@@ -77,11 +81,11 @@
     fsck_msdos \
     fs_config_files_system \
     fs_config_dirs_system \
+    gsid \
     heapprofd \
     heapprofd_client \
     gatekeeperd \
     gpuservice \
-    healthd \
     hid \
     hwservicemanager \
     idmap \
@@ -110,6 +114,8 @@
     libandroidfw \
     libandroid_runtime \
     libandroid_servers \
+    libartpalette-system \
+    libashmemd_client \
     libaudioeffect_jni \
     libaudioflinger \
     libaudiopolicymanager \
@@ -117,14 +123,14 @@
     libaudioutils \
     libbinder \
     libbinder_ndk \
-    libc \
+    libc.bootstrap \
     libcamera2ndk \
     libcamera_client \
     libcameraservice \
     libc_malloc_debug \
     libc_malloc_hooks \
     libcutils \
-    libdl \
+    libdl.bootstrap \
     libdrmframework \
     libdrmframework_jni \
     libEGL \
@@ -144,7 +150,7 @@
     libjnigraphics \
     libjpeg \
     liblog \
-    libm \
+    libm.bootstrap \
     libmdnssd \
     libmedia \
     libmedia_jni \
@@ -180,7 +186,6 @@
     libstagefright_omx \
     libstdc++ \
     libsurfaceflinger \
-    libsurfaceflinger_ddmconnection \
     libsysutils \
     libui \
     libusbhost \
@@ -206,7 +211,6 @@
     MediaProvider \
     mediaserver \
     mke2fs \
-    ModuleMetadata \
     monkey \
     mtpd \
     ndc \
@@ -245,6 +249,7 @@
     storaged \
     surfaceflinger \
     svc \
+    task_profiles.json \
     tc \
     telecom \
     telephony-common \
@@ -258,6 +263,7 @@
     uncrypt \
     usbd \
     vdc \
+    viewcompiler \
     voip-common \
     vold \
     WallpaperBackup \
@@ -269,7 +275,43 @@
 # VINTF data for system image
 PRODUCT_PACKAGES += \
     framework_manifest.xml \
-    framework_compatibility_matrix.xml \
+    system_compatibility_matrix.xml \
+
+# Host tools to install
+PRODUCT_HOST_PACKAGES += \
+    BugReport \
+    adb \
+    adbd \
+    atest \
+    bcc \
+    bit \
+    e2fsck \
+    fastboot \
+    flags_health_check \
+    icu-data_host_runtime_apex \
+    incident_report \
+    ld.mc \
+    lpdump \
+    mdnsd \
+    minigzip \
+    mke2fs \
+    resize2fs \
+    selinux_policy_system \
+    sgdisk \
+    shell_and_utilities_system \
+    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)
@@ -283,15 +325,10 @@
     telephony-common \
     voip-common \
     ims-common
+PRODUCT_UPDATABLE_BOOT_MODULES := conscrypt
+PRODUCT_UPDATABLE_BOOT_LOCATIONS := \
+    /apex/com.android.conscrypt/javalib/conscrypt.jar
 
-# Add the compatibility library that is needed when org.apache.http.legacy
-# is removed from the bootclasspath.
-ifeq ($(REMOVE_OAHL_FROM_BCP),true)
-PRODUCT_PACKAGES += framework-oahl-backward-compatibility
-PRODUCT_BOOT_JARS += framework-oahl-backward-compatibility
-else
-PRODUCT_BOOT_JARS += org.apache.http.legacy.impl
-endif
 
 PRODUCT_COPY_FILES += \
     system/core/rootdir/init.usb.rc:root/init.usb.rc \
@@ -305,7 +342,7 @@
 PRODUCT_PACKAGES += framework-atb-backward-compatibility
 PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
 else
-PRODUCT_BOOT_JARS += android.test.base.impl
+PRODUCT_BOOT_JARS += android.test.base
 endif
 
 PRODUCT_COPY_FILES += system/core/rootdir/init.zygote32.rc:root/init.zygote32.rc
@@ -317,14 +354,18 @@
 PRODUCT_PACKAGES_DEBUG := \
     adb_keys \
     arping \
+    gdbserver \
+    init-debug.rc \
     iotop \
     iw \
     logpersist.start \
+    logtagd.rc \
     procrank \
     showmap \
     sqlite3 \
     ss \
     strace \
+    su \
     sanitizer-status \
     tracepath \
     tracepath6 \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 9bb45d1..bf01957 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,11 +27,22 @@
     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.1-service \
     android.hardware.media.omx@1.0-service \
+    dumpsys_vendor \
     fs_config_files_nonsystem \
     fs_config_dirs_nonsystem \
     gralloc.default \
@@ -55,5 +68,4 @@
 
 # VINTF data for vendor image
 PRODUCT_PACKAGES += \
-    device_manifest.xml \
     device_compatibility_matrix.xml \
diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk
index b432a91..9718dc6 100644
--- a/target/product/core_minimal.mk
+++ b/target/product/core_minimal.mk
@@ -18,11 +18,12 @@
 # means most android products, but excludes wearables.
 #
 # Note: Do not add any contents directly to this file. Choose either
-# media_system or media_vendor depending on partition (also consider
-# base_<x>.mk or handheld_<x>.mk.
+# media_<x> depending on partition also consider base_<x>.mk or
+# handheld_<x>.mk.
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/media_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/media_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/media_product.mk)
 
 PRODUCT_BRAND := generic
 PRODUCT_DEVICE := generic
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_base_telephony.mk b/target/product/full_base_telephony.mk
index ee59090..af4097d 100644
--- a/target/product/full_base_telephony.mk
+++ b/target/product/full_base_telephony.mk
@@ -28,5 +28,4 @@
     frameworks/native/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony.mk)
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index a76b07c..17ca398 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -36,6 +36,10 @@
 	bios.bin \
 	vgabios-cirrus.bin \
 
+PRODUCT_HOST_PACKAGES += \
+	bios.bin \
+	vgabios-cirrus.bin \
+
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 7a9732d..6fe4818 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -18,15 +18,11 @@
 # It includes the base Android platform.
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/generic_no_telephony.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony.mk)
 
 # Overrides
 PRODUCT_BRAND := generic
 PRODUCT_DEVICE := generic
 PRODUCT_NAME := generic
 
-_whitelist := \
-  device_manifest.xml \
-
-$(call enforce-product-packages-exist,$(_whitelist))
+$(call enforce-product-packages-exist,)
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index 5346476..324d36f 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -22,6 +22,7 @@
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_product.mk)
 
 PRODUCT_BRAND := generic
 PRODUCT_DEVICE := generic
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index 06bdec9..7042f6d 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -61,11 +61,15 @@
 # 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
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/current.txt b/target/product/gsi/current.txt
index 0b99000..2716d2c 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -42,7 +42,9 @@
 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
 VNDK-SP: libutils.so
 VNDK-SP: libutilscallstack.so
@@ -70,6 +72,7 @@
 VNDK-core: android.hardware.automotive.vehicle@2.0.so
 VNDK-core: android.hardware.biometrics.fingerprint@2.1.so
 VNDK-core: android.hardware.bluetooth.a2dp@1.0.so
+VNDK-core: android.hardware.bluetooth.audio@2.0.so
 VNDK-core: android.hardware.bluetooth@1.0.so
 VNDK-core: android.hardware.boot@1.0.so
 VNDK-core: android.hardware.broadcastradio@1.0.so
@@ -118,7 +121,9 @@
 VNDK-core: android.hardware.neuralnetworks@1.2.so
 VNDK-core: android.hardware.nfc@1.0.so
 VNDK-core: android.hardware.nfc@1.1.so
+VNDK-core: android.hardware.nfc@1.2.so
 VNDK-core: android.hardware.oemlock@1.0.so
+VNDK-core: android.hardware.power.stats@1.0.so
 VNDK-core: android.hardware.power@1.0.so
 VNDK-core: android.hardware.power@1.1.so
 VNDK-core: android.hardware.power@1.2.so
@@ -133,6 +138,7 @@
 VNDK-core: android.hardware.radio@1.3.so
 VNDK-core: android.hardware.radio@1.4.so
 VNDK-core: android.hardware.secure_element@1.0.so
+VNDK-core: android.hardware.secure_element@1.1.so
 VNDK-core: android.hardware.sensors@1.0.so
 VNDK-core: android.hardware.soundtrigger@2.0.so
 VNDK-core: android.hardware.soundtrigger@2.0-core.so
@@ -201,7 +207,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
diff --git a/target/product/gsi_arm64.mk b/target/product/gsi_arm64.mk
new file mode 100644
index 0000000..b711d88
--- /dev/null
+++ b/target/product/gsi_arm64.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.
+#
+
+$(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 \
+
+# 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 := gsi_arm64
+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
new file mode 100644
index 0000000..fb0478d
--- /dev/null
+++ b/target/product/gsi_common.mk
@@ -0,0 +1,99 @@
+#
+# 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.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+
+# GSI includes all AOSP product packages and placed under /system/product
+$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_product.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_product.mk)
+
+# Default AOSP sounds
+$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
+
+# Additional settings used in all AOSP builds
+PRODUCT_PROPERTY_OVERRIDES += \
+    ro.config.ringtone=Ring_Synth_04.ogg \
+    ro.config.notification_sound=pixiedust.ogg
+
+# 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 \
+    system/lib64/libframesequence.so \
+    system/lib64/libgiftranscode.so \
+    system/priv-app/Dialer/Dialer.apk \
+
+# Some GSI builds enable dexpreopt, whitelist these preopt files
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += %.odex %.vdex %.art
+
+# Exclude GSI specific files
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/etc/init/config/skip_mount.cfg \
+    system/etc/init/init.gsi.rc \
+
+# Exclude all files under system/product and system/product_services
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/product/% \
+    system/product_services/%
+
+
+# Split selinux policy
+PRODUCT_FULL_TREBLE_OVERRIDE := true
+
+# 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
+
+# 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
+
+# Default AOSP packages
+PRODUCT_PACKAGES += \
+    messaging \
+
+# Default AOSP packages
+PRODUCT_PACKAGES += \
+    PhotoTable \
+    WAPPushManager \
+
+# Telephony:
+#   Provide a APN configuration to GSI product
+PRODUCT_COPY_FILES += \
+    device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml
+
+# NFC:
+#   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
diff --git a/target/product/handheld_product.mk b/target/product/handheld_product.mk
new file mode 100644
index 0000000..758fa9b
--- /dev/null
+++ b/target/product/handheld_product.mk
@@ -0,0 +1,42 @@
+#
+# 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 makefile contains the product partition contents for
+# a generic phone or tablet device. Only add something here if
+# it definitely doesn't belong on other types of devices (if it
+# does, use base_vendor.mk).
+$(call inherit-product, $(SRC_TARGET_DIR)/product/media_product.mk)
+
+# /product packages
+PRODUCT_PACKAGES += \
+    Browser2 \
+    Calendar \
+    Camera2 \
+    Contacts \
+    DeskClock \
+    Email \
+    Gallery2 \
+    LatinIME \
+    Launcher3QuickStep \
+    Music \
+    OneTimeInitializer \
+    Provision \
+    QuickSearchBox \
+    Settings \
+    SettingsIntelligence \
+    StorageManager \
+    SystemUI \
+    WallpaperCropper \
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index f874868..a4dd6d7 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -36,53 +36,34 @@
     Bluetooth \
     BluetoothMidiService \
     BookmarkProvider \
-    Browser2 \
     BuiltInPrintService \
-    Calendar \
     CalendarProvider \
-    Camera2 \
     cameraserver \
     CaptivePortalLogin \
     CertInstaller \
     clatd \
     clatd.conf \
-    Contacts \
-    DeskClock \
     DocumentsUI \
     DownloadProviderUi \
     EasterEgg \
-    Email \
-    ExactCalculator \
     ExternalStorageProvider \
     FusedLocation \
-    Gallery2 \
-    Home \
     InputDevices \
     KeyChain \
-    LatinIME \
-    Launcher3QuickStep \
     librs_jni \
     ManagedProvisioning \
     MmsService \
     MtpDocumentsProvider \
-    Music \
     MusicFX \
     NfcNci \
-    OneTimeInitializer \
     PacProcessor \
     PrintRecommendationService \
     PrintSpooler \
-    Provision \
     ProxyHandler \
-    QuickSearchBox \
     screenrecord \
     SecureElement \
-    Settings \
-    SettingsIntelligence \
     SharedStorageBackup \
     SimAppDialog \
-    StorageManager \
-    SystemUI \
     Telecom \
     TelephonyProvider \
     TeleService \
@@ -90,7 +71,6 @@
     UserDictionaryProvider \
     VpnDialogs \
     vr \
-    WallpaperCropper \
 
 
 PRODUCT_SYSTEM_SERVER_APPS += \
@@ -106,4 +86,3 @@
     ro.carrier=unknown \
     ro.config.notification_sound=OnTheHunt.ogg \
     ro.config.alarm_alert=Alarm_Classic.ogg
-
diff --git a/target/product/handheld_vendor.mk b/target/product/handheld_vendor.mk
index 0f73875..ca7760a 100644
--- a/target/product/handheld_vendor.mk
+++ b/target/product/handheld_vendor.mk
@@ -19,6 +19,8 @@
 # it definitely doesn't belong on other types of devices (if it
 # does, use base_vendor.mk).
 $(call inherit-product, $(SRC_TARGET_DIR)/product/media_vendor.mk)
+
+# /vendor packages
 PRODUCT_PACKAGES += \
     audio.primary.default \
     DisplayCutoutEmulationCornerOverlay \
diff --git a/target/product/languages_default.mk b/target/product/languages_default.mk
new file mode 100644
index 0000000..a13a23c
--- /dev/null
+++ b/target/product/languages_default.mk
@@ -0,0 +1,105 @@
+#
+# Copyright (C) 2009 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 is a build configuration that just contains a list of languages, with
+# en_US set as the default language.
+PRODUCT_LOCALES := \
+        en_US \
+        af_ZA \
+        am_ET \
+        ar_EG \
+        ar_XB \
+        as_IN \
+        az_AZ \
+        be_BY \
+        bg_BG \
+        bn_BD \
+        bs_BA \
+        ca_ES \
+        cs_CZ \
+        da_DK \
+        de_DE \
+        el_GR \
+        en_AU \
+        en_CA \
+        en_GB \
+        en_IN \
+        en_XA \
+        es_ES \
+        es_US \
+        et_EE \
+        eu_ES \
+        fa_IR \
+        fi_FI \
+        fr_CA \
+        fr_FR \
+        gl_ES \
+        gu_IN \
+        hi_IN \
+        hr_HR \
+        hu_HU \
+        hy_AM \
+        in_ID \
+        is_IS \
+        it_IT \
+        iw_IL \
+        ja_JP \
+        ka_GE \
+        kk_KZ \
+        km_KH \
+        kn_IN \
+        ko_KR \
+        ky_KG \
+        lo_LA \
+        lt_LT \
+        lv_LV \
+        mk_MK \
+        ml_IN \
+        mn_MN \
+        mr_IN \
+        ms_MY \
+        my_MM \
+        nb_NO \
+        ne_NP \
+        nl_NL \
+        or_IN \
+        pa_IN \
+        pl_PL \
+        pt_BR \
+        pt_PT \
+        ro_RO \
+        ru_RU \
+        si_LK \
+        sk_SK \
+        sl_SI \
+        sq_AL \
+        sr_Latn_RS \
+        sr_RS \
+        sv_SE \
+        sw_TZ \
+        ta_IN \
+        te_IN \
+        th_TH \
+        tl_PH \
+        tr_TR \
+        uk_UA \
+        ur_PK \
+        uz_UZ \
+        vi_VN \
+        zh_CN \
+        zh_HK \
+        zh_TW \
+        zu_ZA \
diff --git a/target/product/languages_full.mk b/target/product/languages_full.mk
index 5f3795f..43a40a7 100644
--- a/target/product/languages_full.mk
+++ b/target/product/languages_full.mk
@@ -14,94 +14,9 @@
 # limitations under the License.
 #
 
-# This is a build configuration that just contains a list of languages.
-#
-# These are all the locales that have translations.
-PRODUCT_LOCALES := \
-        en_US \
-        af_ZA \
-        am_ET \
-        ar_EG \
-        ar_XB \
-        as_IN \
-        az_AZ \
-        be_BY \
-        bg_BG \
-        bn_BD \
-        bs_BA \
-        ca_ES \
-        cs_CZ \
-        da_DK \
-        de_DE \
-        el_GR \
-        en_AU \
-        en_CA \
-        en_GB \
-        en_IN \
-        en_XA \
-        en_XC \
-        es_ES \
-        es_US \
-        et_EE \
-        eu_ES \
-        fa_IR \
-        fi_FI \
-        fr_CA \
-        fr_FR \
-        gl_ES \
-        gu_IN \
-        hi_IN \
-        hr_HR \
-        hu_HU \
-        hy_AM \
-        in_ID \
-        is_IS \
-        it_IT \
-        iw_IL \
-        ja_JP \
-        ka_GE \
-        kk_KZ \
-        km_KH \
-        kn_IN \
-        ko_KR \
-        ky_KG \
-        lo_LA \
-        lt_LT \
-        lv_LV \
-        mk_MK \
-        ml_IN \
-        mn_MN \
-        mr_IN \
-        ms_MY \
-        my_MM \
-        nb_NO \
-        ne_NP \
-        nl_NL \
-        or_IN \
-        pa_IN \
-        pl_PL \
-        pt_BR \
-        pt_PT \
-        ro_RO \
-        ru_RU \
-        si_LK \
-        sk_SK \
-        sl_SI \
-        sq_AL \
-        sr_Latn_RS \
-        sr_RS \
-        sv_SE \
-        sw_TZ \
-        ta_IN \
-        te_IN \
-        th_TH \
-        tl_PH \
-        tr_TR \
-        uk_UA \
-        ur_PK \
-        uz_UZ \
-        vi_VN \
-        zh_CN \
-        zh_HK \
-        zh_TW \
-        zu_ZA
+# This is a build configuration that contains the default list of languages,
+# as well as the en_XC pseudo-locale, which is useful for localization test
+# builds.
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+PRODUCT_LOCALES += en_XC
diff --git a/target/product/languages_small.mk b/target/product/languages_small.mk
deleted file mode 100644
index d695ca8..0000000
--- a/target/product/languages_small.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2009 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 is a build configuration that just contains a list of languages.
-# It helps in situations where laugnages must come first in the list,
-# mostly because screen densities interfere with the list of locales and
-# the system misbehaves when a density is the first locale.
-
-# This is the list of languages that originally shipped on ADP1
-
-PRODUCT_LOCALES := en_US en_GB fr_FR it_IT de_DE es_ES
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
new file mode 100644
index 0000000..59bad98
--- /dev/null
+++ b/target/product/mainline.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+# Makefile including the mainline system image, and the relevant AOSP portions
+# for the other partitions.
+$(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)
diff --git a/target/product/mainline_arm64.mk b/target/product/mainline_arm64.mk
index f93d7e4..6050924 100644
--- a/target/product/mainline_arm64.mk
+++ b/target/product/mainline_arm64.mk
@@ -15,20 +15,58 @@
 #
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(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/telephony_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline.mk)
+$(call enforce-product-packages-exist,)
 
 PRODUCT_NAME := mainline_arm64
-PRODUCT_DEVICE := generic_arm64
+PRODUCT_DEVICE := mainline_arm64
 PRODUCT_BRAND := generic
 PRODUCT_SHIPPING_API_LEVEL := 28
 PRODUCT_RESTRICT_VENDOR_FILES := all
 
 PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-# Target device doesn't have a product partition, so whitelist the /system/ fallback path.
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST := system/product/%
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
   root/init.zygote64_32.rc \
   system/etc/seccomp_policy/crash_dump.arm.policy \
   system/etc/seccomp_policy/mediacodec.policy \
+
+# Modules that are to be moved to /product
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+  system/app/Browser2/Browser2.apk \
+  system/app/Calendar/Calendar.apk \
+  system/app/Camera2/Camera2.apk \
+  system/app/DeskClock/DeskClock.apk \
+  system/app/DeskClock/oat/arm64/DeskClock.odex \
+  system/app/DeskClock/oat/arm64/DeskClock.vdex \
+  system/app/Email/Email.apk \
+  system/app/Gallery2/Gallery2.apk \
+  system/app/LatinIME/LatinIME.apk \
+  system/app/LatinIME/oat/arm64/LatinIME.odex \
+  system/app/LatinIME/oat/arm64/LatinIME.vdex \
+  system/app/Music/Music.apk \
+  system/app/QuickSearchBox/QuickSearchBox.apk \
+  system/app/webview/webview.apk \
+  system/bin/healthd \
+  system/etc/init/healthd.rc \
+  system/etc/vintf/manifest/manifest_healthd.xml \
+  system/lib64/libjni_eglfence.so \
+  system/lib64/libjni_filtershow_filters.so \
+  system/lib64/libjni_jpegstream.so \
+  system/lib64/libjni_jpegutil.so \
+  system/lib64/libjni_latinime.so \
+  system/lib64/libjni_tinyplanet.so \
+  system/priv-app/CarrierConfig/CarrierConfig.apk \
+  system/priv-app/CarrierConfig/oat/arm64/CarrierConfig.odex \
+  system/priv-app/CarrierConfig/oat/arm64/CarrierConfig.vdex \
+  system/priv-app/Contacts/Contacts.apk \
+  system/priv-app/Dialer/Dialer.apk \
+  system/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk \
+  system/priv-app/OneTimeInitializer/OneTimeInitializer.apk \
+  system/priv-app/Provision/Provision.apk \
+  system/priv-app/Settings/Settings.apk \
+  system/priv-app/SettingsIntelligence/SettingsIntelligence.apk \
+  system/priv-app/StorageManager/StorageManager.apk \
+  system/priv-app/SystemUI/SystemUI.apk \
+  system/priv-app/SystemUI/oat/arm64/SystemUI.odex \
+  system/priv-app/SystemUI/oat/arm64/SystemUI.vdex \
+  system/priv-app/WallpaperCropper/WallpaperCropper.apk \
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index c41e1d7..0ddc3db 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -17,6 +17,9 @@
 # This makefile is the basis of a generic system image for a handheld device.
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+# Add adb keys to debuggable AOSP builds (if they exist)
+$(call inherit-product-if-exists, vendor/google/security/adb/vendor_key.mk)
 
 # Shared java libs
 PRODUCT_PACKAGES += \
@@ -24,13 +27,13 @@
 
 # Applications
 PRODUCT_PACKAGES += \
-    DMService \
     LiveWallpapersPicker \
     PartnerBookmarksProvider \
     PresencePolling \
     RcsService \
     SafetyRegulatoryInfo \
     Stk \
+    Tag \
     TimeZoneUpdater \
 
 # Binaries
@@ -38,6 +41,7 @@
 
 # OTA support
 PRODUCT_PACKAGES += \
+    recovery-refresh \
     update_engine \
     update_verifier \
 
@@ -70,8 +74,7 @@
     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.hidl.base@1.0 \
+    android.hardware.wifi@1.0 \
     libaudio-resampler \
     liblogwrap \
     liblz4 \
@@ -89,6 +92,9 @@
     tinypcminfo \
     update_engine_client \
 
+PRODUCT_HOST_PACKAGES += \
+    tinyplay
+
 # Enable stats logging in LMKD
 TARGET_LMKD_STATS_LOG := true
 PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
@@ -97,8 +103,6 @@
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
-PRODUCT_LOCALES := en_US af_ZA am_ET ar_EG as_IN az_AZ be_BY bg_BG bn_BD bs_BA ca_ES cs_CZ da_DK de_DE el_GR en_AU en_CA en_GB en_IN es_ES es_US et_EE eu_ES fa_IR fi_FI fr_CA fr_FR gl_ES gu_IN hi_IN hr_HR hu_HU hy_AM in_ID is_IS it_IT iw_IL ja_JP ka_GE kk_KZ km_KH ko_KR ky_KG lo_LA lt_LT lv_LV km_MH kn_IN mn_MN ml_IN mk_MK mr_IN ms_MY my_MM ne_NP nb_NO nl_NL or_IN pa_IN pl_PL pt_BR pt_PT ro_RO ru_RU si_LK sk_SK sl_SI sq_AL sr_Latn_RS sr_RS sv_SE sw_TZ ta_IN te_IN th_TH tl_PH tr_TR uk_UA ur_PK uz_UZ vi_VN zh_CN zh_HK zh_TW zu_ZA en_XA ar_XB
-
 PRODUCT_NAME := mainline_system
 PRODUCT_BRAND := generic
 
diff --git a/target/product/mainline_system_arm64.mk b/target/product/mainline_system_arm64.mk
index 560dfd3..0b0929e 100644
--- a/target/product/mainline_system_arm64.mk
+++ b/target/product/mainline_system_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_system.mk)
+$(call enforce-product-packages-exist,)
 
 PRODUCT_NAME := mainline_system_arm64
 PRODUCT_DEVICE := mainline_arm64
diff --git a/target/product/media_product.mk b/target/product/media_product.mk
new file mode 100644
index 0000000..17c24ee
--- /dev/null
+++ b/target/product/media_product.mk
@@ -0,0 +1,25 @@
+#
+# 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 makefile contains the product partition contents for
+# media-capable devices (non-wearables). Only add something here
+# if it definitely doesn't belong on wearables. Otherwise, choose
+# base_vendor.mk.
+$(call inherit-product, $(SRC_TARGET_DIR)/product/base_product.mk)
+
+# /product packages
+PRODUCT_PACKAGES += \
+    webview \
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index 992e2ed..2ba7005 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -59,8 +59,9 @@
     requestsync \
     StatementService \
     vndk_snapshot_package \
-    webview \
 
+PRODUCT_HOST_PACKAGES += \
+    fsck.f2fs \
 
 PRODUCT_COPY_FILES += \
     frameworks/native/data/etc/android.software.webview.xml:system/etc/permissions/android.software.webview.xml
@@ -75,7 +76,7 @@
     services \
     ethernet-service \
     wifi-service \
-    com.android.location.provider.impl \
+    com.android.location.provider \
 
 PRODUCT_COPY_FILES += \
     system/core/rootdir/etc/public.libraries.android.txt:system/etc/public.libraries.txt
diff --git a/target/product/media_vendor.mk b/target/product/media_vendor.mk
index 1db0b58..7d4af64 100644
--- a/target/product/media_vendor.mk
+++ b/target/product/media_vendor.mk
@@ -20,6 +20,7 @@
 # base_vendor.mk.
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base_vendor.mk)
 
+# /vendor packages
 PRODUCT_PACKAGES += \
     libaudiopreprocessing \
     libwebrtc_audio_preprocessing \
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 6d835fd..412d8cf 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -33,28 +33,14 @@
 PRODUCT_PACKAGES += \
     ext \
 
-# Why are we pulling in expat, which is used in frameworks, only, it seem?
-PRODUCT_PACKAGES += \
-    libexpat \
-
-# Libcore.
-PRODUCT_PACKAGES += \
-    libjavacore \
-    libopenjdk \
-
-# 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.
-ifneq ($(DONT_INCLUDE_RUNTIME_APEX), true)
-  PRODUCT_PACKAGES += com.android.runtime
-endif
+PRODUCT_PACKAGES += com.android.runtime
+PRODUCT_HOST_PACKAGES += com.android.runtime
 
 # Certificates.
 PRODUCT_PACKAGES += \
@@ -98,6 +84,11 @@
     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 \
     dalvik.vm.dex2oat-minidebuginfo=true
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/board/treble_common_32.mk b/target/product/telephony.mk
similarity index 64%
copy from target/board/treble_common_32.mk
copy to target/product/telephony.mk
index b66c41e..e0eb159 100644
--- a/target/board/treble_common_32.mk
+++ b/target/product/telephony.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,4 +14,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common.mk
+# All modules for telephony
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_product.mk)
diff --git a/target/board/treble_common_32.mk b/target/product/telephony_product.mk
similarity index 67%
copy from target/board/treble_common_32.mk
copy to target/product/telephony_product.mk
index b66c41e..70d4828 100644
--- a/target/board/treble_common_32.mk
+++ b/target/product/telephony_product.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,4 +14,10 @@
 # limitations under the License.
 #
 
-include build/make/target/board/treble_common.mk
+# This is the list of modules that are specific to products that have telephony
+# hardware, and install to the product partition.
+
+# /product packages
+PRODUCT_PACKAGES += \
+    CarrierConfig \
+    Dialer \
diff --git a/target/product/telephony_system.mk b/target/product/telephony_system.mk
index 0b1e8a2..fd79472 100644
--- a/target/product/telephony_system.mk
+++ b/target/product/telephony_system.mk
@@ -18,10 +18,8 @@
 # hardware, and install on the system partition.
 
 PRODUCT_PACKAGES := \
-    ANS \
-    CarrierConfig \
+    ONS \
     CarrierDefaultApp \
-    Dialer \
     CallLogBackup \
     CellBroadcastReceiver \
     EmergencyInfo \
diff --git a/target/product/telephony_vendor.mk b/target/product/telephony_vendor.mk
index bddd383..86dbcc9 100644
--- a/target/product/telephony_vendor.mk
+++ b/target/product/telephony_vendor.mk
@@ -17,6 +17,7 @@
 # This is the list of modules that are specific to products that have telephony
 # hardware, and install outside the system partition.
 
+# /vendor packages
 PRODUCT_PACKAGES := \
     rild \
 
diff --git a/target/product/treble_common.mk b/target/product/treble_common.mk
deleted file mode 100644
index 7642876..0000000
--- a/target/product/treble_common.mk
+++ /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.
-#
-
-# 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_system.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.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_32.mk b/target/product/treble_common_32.mk
deleted file mode 100644
index 0023c3b..0000000
--- a/target/product/treble_common_32.mk
+++ /dev/null
@@ -1,22 +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
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/Android.mk b/tools/Android.mk
deleted file mode 100644
index c05d681..0000000
--- a/tools/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-# Only if this Android.mk was included not by a symlink should it be used.
-# This facilitates the transition away from symlinks: b/64397960
-ifeq ($(LOCAL_PATH),build/make/tools)
-include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index b76c089..24ac663 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -18,8 +18,8 @@
 echo "ro.build.date=`$DATE`"
 echo "ro.build.date.utc=`$DATE +%s`"
 echo "ro.build.type=$TARGET_BUILD_TYPE"
-echo "ro.build.user=$USER"
-echo "ro.build.host=`hostname`"
+echo "ro.build.user=$BUILD_USERNAME"
+echo "ro.build.host=$BUILD_HOSTNAME"
 echo "ro.build.tags=$BUILD_VERSION_TAGS"
 echo "ro.build.flavor=$TARGET_BUILD_FLAVOR"
 if [ -n "$BOARD_BUILD_SYSTEM_ROOT_IMAGE" ] ; then
@@ -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/check_elf_file.py b/tools/check_elf_file.py
new file mode 100755
index 0000000..38c1cf4
--- /dev/null
+++ b/tools/check_elf_file.py
@@ -0,0 +1,538 @@
+#!/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.
+
+"""ELF file checker.
+
+This command ensures all undefined symbols in an ELF file can be resolved to
+global (or weak) symbols defined in shared objects specified in DT_NEEDED
+entries.
+"""
+
+from __future__ import print_function
+
+import argparse
+import collections
+import os
+import os.path
+import re
+import struct
+import subprocess
+import sys
+
+
+_ELF_MAGIC = b'\x7fELF'
+
+
+# Known machines
+_EM_386 = 3
+_EM_ARM = 40
+_EM_X86_64 = 62
+_EM_AARCH64 = 183
+
+_KNOWN_MACHINES = {_EM_386, _EM_ARM, _EM_X86_64, _EM_AARCH64}
+
+
+# ELF header struct
+_ELF_HEADER_STRUCT = (
+  ('ei_magic', '4s'),
+  ('ei_class', 'B'),
+  ('ei_data', 'B'),
+  ('ei_version', 'B'),
+  ('ei_osabi', 'B'),
+  ('ei_pad', '8s'),
+  ('e_type', 'H'),
+  ('e_machine', 'H'),
+  ('e_version', 'I'),
+)
+
+_ELF_HEADER_STRUCT_FMT = ''.join(_fmt for _, _fmt in _ELF_HEADER_STRUCT)
+
+
+ELFHeader = collections.namedtuple(
+  'ELFHeader', [_name for _name, _ in _ELF_HEADER_STRUCT])
+
+
+ELF = collections.namedtuple(
+  'ELF',
+  ('dt_soname', 'dt_needed', 'imported', 'exported', 'header'))
+
+
+def _get_os_name():
+  """Get the host OS name."""
+  if sys.platform == 'linux2':
+    return 'linux'
+  if sys.platform == 'darwin':
+    return 'darwin'
+  raise ValueError(sys.platform + ' is not supported')
+
+
+def _get_build_top():
+  """Find the build top of the source tree ($ANDROID_BUILD_TOP)."""
+  prev_path = None
+  curr_path = os.path.abspath(os.getcwd())
+  while prev_path != curr_path:
+    if os.path.exists(os.path.join(curr_path, '.repo')):
+      return curr_path
+    prev_path = curr_path
+    curr_path = os.path.dirname(curr_path)
+  return None
+
+
+def _select_latest_llvm_version(versions):
+  """Select the latest LLVM prebuilts version from a set of versions."""
+  pattern = re.compile('clang-r([0-9]+)([a-z]?)')
+  found_rev = 0
+  found_ver = None
+  for curr_ver in versions:
+    match = pattern.match(curr_ver)
+    if not match:
+      continue
+    curr_rev = int(match.group(1))
+    if not found_ver or curr_rev > found_rev or (
+        curr_rev == found_rev and curr_ver > found_ver):
+      found_rev = curr_rev
+      found_ver = curr_ver
+  return found_ver
+
+
+def _get_latest_llvm_version(llvm_dir):
+  """Find the latest LLVM prebuilts version from `llvm_dir`."""
+  return _select_latest_llvm_version(os.listdir(llvm_dir))
+
+
+def _get_llvm_dir():
+  """Find the path to LLVM prebuilts."""
+  build_top = _get_build_top()
+
+  llvm_prebuilts_base = os.environ.get('LLVM_PREBUILTS_BASE')
+  if not llvm_prebuilts_base:
+    llvm_prebuilts_base = os.path.join('prebuilts', 'clang', 'host')
+
+  llvm_dir = os.path.join(
+    build_top, llvm_prebuilts_base, _get_os_name() + '-x86')
+
+  if not os.path.exists(llvm_dir):
+    return None
+
+  llvm_prebuilts_version = os.environ.get('LLVM_PREBUILTS_VERSION')
+  if not llvm_prebuilts_version:
+    llvm_prebuilts_version = _get_latest_llvm_version(llvm_dir)
+
+  llvm_dir = os.path.join(llvm_dir, llvm_prebuilts_version)
+
+  if not os.path.exists(llvm_dir):
+    return None
+
+  return llvm_dir
+
+
+def _get_llvm_readobj():
+  """Find the path to llvm-readobj executable."""
+  llvm_dir = _get_llvm_dir()
+  llvm_readobj = os.path.join(llvm_dir, 'bin', 'llvm-readobj')
+  return llvm_readobj if os.path.exists(llvm_readobj) else 'llvm-readobj'
+
+
+class ELFError(ValueError):
+  """Generic ELF parse error"""
+  pass
+
+
+class ELFInvalidMagicError(ELFError):
+  """Invalid ELF magic word error"""
+  def __init__(self):
+    super(ELFInvalidMagicError, self).__init__('bad ELF magic')
+
+
+class ELFParser(object):
+  """ELF file parser"""
+
+  @classmethod
+  def _read_elf_header(cls, elf_file_path):
+    """Read the ELF magic word from the beginning of the file."""
+    with open(elf_file_path, 'rb') as elf_file:
+      buf = elf_file.read(struct.calcsize(_ELF_HEADER_STRUCT_FMT))
+      try:
+        return ELFHeader(*struct.unpack(_ELF_HEADER_STRUCT_FMT, buf))
+      except struct.error:
+        return None
+
+
+  @classmethod
+  def open(cls, elf_file_path, llvm_readobj):
+    """Open and parse the ELF file."""
+    # Parse the ELF header for simple sanity checks.
+    header = cls._read_elf_header(elf_file_path)
+    if not header or header.ei_magic != _ELF_MAGIC:
+      raise ELFInvalidMagicError()
+
+    # Run llvm-readobj and parse the output.
+    return cls._read_llvm_readobj(elf_file_path, header, llvm_readobj)
+
+
+  @classmethod
+  def _find_prefix(cls, pattern, lines_it):
+    """Iterate `lines_it` until finding a string that starts with `pattern`."""
+    for line in lines_it:
+      if line.startswith(pattern):
+        return True
+    return False
+
+
+  @classmethod
+  def _read_llvm_readobj(cls, elf_file_path, header, llvm_readobj):
+    """Run llvm-readobj and parse the output."""
+    proc = subprocess.Popen(
+      [llvm_readobj, '-dynamic-table', '-dyn-symbols', elf_file_path],
+      stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    out, _ = proc.communicate()
+    lines = out.splitlines()
+    return cls._parse_llvm_readobj(elf_file_path, header, lines)
+
+
+  @classmethod
+  def _parse_llvm_readobj(cls, elf_file_path, header, lines):
+    """Parse the output of llvm-readobj."""
+    lines_it = iter(lines)
+    imported, exported = cls._parse_dynamic_symbols(lines_it)
+    dt_soname, dt_needed = cls._parse_dynamic_table(elf_file_path, lines_it)
+    return ELF(dt_soname, dt_needed, imported, exported, header)
+
+
+  _DYNAMIC_SECTION_START_PATTERN = 'DynamicSection ['
+
+  _DYNAMIC_SECTION_NEEDED_PATTERN = re.compile(
+    '^  0x[0-9a-fA-F]+\\s+NEEDED\\s+Shared library: \\[(.*)\\]$')
+
+  _DYNAMIC_SECTION_SONAME_PATTERN = re.compile(
+    '^  0x[0-9a-fA-F]+\\s+SONAME\\s+Library soname: \\[(.*)\\]$')
+
+  _DYNAMIC_SECTION_END_PATTERN = ']'
+
+
+  @classmethod
+  def _parse_dynamic_table(cls, elf_file_path, lines_it):
+    """Parse the dynamic table section."""
+    dt_soname = os.path.basename(elf_file_path)
+    dt_needed = []
+
+    dynamic = cls._find_prefix(cls._DYNAMIC_SECTION_START_PATTERN, lines_it)
+    if not dynamic:
+      return (dt_soname, dt_needed)
+
+    for line in lines_it:
+      if line == cls._DYNAMIC_SECTION_END_PATTERN:
+        break
+
+      match = cls._DYNAMIC_SECTION_NEEDED_PATTERN.match(line)
+      if match:
+        dt_needed.append(match.group(1))
+        continue
+
+      match = cls._DYNAMIC_SECTION_SONAME_PATTERN.match(line)
+      if match:
+        dt_soname = match.group(1)
+        continue
+
+    return (dt_soname, dt_needed)
+
+
+  _DYNAMIC_SYMBOLS_START_PATTERN = 'DynamicSymbols ['
+  _DYNAMIC_SYMBOLS_END_PATTERN = ']'
+
+  _SYMBOL_ENTRY_START_PATTERN = '  Symbol {'
+  _SYMBOL_ENTRY_PATTERN = re.compile('^    ([A-Za-z0-9_]+): (.*)$')
+  _SYMBOL_ENTRY_PAREN_PATTERN = re.compile(
+    '\\s+\\((?:(?:\\d+)|(?:0x[0-9a-fA-F]+))\\)$')
+  _SYMBOL_ENTRY_END_PATTERN = '  }'
+
+
+  @classmethod
+  def _parse_symbol_name(cls, 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]
+    return (name, version)
+
+
+  @classmethod
+  def _parse_dynamic_symbols(cls, lines_it):
+    """Parse dynamic symbol table and collect imported and exported symbols."""
+    imported = collections.defaultdict(set)
+    exported = collections.defaultdict(set)
+
+    for symbol in cls._parse_dynamic_symbols_internal(lines_it):
+      name, version = cls._parse_symbol_name(symbol['Name'])
+      if name:
+        if symbol['Section'] == 'Undefined':
+          if symbol['Binding'] != 'Weak':
+            imported[name].add(version)
+        else:
+          if symbol['Binding'] != 'Local':
+            exported[name].add(version)
+
+    # Freeze the returned imported/exported dict.
+    return (dict(imported), dict(exported))
+
+
+  @classmethod
+  def _parse_dynamic_symbols_internal(cls, lines_it):
+    """Parse symbols entries and yield each symbols."""
+
+    if not cls._find_prefix(cls._DYNAMIC_SYMBOLS_START_PATTERN, lines_it):
+      return
+
+    for line in lines_it:
+      if line == cls._DYNAMIC_SYMBOLS_END_PATTERN:
+        return
+
+      if line == cls._SYMBOL_ENTRY_START_PATTERN:
+        symbol = {}
+        continue
+
+      if line == cls._SYMBOL_ENTRY_END_PATTERN:
+        yield symbol
+        symbol = None
+        continue
+
+      match = cls._SYMBOL_ENTRY_PATTERN.match(line)
+      if match:
+        key = match.group(1)
+        value = cls._SYMBOL_ENTRY_PAREN_PATTERN.sub('', match.group(2))
+        symbol[key] = value
+        continue
+
+
+class Checker(object):
+  """ELF file checker that checks DT_SONAME, DT_NEEDED, and symbols."""
+
+  def __init__(self, llvm_readobj):
+    self._file_path = ''
+    self._file_under_test = None
+    self._shared_libs = []
+
+    self._llvm_readobj = llvm_readobj
+
+
+  if sys.stderr.isatty():
+    _ERROR_TAG = '\033[0;1;31merror:\033[m'  # Red error
+    _NOTE_TAG = '\033[0;1;30mnote:\033[m'  # Black note
+  else:
+    _ERROR_TAG = 'error:'  # Red error
+    _NOTE_TAG = 'note:'  # Black note
+
+
+  def _error(self, *args):
+    """Emit an error to stderr."""
+    print(self._file_path + ': ' + self._ERROR_TAG, *args, file=sys.stderr)
+
+
+  def _note(self, *args):
+    """Emit a note to stderr."""
+    print(self._file_path + ': ' + self._NOTE_TAG, *args, file=sys.stderr)
+
+
+  def _load_elf_file(self, path, skip_bad_elf_magic):
+    """Load an ELF file from the `path`."""
+    try:
+      return ELFParser.open(path, self._llvm_readobj)
+    except (IOError, OSError):
+      self._error('Failed to open "{}".'.format(path))
+      sys.exit(2)
+    except ELFInvalidMagicError:
+      if skip_bad_elf_magic:
+        sys.exit(0)
+      else:
+        self._error('File "{}" must have a valid ELF magic word.'.format(path))
+        sys.exit(2)
+    except:
+      self._error('An unknown error occurred while opening "{}".'.format(path))
+      raise
+
+
+  def load_file_under_test(self, path, skip_bad_elf_magic,
+                           skip_unknown_elf_machine):
+    """Load file-under-test (either an executable or a shared lib)."""
+    self._file_path = path
+    self._file_under_test = self._load_elf_file(path, skip_bad_elf_magic)
+
+    if skip_unknown_elf_machine and \
+        self._file_under_test.header.e_machine not in _KNOWN_MACHINES:
+      sys.exit(0)
+
+
+  def load_shared_libs(self, shared_lib_paths):
+    """Load shared libraries."""
+    for path in shared_lib_paths:
+      self._shared_libs.append(self._load_elf_file(path, False))
+
+
+  def check_dt_soname(self, soname):
+    """Check whether DT_SONAME matches installation file name."""
+    if self._file_under_test.dt_soname != soname:
+      self._error('DT_SONAME "{}" must be equal to the file name "{}".'
+                  .format(self._file_under_test.dt_soname, soname))
+      sys.exit(2)
+
+
+  def check_dt_needed(self):
+    """Check whether all DT_NEEDED entries are specified in the build
+    system."""
+
+    missing_shared_libs = False
+
+    # Collect the DT_SONAMEs from shared libs specified in the build system.
+    specified_sonames = {lib.dt_soname for lib in self._shared_libs}
+
+    # Chech whether all DT_NEEDED entries are specified.
+    for lib in self._file_under_test.dt_needed:
+      if lib not in specified_sonames:
+        self._error('DT_NEEDED "{}" is not specified in shared_libs.'
+                    .format(lib.decode('utf-8')))
+        missing_shared_libs = True
+
+    if missing_shared_libs:
+      dt_needed = sorted(set(self._file_under_test.dt_needed))
+      modules = [re.sub('\\.so$', '', lib) for lib in dt_needed]
+
+      self._note()
+      self._note('Fix suggestions:')
+      self._note(
+        '  Android.bp: shared_libs: [' +
+        ', '.join('"' + module + '"' for module in modules) + '],')
+      self._note(
+        '  Android.mk: LOCAL_SHARED_LIBRARIES := ' + ' '.join(modules))
+
+      self._note()
+      self._note('If the fix above doesn\'t work, bypass this check with:')
+      self._note('  Android.bp: check_elf_files: false,')
+      self._note('  Android.mk: LOCAL_CHECK_ELF_FILES := false')
+
+      sys.exit(2)
+
+
+  @staticmethod
+  def _find_symbol(lib, name, version):
+    """Check whether the symbol name and version matches a definition in
+    lib."""
+    try:
+      lib_sym_vers = lib.exported[name]
+    except KeyError:
+      return False
+    if version == '':  # Symbol version is not requested
+      return True
+    return version in lib_sym_vers
+
+
+  @classmethod
+  def _find_symbol_from_libs(cls, libs, name, version):
+    """Check whether the symbol name and version is defined in one of the
+    shared libraries in libs."""
+    for lib in libs:
+      if cls._find_symbol(lib, name, version):
+        return lib
+    return None
+
+
+  def check_symbols(self):
+    """Check whether all undefined symbols are resolved to a definition."""
+    all_elf_files = [self._file_under_test] + self._shared_libs
+    missing_symbols = []
+    for sym, imported_vers in self._file_under_test.imported.iteritems():
+      for imported_ver in imported_vers:
+        lib = self._find_symbol_from_libs(all_elf_files, sym, imported_ver)
+        if not lib:
+          missing_symbols.append((sym, imported_ver))
+
+    if missing_symbols:
+      for sym, ver in sorted(missing_symbols):
+        sym = sym.decode('utf-8')
+        if ver:
+          sym += '@' + ver.decode('utf-8')
+        self._error('Unresolved symbol: {}'.format(sym))
+
+      self._note()
+      self._note('Some dependencies might be changed, thus the symbol(s) '
+                 'above cannot be resolved.')
+      self._note('Please re-build the prebuilt file: "{}".'
+                 .format(self._file_path))
+
+      self._note()
+      self._note('If this is a new prebuilt file and it is designed to have '
+                 'unresolved symbols, add one of the following properties:')
+      self._note('  Android.bp: allow_undefined_symbols: true,')
+      self._note('  Android.mk: LOCAL_ALLOW_UNDEFINED_SYMBOLS := true')
+
+      sys.exit(2)
+
+
+def _parse_args():
+  """Parse command line options."""
+  parser = argparse.ArgumentParser()
+
+  # Input file
+  parser.add_argument('file',
+                      help='Path to the input file to be checked')
+  parser.add_argument('--soname',
+                      help='Shared object name of the input file')
+
+  # Shared library dependencies
+  parser.add_argument('--shared-lib', action='append', default=[],
+                      help='Path to shared library dependencies')
+
+  # Check options
+  parser.add_argument('--skip-bad-elf-magic', action='store_true',
+                      help='Ignore the input file without the ELF magic word')
+  parser.add_argument('--skip-unknown-elf-machine', action='store_true',
+                      help='Ignore the input file with unknown machine ID')
+  parser.add_argument('--allow-undefined-symbols', action='store_true',
+                      help='Ignore unresolved undefined symbols')
+
+  # Other options
+  parser.add_argument('--llvm-readobj',
+                      help='Path to the llvm-readobj executable')
+
+  return parser.parse_args()
+
+
+def main():
+  """Main function"""
+  args = _parse_args()
+
+  llvm_readobj = args.llvm_readobj
+  if not llvm_readobj:
+    llvm_readobj = _get_llvm_readobj()
+
+  # Load ELF files
+  checker = Checker(llvm_readobj)
+  checker.load_file_under_test(
+    args.file, args.skip_bad_elf_magic, args.skip_unknown_elf_machine)
+  checker.load_shared_libs(args.shared_lib)
+
+  # Run checks
+  if args.soname:
+    checker.check_dt_soname(args.soname)
+
+  checker.check_dt_needed()
+
+  if not args.allow_undefined_symbols:
+    checker.check_symbols()
+
+
+if __name__ == '__main__':
+  main()
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/droiddoc/Android.mk b/tools/droiddoc/Android.mk
deleted file mode 100644
index ff08edc..0000000
--- a/tools/droiddoc/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2008 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Droiddoc is now Doclava -- See external/doclava.
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/releasetools/OWNERS b/tools/releasetools/OWNERS
index 39448cf..766adb4 100644
--- a/tools/releasetools/OWNERS
+++ b/tools/releasetools/OWNERS
@@ -1 +1,2 @@
 tbao@google.com
+xunchang@google.com
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 1872a58..10aecf9 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -82,18 +82,23 @@
 
 
 class OutputFile(object):
-  def __init__(self, output_zip, input_dir, prefix, name):
-    self._output_zip = output_zip
-    self.input_name = os.path.join(input_dir, prefix, name)
+  """A helper class to write a generated file to the given dir or zip.
 
+  When generating images, we want the outputs to go into the given zip file, or
+  the given dir.
+
+  Attributes:
+    name: The name of the output file, regardless of the final destination.
+  """
+
+  def __init__(self, output_zip, input_dir, prefix, name):
+    # We write the intermediate output file under the given input_dir, even if
+    # the final destination is a zip archive.
+    self.name = os.path.join(input_dir, prefix, name)
+    self._output_zip = output_zip
     if self._output_zip:
       self._zip_name = os.path.join(prefix, name)
 
-      root, suffix = os.path.splitext(name)
-      self.name = common.MakeTempFile(prefix=root + '-', suffix=suffix)
-    else:
-      self.name = self.input_name
-
   def Write(self):
     if self._output_zip:
       common.ZipWrite(self._output_zip, self.name, self._zip_name)
@@ -114,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)))
@@ -129,20 +137,21 @@
   output_zip. Returns the name of the system image file."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("system.img already exists; no need to rebuild...")
-    return img.input_name
+    return img.name
 
   def output_sink(fn, data):
     ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
     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")
@@ -161,7 +170,7 @@
   and store it in output_zip."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system_other.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("system_other.img already exists; no need to rebuild...")
     return
 
@@ -173,9 +182,9 @@
   output_zip."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("vendor.img already exists; no need to rebuild...")
-    return img.input_name
+    return img.name
 
   block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.map")
   CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "vendor", img,
@@ -188,9 +197,9 @@
   output_zip."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "product.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("product.img already exists; no need to rebuild...")
-    return img.input_name
+    return img.name
 
   block_list = OutputFile(
       output_zip, OPTIONS.input_tmp, "IMAGES", "product.map")
@@ -206,9 +215,9 @@
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES",
                    "product_services.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("product_services.img already exists; no need to rebuild...")
-    return img.input_name
+    return img.name
 
   block_list = OutputFile(
       output_zip, OPTIONS.input_tmp, "IMAGES", "product_services.map")
@@ -222,9 +231,9 @@
   """Turn the contents of ODM into an odm image and store it in output_zip."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "odm.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("odm.img already exists; no need to rebuild...")
-    return img.input_name
+    return img.name
 
   block_list = OutputFile(
       output_zip, OPTIONS.input_tmp, "IMAGES", "odm.map")
@@ -241,9 +250,9 @@
   image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
   """
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "dtbo.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("dtbo.img already exists; no need to rebuild...")
-    return img.input_name
+    return img.name
 
   dtbo_prebuilt_path = os.path.join(
       OPTIONS.input_tmp, "PREBUILT_IMAGES", "dtbo.img")
@@ -252,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,
@@ -314,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")
@@ -324,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
@@ -344,7 +351,7 @@
   """
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "userdata.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("userdata.img already exists; no need to rebuild...")
     return
 
@@ -418,11 +425,11 @@
 
   img = OutputFile(
       output_zip, OPTIONS.input_tmp, "IMAGES", "{}.img".format(name))
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("%s.img already exists; not rebuilding...", name)
-    return img.input_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)
 
@@ -497,7 +504,7 @@
   """Create an empty cache image and store it in output_zip."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "cache.img")
-  if os.path.exists(img.input_name):
+  if os.path.exists(img.name):
     logger.info("cache.img already exists; no need to rebuild...")
     return
 
@@ -728,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"))
 
@@ -792,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")
@@ -859,11 +868,12 @@
     banner("vbmeta")
     AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
 
-  if OPTIONS.info_dict.get("build_super_partition"):
+  if OPTIONS.info_dict.get("build_super_partition") == "true":
     banner("super_empty")
     AddSuperEmpty(output_zip)
 
-    if OPTIONS.info_dict.get("dynamic_partition_retrofit") == "true":
+    if OPTIONS.info_dict.get(
+        "build_retrofit_dynamic_partitions_ota_package") == "true":
       banner("super split images")
       AddSuperSplit(output_zip)
 
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/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 80d4023..e5a9050 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -84,6 +84,7 @@
     self.extended = RangeSet()
     self.total_blocks = 0
     self.file_map = {}
+    self.hashtree_info = None
 
   def RangeSha1(self, ranges):
     return sha1().hexdigest()
@@ -483,7 +484,8 @@
       # choose the transfers for conversion. The number '1024' can be further
       # tweaked here to balance the package size and build time.
       if max_stashed_blocks > stash_limit + 1024:
-        self.SelectAndConvertDiffTransfersToNew()
+        self.SelectAndConvertDiffTransfersToNew(
+            max_stashed_blocks - stash_limit)
         # Regenerate the sequence as the graph has changed.
         self.FindSequenceForTransfers()
 
@@ -830,7 +832,8 @@
     num_of_bytes = new_blocks * self.tgt.blocksize
     logger.info(
         "  Total %d blocks (%d bytes) are packed as new blocks due to "
-        "insufficient cache size.", new_blocks, num_of_bytes)
+        "insufficient cache size. Maximum blocks stashed simultaneously: %d",
+        new_blocks, num_of_bytes, max_stashed_blocks)
     return new_blocks, max_stashed_blocks
 
   def ComputePatches(self, prefix):
@@ -1339,7 +1342,7 @@
 
     return patches
 
-  def SelectAndConvertDiffTransfersToNew(self):
+  def SelectAndConvertDiffTransfersToNew(self, violated_stash_blocks):
     """Converts the diff transfers to reduce the max simultaneous stash.
 
     Since the 'new' data is compressed with deflate, we can select the 'diff'
@@ -1347,6 +1350,8 @@
     compressed data. Ideally, we want to convert the transfers with a small
     size increase, but using a large number of stashed blocks.
     """
+    TransferSizeScore = namedtuple("TransferSizeScore",
+                                   "xf, used_stash_blocks, score")
 
     logger.info("Selecting diff commands to convert to new.")
     diff_queue = []
@@ -1360,7 +1365,7 @@
     # for the remaining.
     result = self.ComputePatchesForInputList(diff_queue, True)
 
-    removed_stashed_blocks = 0
+    conversion_candidates = []
     for xf_index, patch_info, compressed_size in result:
       xf = self.transfers[xf_index]
       if not xf.patch_info:
@@ -1368,21 +1373,43 @@
 
       size_ratio = len(xf.patch_info.content) * 100.0 / compressed_size
       diff_style = "imgdiff" if xf.patch_info.imgdiff else "bsdiff"
-      logger.info("%s, target size: %d, style: %s, patch size: %d,"
+      logger.info("%s, target size: %d blocks, style: %s, patch size: %d,"
                   " compression_size: %d, ratio %.2f%%", xf.tgt_name,
                   xf.tgt_ranges.size(), diff_style,
                   len(xf.patch_info.content), compressed_size, size_ratio)
 
+      used_stash_blocks = sum(sr.size() for _, sr in xf.use_stash)
       # Convert the transfer to new if the compressed size is smaller or equal.
       # We don't need to maintain the stash_before lists here because the
       # graph will be regenerated later.
       if len(xf.patch_info.content) >= compressed_size:
-        removed_stashed_blocks += sum(sr.size() for _, sr in xf.use_stash)
-        logger.info("Converting %s to new", xf.tgt_name)
-        xf.ConvertToNew()
+        # Add the transfer to the candidate list with negative score. And it
+        # will be converted later.
+        conversion_candidates.append(TransferSizeScore(xf, used_stash_blocks,
+                                                       -1))
+      elif used_stash_blocks > 0:
+        # This heuristic represents the size increase in the final package to
+        # remove per unit of stashed data.
+        score = ((compressed_size - len(xf.patch_info.content)) * 100.0
+                 / used_stash_blocks)
+        conversion_candidates.append(TransferSizeScore(xf, used_stash_blocks,
+                                                       score))
+    # Transfers with lower score (i.e. less expensive to convert) will be
+    # converted first.
+    conversion_candidates.sort(key=lambda x: x.score)
 
-    # TODO(xunchang) convert more transfers by sorting:
-    # (compressed size - patch_size) / used_stashed_blocks
+    # TODO(xunchang), improve the logic to find the transfers to convert, e.g.
+    # convert the ones that contribute to the max stash, run ReviseStashSize
+    # multiple times etc.
+    removed_stashed_blocks = 0
+    for xf, used_stash_blocks, _ in conversion_candidates:
+      logger.info("Converting %s to new", xf.tgt_name)
+      xf.ConvertToNew()
+      removed_stashed_blocks += used_stash_blocks
+      # Experiments show that we will get a smaller package size if we remove
+      # slightly more stashed blocks than the violated stash blocks.
+      if removed_stashed_blocks >= violated_stash_blocks:
+        break
 
     logger.info("Removed %d stashed blocks", removed_stashed_blocks)
 
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 146b868..bcbc921 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -75,26 +75,35 @@
   """
   cmd = ["find", path, "-print"]
   output = common.RunAndCheckOutput(cmd, verbose=False)
-  # increase by 25 % as number of files and directories is not whole picture.
-  return output.count('\n') * 30 // 24
+  # increase by > 4% as number of files and directories is not whole picture.
+  inodes = output.count('\n')
+  spare_inodes = inodes * 4 // 100
+  min_spare_inodes = 12
+  if spare_inodes < min_spare_inodes:
+    spare_inodes = min_spare_inodes
+  return inodes + spare_inodes
 
 
-def GetFilesystemCharacteristics(sparse_image_path):
-  """Returns various filesystem characteristics of "sparse_image_path".
+def GetFilesystemCharacteristics(image_path, sparse_image=True):
+  """Returns various filesystem characteristics of "image_path".
 
   Args:
-    sparse_image_path: The file to analyze.
+    image_path: The file to analyze.
+    sparse_image: Image is sparse
 
   Returns:
     The characteristics dictionary.
   """
-  unsparse_image_path = UnsparseImage(sparse_image_path, replace=False)
+  unsparse_image_path = image_path
+  if sparse_image:
+    unsparse_image_path = UnsparseImage(image_path, replace=False)
 
   cmd = ["tune2fs", "-l", unsparse_image_path]
   try:
     output = common.RunAndCheckOutput(cmd, verbose=False)
   finally:
-    os.remove(unsparse_image_path)
+    if sparse_image:
+      os.remove(unsparse_image_path)
   fs_dict = {}
   for line in output.splitlines():
     fields = line.split(":")
@@ -280,6 +289,7 @@
         build_command.extend(["-S", prop_dict["hash_seed"]])
     if "ext4_share_dup_blocks" in prop_dict:
       build_command.append("-c")
+    build_command.extend(["--inode_size", "256"])
     if "selinux_fc" in prop_dict:
       build_command.append(prop_dict["selinux_fc"])
   elif fs_type.startswith("squash"):
@@ -413,7 +423,10 @@
           "First Pass based on estimates of %d MB and %s inodes.",
           size // BYTES_IN_MB, prop_dict["extfs_inode_count"])
       BuildImageMkfs(in_dir, prop_dict, out_file, target_out, fs_config)
-      fs_dict = GetFilesystemCharacteristics(out_file)
+      sparse_image = False
+      if "extfs_sparse_flag" in prop_dict:
+        sparse_image = True
+      fs_dict = GetFilesystemCharacteristics(out_file, sparse_image)
       os.remove(out_file)
       block_size = int(fs_dict.get("Block size", "4096"))
       free_size = int(fs_dict.get("Free blocks", "0")) * block_size
@@ -427,16 +440,25 @@
       else:
         size -= free_size
         size += reserved_size
+        if reserved_size == 0:
+          # add .3% margin
+          size = size * 1003 // 1000
+        # Use a minimum size, otherwise we will fail to calculate an AVB footer
+        # or fail to construct an ext4 image.
+        size = max(size, 256 * 1024)
         if block_size <= 4096:
           size = common.RoundUpTo4K(size)
         else:
           size = ((size + block_size - 1) // block_size) * block_size
-        # Use a minimum size, otherwise we will fail to calculate an AVB footer
-        # or fail to construct an ext4 image.
-        size = max(size, 256 * 1024)
       extfs_inode_count = prop_dict["extfs_inode_count"]
       inodes = int(fs_dict.get("Inode count", extfs_inode_count))
       inodes -= int(fs_dict.get("Free inodes", "0"))
+      # add .2% margin or 1 inode, whichever is greater
+      spare_inodes = inodes * 2 // 1000
+      min_spare_inodes = 1
+      if spare_inodes < min_spare_inodes:
+        spare_inodes = min_spare_inodes
+      inodes += spare_inodes
       prop_dict["extfs_inode_count"] = str(inodes)
       prop_dict["partition_size"] = str(size)
       logger.info(
@@ -547,14 +569,14 @@
   elif mount_point == "system_other":
     # We inherit the selinux policies of /system since we contain some of its
     # files.
-    copy_prop("avb_system_hashtree_enable", "avb_hashtree_enable")
-    copy_prop("avb_system_add_hashtree_footer_args",
+    copy_prop("avb_system_other_hashtree_enable", "avb_hashtree_enable")
+    copy_prop("avb_system_other_add_hashtree_footer_args",
               "avb_add_hashtree_footer_args")
-    copy_prop("avb_system_key_path", "avb_key_path")
-    copy_prop("avb_system_algorithm", "avb_algorithm")
+    copy_prop("avb_system_other_key_path", "avb_key_path")
+    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")
@@ -701,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":
@@ -718,6 +740,28 @@
     f.writelines(["%s=%s" % (key, value) for (key, value) in glob_dict.items()])
 
 
+def ExtractSystemOtherAvbKey(in_dir, glob_dict):
+  if glob_dict.get("avb_system_extract_system_other_key") != "true":
+    return
+
+  extract_to = os.path.join(in_dir, "etc/security/avb/system_other.avbpubkey")
+  extract_to_dir = os.path.dirname(extract_to)
+
+  if os.path.isdir(extract_to_dir):
+    shutil.rmtree(extract_to_dir)
+  elif os.path.isfile(extract_to_dir):
+    os.remove(extract_to_dir)
+  os.mkdir(extract_to_dir);
+
+  # Extracts the public key used to sign system_other.img, into system.img:
+  #   /system/etc/security/avb/system_other.avbpubkey.
+  avbtool = glob_dict.get("avb_avbtool")
+  extract_from = glob_dict.get("avb_system_other_key_path")
+  cmd = [avbtool, "extract_public_key", "--key", extract_from,
+         "--output", extract_to]
+  common.RunAndCheckOutput(cmd, verbose=False)
+
+
 def main(argv):
   if len(argv) < 4 or len(argv) > 5:
     print(__doc__)
@@ -741,6 +785,7 @@
     mount_point = ""
     if image_filename == "system.img":
       mount_point = "system"
+      ExtractSystemOtherAvbKey(in_dir, glob_dict)
     elif image_filename == "system_other.img":
       mount_point = "system_other"
     elif image_filename == "userdata.img":
diff --git a/tools/releasetools/build_super_image.py b/tools/releasetools/build_super_image.py
index bb0e641..38ea3d6 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..9b76954 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
@@ -415,6 +418,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 dcc083c..780b9c1 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -14,6 +14,7 @@
 
 from __future__ import print_function
 
+import collections
 import copy
 import errno
 import getopt
@@ -45,9 +46,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)
@@ -189,6 +197,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.
 
@@ -522,11 +553,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)
@@ -587,6 +614,11 @@
     cmd.append("--second")
     cmd.append(fn)
 
+  fn = os.path.join(sourcedir, "dtb")
+  if os.access(fn, os.F_OK):
+    cmd.append("--dtb")
+    cmd.append(fn)
+
   fn = os.path.join(sourcedir, "cmdline")
   if os.access(fn, os.F_OK):
     cmd.append("--cmdline")
@@ -672,7 +704,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",
@@ -739,30 +771,46 @@
     shutil.copyfileobj(in_file, out_file)
 
 
+def UnzipToDir(filename, dirname, pattern=None):
+  """Unzips the archive to the given directory.
+
+  Args:
+    filename: The name of the zip file to unzip.
+
+    dirname: Where the unziped files will land.
+
+    pattern: Files to unzip from the archive. If omitted, will unzip the entire
+    archvie.
+  """
+
+  cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
+  if pattern is not None:
+    cmd.extend(pattern)
+  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
 
@@ -1523,6 +1571,13 @@
     """Called at the start of full OTA installation."""
     return self._DoCall("FullOTA_InstallBegin")
 
+  def FullOTA_GetBlockDifferences(self):
+    """Called during full OTA installation and verification.
+    Implementation should return a list of BlockDifference objects describing
+    the update on each additional partitions.
+    """
+    return self._DoCall("FullOTA_GetBlockDifferences")
+
   def FullOTA_InstallEnd(self):
     """Called at the end of full OTA installation; typically this is
     used to install the image for the device's baseband processor."""
@@ -1551,6 +1606,13 @@
     verification is complete)."""
     return self._DoCall("IncrementalOTA_InstallBegin")
 
+  def IncrementalOTA_GetBlockDifferences(self):
+    """Called during incremental OTA installation and verification.
+    Implementation should return a list of BlockDifference objects describing
+    the update on each additional partitions.
+    """
+    return self._DoCall("IncrementalOTA_GetBlockDifferences")
+
   def IncrementalOTA_InstallEnd(self):
     """Called at the end of incremental OTA installation; typically
     this is used to install the image for the device's baseband
@@ -1745,11 +1807,35 @@
     self.touched_src_ranges = b.touched_src_ranges
     self.touched_src_sha1 = b.touched_src_sha1
 
-    if src is None:
-      _, self.device = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+    # On devices with dynamic partitions, for new partitions,
+    # src is None but OPTIONS.source_info_dict is not.
+    if OPTIONS.source_info_dict is None:
+      is_dynamic_build = OPTIONS.info_dict.get(
+          "use_dynamic_partitions") == "true"
+      is_dynamic_source = False
     else:
-      _, self.device = GetTypeAndDevice("/" + partition,
-                                        OPTIONS.source_info_dict)
+      is_dynamic_build = OPTIONS.source_info_dict.get(
+          "use_dynamic_partitions") == "true"
+      is_dynamic_source = partition in shlex.split(
+          OPTIONS.source_info_dict.get("dynamic_partition_list", "").strip())
+
+    is_dynamic_target = partition in shlex.split(
+        OPTIONS.info_dict.get("dynamic_partition_list", "").strip())
+
+    # For dynamic partitions builds, check partition list in both source
+    # and target build because new partitions may be added, and existing
+    # partitions may be removed.
+    is_dynamic = is_dynamic_build and (is_dynamic_source or is_dynamic_target)
+
+    if is_dynamic:
+      self.device = 'map_partition("%s")' % partition
+    else:
+      if OPTIONS.source_info_dict is None:
+        _, device_path = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+      else:
+        _, device_path = GetTypeAndDevice("/" + partition,
+                                          OPTIONS.source_info_dict)
+      self.device = '"%s"' % device_path
 
   @property
   def required_cache(self):
@@ -1768,7 +1854,7 @@
     self._WriteUpdate(script, output_zip)
 
     if write_verify_script:
-      self._WritePostInstallVerifyScript(script)
+      self.WritePostInstallVerifyScript(script)
 
   def WriteStrictVerifyScript(self, script):
     """Verify all the blocks in the care_map, including clobbered blocks.
@@ -1782,11 +1868,11 @@
     ranges = self.tgt.care_map
     ranges_str = ranges.to_string_raw()
     script.AppendExtra(
-        'range_sha1("%s", "%s") == "%s" && ui_print("    Verified.") || '
-        'ui_print("\\"%s\\" has unexpected contents.");' % (
+        'range_sha1(%s, "%s") == "%s" && ui_print("    Verified.") || '
+        'ui_print("%s has unexpected contents.");' % (
             self.device, ranges_str,
             self.tgt.TotalSha1(include_clobbered_blocks=True),
-            self.device))
+            self.partition))
     script.AppendExtra("")
 
   def WriteVerifyScript(self, script, touched_blocks_only=False):
@@ -1811,7 +1897,7 @@
 
       ranges_str = ranges.to_string_raw()
       script.AppendExtra(
-          'if (range_sha1("%s", "%s") == "%s" || block_image_verify("%s", '
+          'if (range_sha1(%s, "%s") == "%s" || block_image_verify(%s, '
           'package_extract_file("%s.transfer.list"), "%s.new.dat", '
           '"%s.patch.dat")) then' % (
               self.device, ranges_str, expected_sha1,
@@ -1828,7 +1914,7 @@
         # this check fails, give an explicit log message about the partition
         # having been remounted R/W (the most likely explanation).
         if self.check_first_block:
-          script.AppendExtra('check_first_block("%s");' % (self.device,))
+          script.AppendExtra('check_first_block(%s);' % (self.device,))
 
         # If version >= 4, try block recovery before abort update
         if partition == "system":
@@ -1836,8 +1922,8 @@
         else:
           code = ErrorCode.VENDOR_RECOVER_FAILURE
         script.AppendExtra((
-            'ifelse (block_image_recover("{device}", "{ranges}") && '
-            'block_image_verify("{device}", '
+            'ifelse (block_image_recover({device}, "{ranges}") && '
+            'block_image_verify({device}, '
             'package_extract_file("{partition}.transfer.list"), '
             '"{partition}.new.dat", "{partition}.patch.dat"), '
             'ui_print("{partition} recovered successfully."), '
@@ -1859,14 +1945,14 @@
             'abort("E%d: %s partition has unexpected contents");\n'
             'endif;') % (code, partition))
 
-  def _WritePostInstallVerifyScript(self, script):
+  def WritePostInstallVerifyScript(self, script):
     partition = self.partition
     script.Print('Verifying the updated %s image...' % (partition,))
     # Unlike pre-install verification, clobbered_blocks should not be ignored.
     ranges = self.tgt.care_map
     ranges_str = ranges.to_string_raw()
     script.AppendExtra(
-        'if range_sha1("%s", "%s") == "%s" then' % (
+        'if range_sha1(%s, "%s") == "%s" then' % (
             self.device, ranges_str,
             self.tgt.TotalSha1(include_clobbered_blocks=True)))
 
@@ -1875,7 +1961,7 @@
     if self.tgt.extended:
       ranges_str = self.tgt.extended.to_string_raw()
       script.AppendExtra(
-          'if range_sha1("%s", "%s") == "%s" then' % (
+          'if range_sha1(%s, "%s") == "%s" then' % (
               self.device, ranges_str,
               self._HashZeroBlocks(self.tgt.extended.size())))
       script.Print('Verified the updated %s image.' % (partition,))
@@ -1941,7 +2027,7 @@
     else:
       code = ErrorCode.VENDOR_UPDATE_FAILURE
 
-    call = ('block_image_update("{device}", '
+    call = ('block_image_update({device}, '
             'package_extract_file("{partition}.transfer.list"), '
             '"{new_data_name}", "{partition}.patch.dat") ||\n'
             '  abort("E{code}: Failed to update {partition} image.");'.format(
@@ -2034,6 +2120,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.
@@ -2134,3 +2235,219 @@
   logger.info("putting script in %s", sh_location)
 
   output_sink(sh_location, sh)
+
+
+class DynamicPartitionUpdate(object):
+  def __init__(self, src_group=None, tgt_group=None, progress=None,
+               block_difference=None):
+    self.src_group = src_group
+    self.tgt_group = tgt_group
+    self.progress = progress
+    self.block_difference = block_difference
+
+  @property
+  def src_size(self):
+    if not self.block_difference:
+      return 0
+    return DynamicPartitionUpdate._GetSparseImageSize(self.block_difference.src)
+
+  @property
+  def tgt_size(self):
+    if not self.block_difference:
+      return 0
+    return DynamicPartitionUpdate._GetSparseImageSize(self.block_difference.tgt)
+
+  @staticmethod
+  def _GetSparseImageSize(img):
+    if not img:
+      return 0
+    return img.blocksize * img.total_blocks
+
+
+class DynamicGroupUpdate(object):
+  def __init__(self, src_size=None, tgt_size=None):
+    # None: group does not exist. 0: no size limits.
+    self.src_size = src_size
+    self.tgt_size = tgt_size
+
+
+class DynamicPartitionsDifference(object):
+  def __init__(self, info_dict, block_diffs, progress_dict=None,
+               source_info_dict=None):
+    if progress_dict is None:
+      progress_dict = dict()
+
+    self._remove_all_before_apply = False
+    if source_info_dict is None:
+      self._remove_all_before_apply = True
+      source_info_dict = dict()
+
+    block_diff_dict = {e.partition:e for e in block_diffs}
+    assert len(block_diff_dict) == len(block_diffs), \
+        "Duplicated BlockDifference object for {}".format(
+            [partition for partition, count in
+             collections.Counter(e.partition for e in block_diffs).items()
+             if count > 1])
+
+    self._partition_updates = collections.OrderedDict()
+
+    for p, block_diff in block_diff_dict.items():
+      self._partition_updates[p] = DynamicPartitionUpdate()
+      self._partition_updates[p].block_difference = block_diff
+
+    for p, progress in progress_dict.items():
+      if p in self._partition_updates:
+        self._partition_updates[p].progress = progress
+
+    tgt_groups = shlex.split(info_dict.get(
+        "super_partition_groups", "").strip())
+    src_groups = shlex.split(source_info_dict.get(
+        "super_partition_groups", "").strip())
+
+    for g in tgt_groups:
+      for p in shlex.split(info_dict.get(
+          "super_%s_partition_list" % g, "").strip()):
+        assert p in self._partition_updates, \
+            "{} is in target super_{}_partition_list but no BlockDifference " \
+            "object is provided.".format(p, g)
+        self._partition_updates[p].tgt_group = g
+
+    for g in src_groups:
+      for p in shlex.split(source_info_dict.get(
+          "super_%s_partition_list" % g, "").strip()):
+        assert p in self._partition_updates, \
+            "{} is in source super_{}_partition_list but no BlockDifference " \
+            "object is provided.".format(p, g)
+        self._partition_updates[p].src_group = g
+
+    target_dynamic_partitions = set(shlex.split(info_dict.get(
+        "dynamic_partition_list", "").strip()))
+    block_diffs_with_target = set(p for p, u in self._partition_updates.items()
+                                  if u.tgt_size)
+    assert block_diffs_with_target == target_dynamic_partitions, \
+        "Target Dynamic partitions: {}, BlockDifference with target: {}".format(
+            list(target_dynamic_partitions), list(block_diffs_with_target))
+
+    source_dynamic_partitions = set(shlex.split(source_info_dict.get(
+        "dynamic_partition_list", "").strip()))
+    block_diffs_with_source = set(p for p, u in self._partition_updates.items()
+                                  if u.src_size)
+    assert block_diffs_with_source == source_dynamic_partitions, \
+        "Source Dynamic partitions: {}, BlockDifference with source: {}".format(
+            list(source_dynamic_partitions), list(block_diffs_with_source))
+
+    if self._partition_updates:
+      logger.info("Updating dynamic partitions %s",
+                  self._partition_updates.keys())
+
+    self._group_updates = collections.OrderedDict()
+
+    for g in tgt_groups:
+      self._group_updates[g] = DynamicGroupUpdate()
+      self._group_updates[g].tgt_size = int(info_dict.get(
+          "super_%s_group_size" % g, "0").strip())
+
+    for g in src_groups:
+      if g not in self._group_updates:
+        self._group_updates[g] = DynamicGroupUpdate()
+      self._group_updates[g].src_size = int(source_info_dict.get(
+          "super_%s_group_size" % g, "0").strip())
+
+    self._Compute()
+
+  def WriteScript(self, script, output_zip, write_verify_script=False):
+    script.Comment('--- Start patching dynamic partitions ---')
+    for p, u in self._partition_updates.items():
+      if u.src_size and u.tgt_size and u.src_size > u.tgt_size:
+        script.Comment('Patch partition %s' % p)
+        u.block_difference.WriteScript(script, output_zip, progress=u.progress,
+                                       write_verify_script=False)
+
+    op_list_path = MakeTempFile()
+    with open(op_list_path, 'w') as f:
+      for line in self._op_list:
+        f.write('{}\n'.format(line))
+
+    ZipWrite(output_zip, op_list_path, "dynamic_partitions_op_list")
+
+    script.Comment('Update dynamic partition metadata')
+    script.AppendExtra('assert(update_dynamic_partitions('
+                       'package_extract_file("dynamic_partitions_op_list")));')
+
+    if write_verify_script:
+      for p, u in self._partition_updates.items():
+        if u.src_size and u.tgt_size and u.src_size > u.tgt_size:
+          u.block_difference.WritePostInstallVerifyScript(script)
+          script.AppendExtra('unmap_partition("%s");' % p) # ignore errors
+
+    for p, u in self._partition_updates.items():
+      if u.tgt_size and u.src_size <= u.tgt_size:
+        script.Comment('Patch partition %s' % p)
+        u.block_difference.WriteScript(script, output_zip, progress=u.progress,
+                                       write_verify_script=write_verify_script)
+        if write_verify_script:
+          script.AppendExtra('unmap_partition("%s");' % p) # ignore errors
+
+    script.Comment('--- End patching dynamic partitions ---')
+
+  def _Compute(self):
+    self._op_list = list()
+
+    def append(line):
+      self._op_list.append(line)
+
+    def comment(line):
+      self._op_list.append("# %s" % line)
+
+    if self._remove_all_before_apply:
+      comment('Remove all existing dynamic partitions and groups before '
+              'applying full OTA')
+      append('remove_all_groups')
+
+    for p, u in self._partition_updates.items():
+      if u.src_group and not u.tgt_group:
+        append('remove %s' % p)
+
+    for p, u in self._partition_updates.items():
+      if u.src_group and u.tgt_group and u.src_group != u.tgt_group:
+        comment('Move partition %s from %s to default' % (p, u.src_group))
+        append('move %s default' % p)
+
+    for p, u in self._partition_updates.items():
+      if u.src_size and u.tgt_size and u.src_size > u.tgt_size:
+        comment('Shrink partition %s from %d to %d' %
+                (p, u.src_size, u.tgt_size))
+        append('resize %s %s' % (p, u.tgt_size))
+
+    for g, u in self._group_updates.items():
+      if u.src_size is not None and u.tgt_size is None:
+        append('remove_group %s' % g)
+      if (u.src_size is not None and u.tgt_size is not None and
+          u.src_size > u.tgt_size):
+        comment('Shrink group %s from %d to %d' % (g, u.src_size, u.tgt_size))
+        append('resize_group %s %d' % (g, u.tgt_size))
+
+    for g, u in self._group_updates.items():
+      if u.src_size is None and u.tgt_size is not None:
+        comment('Add group %s with maximum size %d' % (g, u.tgt_size))
+        append('add_group %s %d' % (g, u.tgt_size))
+      if (u.src_size is not None and u.tgt_size is not None and
+          u.src_size < u.tgt_size):
+        comment('Grow group %s from %d to %d' % (g, u.src_size, u.tgt_size))
+        append('resize_group %s %d' % (g, u.tgt_size))
+
+    for p, u in self._partition_updates.items():
+      if u.tgt_group and not u.src_group:
+        comment('Add partition %s to group %s' % (p, u.tgt_group))
+        append('add %s %s' % (p, u.tgt_group))
+
+    for p, u in self._partition_updates.items():
+      if u.tgt_size and u.src_size < u.tgt_size:
+        comment('Grow partition %s from %d to %d' % (p, u.src_size, u.tgt_size))
+        append('resize %s %d' % (p, u.tgt_size))
+
+    for p, u in self._partition_updates.items():
+      if u.src_group and u.tgt_group and u.src_group != u.tgt_group:
+        comment('Move partition %s from default to %s' %
+                (p, u.tgt_group))
+        append('move %s %s' % (p, u.tgt_group))
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
new file mode 100755
index 0000000..1d62e3b
--- /dev/null
+++ b/tools/releasetools/merge_target_files.py
@@ -0,0 +1,737 @@
+#!/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.
+"""
+
+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, other_item_list):
+  """Performs validations on the merge config lists.
+
+  Args:
+    system_item_list: The list of items to extract from the partial
+    system target files package as is.
+
+    other_item_list: The list of items to extract from the partial
+    other target files package as is.
+
+  Returns:
+    False if a validation fails, otherwise true.
+  """
+  default_combined_item_set = set(default_system_item_list)
+  default_combined_item_set.update(default_other_item_list)
+
+  combined_item_set = set(system_item_list)
+  combined_item_set.update(other_item_list)
+
+  # Check that the merge config lists are not missing any item specified
+  # by the default config lists.
+  difference = default_combined_item_set.difference(combined_item_set)
+  if difference:
+    logger.error('Missing merge config items: %s' % list(difference))
+    logger.error('Please ensure missing items are in either the '
+                 'system-item-list or other-item-list files provided to '
+                 'this script.')
+    return False
+
+  return True
+
+
+def process_ab_partitions_txt(
+    system_target_files_temp_dir,
+    other_target_files_temp_dir,
+    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 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]
+
+  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):
+  """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.
+  """
+
+  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)
+
+  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)
+
+  # 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,
+      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 7ec8ad8..fe40936 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'
+AB_PARTITIONS = 'META/ab_partitions.txt'
 UNZIP_PATTERN = ['IMAGES/*', 'META/*']
-SUPER_SPLIT_PATTERN = ['OTA/super_*.img']
+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)
@@ -826,32 +890,51 @@
   # See the notes in WriteBlockIncrementalOTAPackage().
   allow_shared_blocks = target_info.get('ext4_share_dup_blocks') == "true"
 
-  # Full OTA is done as an "incremental" against an empty source image. This
-  # has the effect of writing new data from the package to the entire
-  # partition, but lets us reuse the updater code that writes incrementals to
-  # do it.
-  system_tgt = common.GetSparseImage("system", OPTIONS.input_tmp, input_zip,
-                                     allow_shared_blocks)
-  system_tgt.ResetFileMap()
-  system_diff = common.BlockDifference("system", system_tgt, src=None)
-  system_diff.WriteScript(script, output_zip,
-                          write_verify_script=OPTIONS.verify)
+  def GetBlockDifference(partition):
+    # Full OTA is done as an "incremental" against an empty source image. This
+    # has the effect of writing new data from the package to the entire
+    # partition, but lets us reuse the updater code that writes incrementals to
+    # do it.
+    tgt = common.GetSparseImage(partition, OPTIONS.input_tmp, input_zip,
+                                allow_shared_blocks)
+    tgt.ResetFileMap()
+    diff = common.BlockDifference(partition, tgt, src=None)
+    return diff
 
-  boot_img = common.GetBootableImage(
-      "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
+  device_specific_diffs = device_specific.FullOTA_GetBlockDifferences()
+  if device_specific_diffs:
+    assert all(isinstance(diff, common.BlockDifference)
+               for diff in device_specific_diffs), \
+        "FullOTA_GetBlockDifferences is not returning a list of " \
+        "BlockDifference objects"
 
+  progress_dict = dict()
+  block_diffs = [GetBlockDifference("system")]
   if HasVendorPartition(input_zip):
-    script.ShowProgress(0.1, 0)
+    block_diffs.append(GetBlockDifference("vendor"))
+    progress_dict["vendor"] = 0.1
+  if device_specific_diffs:
+    block_diffs += device_specific_diffs
 
-    vendor_tgt = common.GetSparseImage("vendor", OPTIONS.input_tmp, input_zip,
-                                       allow_shared_blocks)
-    vendor_tgt.ResetFileMap()
-    vendor_diff = common.BlockDifference("vendor", vendor_tgt)
-    vendor_diff.WriteScript(script, output_zip,
-                            write_verify_script=OPTIONS.verify)
+  if target_info.get('use_dynamic_partitions') == "true":
+    # Use empty source_info_dict to indicate that all partitions / groups must
+    # be re-added.
+    dynamic_partitions_diff = common.DynamicPartitionsDifference(
+        info_dict=OPTIONS.info_dict,
+        block_diffs=block_diffs,
+        progress_dict=progress_dict)
+    dynamic_partitions_diff.WriteScript(script, output_zip,
+                                        write_verify_script=OPTIONS.verify)
+  else:
+    for block_diff in block_diffs:
+      block_diff.WriteScript(script, output_zip,
+                             progress=progress_dict.get(block_diff.partition),
+                             write_verify_script=OPTIONS.verify)
 
   AddCompatibilityArchiveIfTrebleEnabled(input_zip, output_zip, target_info)
 
+  boot_img = common.GetBootableImage(
+      "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
   common.CheckSize(boot_img.data, "boot.img", target_info)
   common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
 
@@ -901,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):
@@ -966,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
@@ -1348,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)
@@ -1571,18 +1674,43 @@
   system_diff.WriteVerifyScript(script, touched_blocks_only=True)
   if vendor_diff:
     vendor_diff.WriteVerifyScript(script, touched_blocks_only=True)
+  device_specific_diffs = device_specific.IncrementalOTA_GetBlockDifferences()
+  if device_specific_diffs:
+    assert all(isinstance(diff, common.BlockDifference)
+               for diff in device_specific_diffs), \
+        "IncrementalOTA_GetBlockDifferences is not returning a list of " \
+        "BlockDifference objects"
+    for diff in device_specific_diffs:
+      diff.WriteVerifyScript(script, touched_blocks_only=True)
 
   script.Comment("---- start making changes here ----")
 
   device_specific.IncrementalOTA_InstallBegin()
 
-  system_diff.WriteScript(script, output_zip,
-                          progress=0.8 if vendor_diff else 0.9,
-                          write_verify_script=OPTIONS.verify)
-
+  block_diffs = [system_diff]
+  progress_dict = {"system": 0.8 if vendor_diff else 0.9}
   if vendor_diff:
-    vendor_diff.WriteScript(script, output_zip, progress=0.1,
-                            write_verify_script=OPTIONS.verify)
+    block_diffs.append(vendor_diff)
+    progress_dict["vendor"] = 0.1
+  if device_specific_diffs:
+    block_diffs += device_specific_diffs
+
+  if OPTIONS.source_info_dict.get("use_dynamic_partitions") == "true":
+    if OPTIONS.target_info_dict.get("use_dynamic_partitions") != "true":
+      raise RuntimeError(
+          "can't generate incremental that disables dynamic partitions")
+    dynamic_partitions_diff = common.DynamicPartitionsDifference(
+        info_dict=OPTIONS.target_info_dict,
+        source_info_dict=OPTIONS.source_info_dict,
+        block_diffs=block_diffs,
+        progress_dict=progress_dict)
+    dynamic_partitions_diff.WriteScript(
+        script, output_zip, write_verify_script=OPTIONS.verify)
+  else:
+    for block_diff in block_diffs:
+      block_diff.WriteScript(script, output_zip,
+                             progress=progress_dict.get(block_diff.partition),
+                             write_verify_script=OPTIONS.verify)
 
   if OPTIONS.two_step:
     common.ZipWriteStr(output_zip, "boot.img", target_boot.data)
@@ -1728,7 +1856,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
@@ -1737,6 +1866,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
@@ -1753,8 +1883,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.
@@ -1766,7 +1922,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.
@@ -1776,6 +1931,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
@@ -1804,7 +1962,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)
 
@@ -1939,6 +2098,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
@@ -1970,6 +2133,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 de3ead6..71598e3 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
@@ -90,7 +96,7 @@
       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,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,69 @@
   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/o 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:
+    (signed_apex, payload_key_name): signed_apex is the path to the signed APEX
+        file; payload_key_name is a str of the payload signing key name (e.g.
+        com.android.tzdata).
+  """
+  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'
+
+  # Signing an APEX is a two step process.
+  # 1. 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)
+
+  common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
+  apex_zip = zipfile.ZipFile(apex_file, 'a')
+  common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
+  common.ZipClose(apex_zip)
+
+  # 2. Sign the overall APEX container with container_key.
+  signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
+  common.SignFile(
+      apex_file,
+      signed_apex,
+      container_key,
+      container_pw,
+      codename_to_api_level_map=codename_to_api_level_map)
+
+  signed_and_aligned_apex = common.MakeTempFile(
+      prefix='apex-container-', suffix='.apex')
+  common.RunAndCheckOutput(
+      ['zipalign', '-f', '4096', signed_apex, signed_and_aligned_apex])
+
+  return (signed_and_aligned_apex, payload_info['apex.key'])
+
+
 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.
@@ -304,11 +448,19 @@
        if GetApkFileInfo(i.filename, compressed_extension, [])[0]])
   system_root_image = misc_info.get("system_root_image") == "true"
 
+  # A dict of APEX payload public keys that should be updated, i.e. the files
+  # under '/system/etc/security/apex/'.
+  updated_apex_payload_keys = {}
+
   for info in input_tf_zip.infolist():
     filename = info.filename
     if filename.startswith("IMAGES/"):
       continue
 
+    # Skip split super images, which will be re-generated during signing.
+    if filename.startswith("OTA/") and filename.endswith(".img"):
+      continue
+
     data = input_tf_zip.read(filename)
     out_info = copy.copy(info)
     (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
@@ -327,7 +479,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,
@@ -340,6 +492,40 @@
             "        (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, payload_key_name) = SignApex(
+            data,
+            payload_key,
+            container_key,
+            key_passwords[container_key],
+            codename_to_api_level_map,
+            OPTIONS.avb_extra_args.get('apex'))
+        common.ZipWrite(output_tf_zip, signed_apex, filename)
+        updated_apex_payload_keys[payload_key_name] = payload_key
+
+      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 +588,32 @@
     else:
       common.ZipWriteStr(output_tf_zip, out_info, data)
 
+  # Update APEX payload public keys.
+  for info in input_tf_zip.infolist():
+    filename = info.filename
+    if (os.path.dirname(filename) != 'SYSTEM/etc/security/apex' or
+        filename == 'SYSTEM/etc/security/apex/'):
+      continue
+
+    name = os.path.basename(filename)
+
+    # Skip PRESIGNED APEXes.
+    if name not in updated_apex_payload_keys:
+      continue
+
+    key_path = updated_apex_payload_keys[name]
+    if not os.path.exists(key_path) and not key_path.endswith('.pem'):
+      key_path = '{}.pem'.format(key_path)
+    assert os.path.exists(key_path), \
+        'Failed to find public key file {} for APEX {}'.format(
+            updated_apex_payload_keys[name], name)
+
+    print('Replacing APEX payload public key for {} with {}'.format(
+        name, key_path))
+
+    public_key = common.ExtractAvbPublicKey(key_path)
+    common.ZipWrite(output_tf_zip, public_key, arcname=filename)
+
   if OPTIONS.replace_ota_keys:
     ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info)
 
@@ -812,11 +1024,72 @@
   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_public_key = matches.group("PAYLOAD_PUBLIC_KEY")
+    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])
+
+    PAYLOAD_PUBLIC_KEY_SUFFIX = '.avbpubkey'
+    PAYLOAD_PRIVATE_KEY_SUFFIX = '.pem'
+    if not CompareKeys(
+        payload_public_key, PAYLOAD_PUBLIC_KEY_SUFFIX,
+        payload_private_key, PAYLOAD_PRIVATE_KEY_SUFFIX):
+      raise ValueError("Failed to parse payload keys: \n{}".format(line))
+
+    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 = []
@@ -827,6 +1100,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]
@@ -883,6 +1159,8 @@
       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
@@ -892,6 +1170,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=",
@@ -900,6 +1179,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=",
@@ -922,6 +1202,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,
@@ -931,18 +1213,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/target_files_diff.py b/tools/releasetools/target_files_diff.py
index 7415f27..4402c8d 100755
--- a/tools/releasetools/target_files_diff.py
+++ b/tools/releasetools/target_files_diff.py
@@ -71,7 +71,6 @@
              'ro.build.user=',
              'ro.build.description=',
              'ro.build.fingerprint=',
-             'ro.expect.recovery_id=',
              'ro.vendor.build.date=',
              'ro.vendor.build.date.utc=',
              'ro.vendor.build.fingerprint=']
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 c99049a..8709124 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -27,6 +27,7 @@
 import validate_target_files
 from rangelib import RangeSet
 
+from blockimgdiff import EmptyImage, DataImage
 
 KiB = 1024
 MiB = 1024 * KiB
@@ -490,6 +491,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')
 
@@ -988,3 +996,236 @@
                              recovery_image, boot_image, self._info)
     validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
                                                         self._info)
+
+
+class MockScriptWriter(object):
+  """A class that mocks edify_generator.EdifyGenerator.
+  """
+  def __init__(self, enable_comments=False):
+    self.lines = []
+    self.enable_comments = enable_comments
+  def Comment(self, comment):
+    if self.enable_comments:
+      self.lines.append("# {}".format(comment))
+  def AppendExtra(self, extra):
+    self.lines.append(extra)
+  def __str__(self):
+    return "\n".join(self.lines)
+
+
+class MockBlockDifference(object):
+  def __init__(self, partition, tgt, src=None):
+    self.partition = partition
+    self.tgt = tgt
+    self.src = src
+  def WriteScript(self, script, _, progress=None,
+                  write_verify_script=False):
+    if progress:
+      script.AppendExtra("progress({})".format(progress))
+    script.AppendExtra("patch({});".format(self.partition))
+    if write_verify_script:
+      self.WritePostInstallVerifyScript(script)
+  def WritePostInstallVerifyScript(self, script):
+    script.AppendExtra("verify({});".format(self.partition))
+
+
+class FakeSparseImage(object):
+  def __init__(self, size):
+    self.blocksize = 4096
+    self.total_blocks = size // 4096
+    assert size % 4096 == 0, "{} is not a multiple of 4096".format(size)
+
+
+class DynamicPartitionsDifferenceTest(test_utils.ReleaseToolsTestCase):
+  @staticmethod
+  def get_op_list(output_path):
+    with zipfile.ZipFile(output_path, 'r') as output_zip:
+      with output_zip.open("dynamic_partitions_op_list") as op_list:
+        return [line.strip() for line in op_list.readlines()
+                if not line.startswith("#")]
+
+  def setUp(self):
+    self.script = MockScriptWriter()
+    self.output_path = common.MakeTempFile(suffix='.zip')
+
+  def test_full(self):
+    target_info = common.LoadDictionaryFromLines("""
+dynamic_partition_list=system vendor
+super_partition_groups=group_foo
+super_group_foo_group_size={group_size}
+super_group_foo_partition_list=system vendor
+""".format(group_size=4 * GiB).split("\n"))
+    block_diffs = [MockBlockDifference("system", FakeSparseImage(3 * GiB)),
+                   MockBlockDifference("vendor", FakeSparseImage(1 * GiB))]
+
+    dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs)
+    with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+      dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
+
+    self.assertEqual(str(self.script).strip(), """
+assert(update_dynamic_partitions(package_extract_file("dynamic_partitions_op_list")));
+patch(vendor);
+verify(vendor);
+unmap_partition("vendor");
+patch(system);
+verify(system);
+unmap_partition("system");
+""".strip())
+
+    lines = self.get_op_list(self.output_path)
+
+    remove_all_groups = lines.index("remove_all_groups")
+    add_group = lines.index("add_group group_foo 4294967296")
+    add_vendor = lines.index("add vendor group_foo")
+    add_system = lines.index("add system group_foo")
+    resize_vendor = lines.index("resize vendor 1073741824")
+    resize_system = lines.index("resize system 3221225472")
+
+    self.assertLess(remove_all_groups, add_group,
+                    "Should add groups after removing all groups")
+    self.assertLess(add_group, min(add_vendor, add_system),
+                    "Should add partitions after adding group")
+    self.assertLess(add_system, resize_system,
+                    "Should resize system after adding it")
+    self.assertLess(add_vendor, resize_vendor,
+                    "Should resize vendor after adding it")
+
+  def test_inc_groups(self):
+    source_info = common.LoadDictionaryFromLines("""
+super_partition_groups=group_foo group_bar group_baz
+super_group_foo_group_size={group_foo_size}
+super_group_bar_group_size={group_bar_size}
+""".format(group_foo_size=4 * GiB, group_bar_size=3 * GiB).split("\n"))
+    target_info = common.LoadDictionaryFromLines("""
+super_partition_groups=group_foo group_baz group_qux
+super_group_foo_group_size={group_foo_size}
+super_group_baz_group_size={group_baz_size}
+super_group_qux_group_size={group_qux_size}
+""".format(group_foo_size=3 * GiB, group_baz_size=4 * GiB,
+           group_qux_size=1 * GiB).split("\n"))
+
+    dp_diff = common.DynamicPartitionsDifference(target_info,
+                                                 block_diffs=[],
+                                                 source_info_dict=source_info)
+    with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+      dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
+
+    lines = self.get_op_list(self.output_path)
+
+    removed = lines.index("remove_group group_bar")
+    shrunk = lines.index("resize_group group_foo 3221225472")
+    grown = lines.index("resize_group group_baz 4294967296")
+    added = lines.index("add_group group_qux 1073741824")
+
+    self.assertLess(max(removed, shrunk) < min(grown, added),
+                    "ops that remove / shrink partitions must precede ops that "
+                    "grow / add partitions")
+
+  def test_incremental(self):
+    source_info = common.LoadDictionaryFromLines("""
+dynamic_partition_list=system vendor product product_services
+super_partition_groups=group_foo
+super_group_foo_group_size={group_foo_size}
+super_group_foo_partition_list=system vendor product product_services
+""".format(group_foo_size=4 * GiB).split("\n"))
+    target_info = common.LoadDictionaryFromLines("""
+dynamic_partition_list=system vendor product odm
+super_partition_groups=group_foo group_bar
+super_group_foo_group_size={group_foo_size}
+super_group_foo_partition_list=system vendor odm
+super_group_bar_group_size={group_bar_size}
+super_group_bar_partition_list=product
+""".format(group_foo_size=3 * GiB, group_bar_size=1 * GiB).split("\n"))
+
+    block_diffs = [MockBlockDifference("system", FakeSparseImage(1536 * MiB),
+                                       src=FakeSparseImage(1024 * MiB)),
+                   MockBlockDifference("vendor", FakeSparseImage(512 * MiB),
+                                       src=FakeSparseImage(1024 * MiB)),
+                   MockBlockDifference("product", FakeSparseImage(1024 * MiB),
+                                       src=FakeSparseImage(1024 * MiB)),
+                   MockBlockDifference("product_services", None,
+                                       src=FakeSparseImage(1024 * MiB)),
+                   MockBlockDifference("odm", FakeSparseImage(1024 * MiB),
+                                       src=None)]
+
+    dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs,
+                                                 source_info_dict=source_info)
+    with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+      dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
+
+    metadata_idx = self.script.lines.index(
+        'assert(update_dynamic_partitions(package_extract_file('
+        '"dynamic_partitions_op_list")));')
+    self.assertLess(self.script.lines.index('patch(vendor);'), metadata_idx)
+    self.assertLess(metadata_idx, self.script.lines.index('verify(vendor);'))
+    for p in ("product", "system", "odm"):
+      patch_idx = self.script.lines.index("patch({});".format(p))
+      verify_idx = self.script.lines.index("verify({});".format(p))
+      self.assertLess(metadata_idx, patch_idx,
+                      "Should patch {} after updating metadata".format(p))
+      self.assertLess(patch_idx, verify_idx,
+                      "Should verify {} after patching".format(p))
+
+    self.assertNotIn("patch(product_services);", self.script.lines)
+
+    lines = self.get_op_list(self.output_path)
+
+    remove = lines.index("remove product_services")
+    move_product_out = lines.index("move product default")
+    shrink = lines.index("resize vendor 536870912")
+    shrink_group = lines.index("resize_group group_foo 3221225472")
+    add_group_bar = lines.index("add_group group_bar 1073741824")
+    add_odm = lines.index("add odm group_foo")
+    grow_existing = lines.index("resize system 1610612736")
+    grow_added = lines.index("resize odm 1073741824")
+    move_product_in = lines.index("move product group_bar")
+
+    max_idx_move_partition_out_foo = max(remove, move_product_out, shrink)
+    min_idx_move_partition_in_foo = min(add_odm, grow_existing, grow_added)
+
+    self.assertLess(max_idx_move_partition_out_foo, shrink_group,
+                    "Must shrink group after partitions inside group are shrunk"
+                    " / removed")
+
+    self.assertLess(add_group_bar, move_product_in,
+                    "Must add partitions to group after group is added")
+
+    self.assertLess(max_idx_move_partition_out_foo,
+                    min_idx_move_partition_in_foo,
+                    "Must shrink partitions / remove partitions from group"
+                    "before adding / moving partitions into group")
+
+  def test_remove_partition(self):
+    source_info = common.LoadDictionaryFromLines("""
+blockimgdiff_versions=3,4
+use_dynamic_partitions=true
+dynamic_partition_list=foo
+super_partition_groups=group_foo
+super_group_foo_group_size={group_foo_size}
+super_group_foo_partition_list=foo
+""".format(group_foo_size=4 * GiB).split("\n"))
+    target_info = common.LoadDictionaryFromLines("""
+blockimgdiff_versions=3,4
+use_dynamic_partitions=true
+super_partition_groups=group_foo
+super_group_foo_group_size={group_foo_size}
+""".format(group_foo_size=4 * GiB).split("\n"))
+
+    common.OPTIONS.info_dict = target_info
+    common.OPTIONS.target_info_dict = target_info
+    common.OPTIONS.source_info_dict = source_info
+    common.OPTIONS.cache_size = 4 * 4096
+
+    block_diffs = [common.BlockDifference("foo", EmptyImage(),
+                                          src=DataImage("source", pad=True))]
+
+    dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs,
+                                                 source_info_dict=source_info)
+    with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+      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.")
+
+    lines = self.get_op_list(self.output_path)
+    self.assertEqual(lines, ["remove foo"])
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..6082baf 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,58 @@
     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_mismatchingKeys(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_3.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:
+      self.assertRaises(ValueError, ReadApexKeysInfo, target_files_zip)
+
+  def test_ReadApexKeysInfo_missingPrivateKey(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)
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/target/board/treble_common_32.mk b/tools/releasetools/testdata/signing_helper.sh
old mode 100644
new mode 100755
similarity index 76%
rename from target/board/treble_common_32.mk
rename to tools/releasetools/testdata/signing_helper.sh
index b66c41e..364e023
--- a/target/board/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,4 +15,7 @@
 # limitations under the License.
 #
 
-include build/make/target/board/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..275939c 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(
diff --git a/tools/signapk/Android.bp b/tools/signapk/Android.bp
index e95205d..ad9d957 100644
--- a/tools/signapk/Android.bp
+++ b/tools/signapk/Android.bp
@@ -28,4 +28,10 @@
     ],
 
     required: ["libconscrypt_openjdk_jni"],
+
+    // The post-build signing tools need signapk.jar (and its shared libraries,
+    // handled in their own Android.bp files)
+    dist: {
+        targets: ["droidcore"],
+    },
 }
diff --git a/tools/signapk/Android.mk b/tools/signapk/Android.mk
deleted file mode 100644
index ff54d6d..0000000
--- a/tools/signapk/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-ifeq ($(TARGET_BUILD_APPS),)
-# The post-build signing tools need signapk.jar and its shared libraries,
-# but we don't need this if we're just doing unbundled apps.
-my_dist_files := $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
-    $(HOST_OUT_SHARED_LIBRARIES)/libconscrypt_openjdk_jni$(HOST_SHLIB_SUFFIX)
-
-$(call dist-for-goals,droidcore,$(my_dist_files))
-my_dist_files :=
-endif
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"))