Merge "sign_apex.py respects hash algorithm"
diff --git a/core/Makefile b/core/Makefile
index 5e81549..6926b26 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -161,295 +161,6 @@
 
 $(call dist-for-goals,sdk,$(API_FINGERPRINT))
 
-# -----------------------------------------------------------------
-# property_overrides_split_enabled
-property_overrides_split_enabled :=
-ifeq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true)
-  property_overrides_split_enabled := true
-endif
-
-# -----------------------------------------------------------------
-# FINAL_VENDOR_DEFAULT_PROPERTIES will be installed in vendor/build.prop if
-# property_overrides_split_enabled is true. Otherwise it will be installed in
-# /system/build.prop
-ifdef BOARD_VNDK_VERSION
-  ifeq ($(BOARD_VNDK_VERSION),current)
-    FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION)
-  else
-    FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION)
-  endif
-  ifdef BOARD_VNDK_RUNTIME_DISABLE
-    FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true
-  endif
-else
-  FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION)
-  FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true
-endif
-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_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_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).
-ifdef TARGET_RECOVERY_DEFAULT_ROTATION
-FINAL_VENDOR_DEFAULT_PROPERTIES += \
-    ro.minui.default_rotation=$(TARGET_RECOVERY_DEFAULT_ROTATION)
-endif
-ifdef TARGET_RECOVERY_OVERSCAN_PERCENT
-FINAL_VENDOR_DEFAULT_PROPERTIES += \
-    ro.minui.overscan_percent=$(TARGET_RECOVERY_OVERSCAN_PERCENT)
-endif
-ifdef TARGET_RECOVERY_PIXEL_FORMAT
-FINAL_VENDOR_DEFAULT_PROPERTIES += \
-    ro.minui.pixel_format=$(TARGET_RECOVERY_PIXEL_FORMAT)
-endif
-FINAL_VENDOR_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_VENDOR_DEFAULT_PROPERTIES),=)
-
-BUILDINFO_SH := build/make/tools/buildinfo.sh
-BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh
-POST_PROCESS_PROPS :=$= build/make/tools/post_process_props.py
-
-# Generates a set of sysprops common to all partitions to a file.
-# $(1): Partition name
-# $(2): Output file name
-define generate-common-build-props
-	PRODUCT_BRAND="$(PRODUCT_BRAND)" \
-	PRODUCT_DEVICE="$(TARGET_DEVICE)" \
-	PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
-	PRODUCT_MODEL="$(PRODUCT_MODEL)" \
-	PRODUCT_NAME="$(TARGET_PRODUCT)" \
-	$(call generate-common-build-props-with-product-vars-set,$(1),$(2))
-endef
-
-# Like the above macro, but requiring the relevant PRODUCT_ environment
-# variables to be set when called.
-define generate-common-build-props-with-product-vars-set
-	BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
-	BUILD_ID="$(BUILD_ID)" \
-	BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
-	BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
-	DATE="$(DATE_FROM_FILE)" \
-	PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
-	PLATFORM_VERSION="$(PLATFORM_VERSION)" \
-	TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
-	bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2)
-endef
-
-# -----------------------------------------------------------------
-# build.prop
-intermediate_system_build_prop := $(call intermediates-dir-for,ETC,system_build_prop)/build.prop
-INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop
-ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_BUILD_PROP_TARGET)
-
-# TODO(b/117892318) merge DEFAULT into BUILD
-FINAL_DEFAULT_PROPERTIES := \
-    $(call collapse-pairs, $(ADDITIONAL_DEFAULT_PROPERTIES)) \
-    $(call collapse-pairs, $(PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
-FINAL_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_DEFAULT_PROPERTIES),=)
-
-FINAL_BUILD_PROPERTIES := \
-    $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))
-FINAL_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_BUILD_PROPERTIES),=)
-
-# A list of arbitrary tags describing the build configuration.
-# Force ":=" so we can use +=
-BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
-ifeq ($(TARGET_BUILD_TYPE),debug)
-  BUILD_VERSION_TAGS += debug
-endif
-# The "test-keys" tag marks builds signed with the old test keys,
-# which are available in the SDK.  "dev-keys" marks builds signed with
-# non-default dev keys (usually private keys from a vendor directory).
-# Both of these tags will be removed and replaced with "release-keys"
-# when the target-files is signed in a post-build step.
-ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
-BUILD_KEYS := test-keys
-else
-BUILD_KEYS := dev-keys
-endif
-BUILD_VERSION_TAGS += $(BUILD_KEYS)
-BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
-
-# A human-readable string that descibes this build in detail.
-build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER_FROM_FILE) $(BUILD_VERSION_TAGS)
-$(intermediate_system_build_prop): PRIVATE_BUILD_DESC := $(build_desc)
-
-# 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 := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M)
-  else
-    BF_BUILD_NUMBER := $(file <$(BUILD_NUMBER_FILE))
-  endif
-  BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
-endif
-# unset it for safety.
-BF_BUILD_NUMBER :=
-
-BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
-ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE)))
-  $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))")
-endif
-BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE))
-# unset it for safety.
-BUILD_FINGERPRINT :=
-
-# The string used to uniquely identify the system build; used by the OTA server.
-# This purposefully excludes any product-specific variables.
-ifeq (,$(strip $(BUILD_THUMBPRINT)))
-  BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
-endif
-
-BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt
-ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE)))
-  $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))")
-endif
-BUILD_THUMBPRINT_FROM_FILE := $$(cat $(BUILD_THUMBPRINT_FILE))
-# unset it for safety.
-BUILD_THUMBPRINT :=
-
-KNOWN_OEM_THUMBPRINT_PROPERTIES := \
-    ro.product.brand \
-    ro.product.name \
-    ro.product.device
-OEM_THUMBPRINT_PROPERTIES := $(filter $(KNOWN_OEM_THUMBPRINT_PROPERTIES),\
-    $(PRODUCT_OEM_PROPERTIES))
-
-# Display parameters shown under Settings -> About Phone
-ifeq ($(TARGET_BUILD_VARIANT),user)
-  # User builds should show:
-  # release build number or branch.buld_number non-release builds
-
-  # Dev. branches should have DISPLAY_BUILD_NUMBER set
-  ifeq (true,$(DISPLAY_BUILD_NUMBER))
-    BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER_FROM_FILE) $(BUILD_KEYS)
-  else
-    BUILD_DISPLAY_ID := $(BUILD_ID) $(BUILD_KEYS)
-  endif
-else
-  # Non-user builds should show detailed build information
-  BUILD_DISPLAY_ID := $(build_desc)
-endif
-
-# Accepts a whitespace separated list of product locales such as
-# (en_US en_AU en_GB...) and returns the first locale in the list with
-# underscores replaced with hyphens. In the example above, this will
-# return "en-US".
-define get-default-product-locale
-$(strip $(subst _,-, $(firstword $(1))))
-endef
-
-# TARGET_BUILD_FLAVOR and ro.build.flavor are used only by the test
-# harness to distinguish builds. Only add _asan for a sanitized build
-# if it isn't already a part of the flavor (via a dedicated lunch
-# config for example).
-TARGET_BUILD_FLAVOR := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)
-ifneq (, $(filter address, $(SANITIZE_TARGET)))
-ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR)))
-TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan
-endif
-endif
-
-ifdef TARGET_SYSTEM_PROP
-system_prop_file := $(TARGET_SYSTEM_PROP)
-else
-system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
-endif
-$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT) $(POST_PROCESS_PROPS)
-	@echo Target buildinfo: $@
-	@mkdir -p $(dir $@)
-	$(hide) rm -f $@ && touch $@
-	$(hide) $(foreach line,$(FINAL_DEFAULT_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-ifndef property_overrides_split_enabled
-	$(hide) $(foreach line,$(FINAL_VENDOR_DEFAULT_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-endif
-ifneq ($(PRODUCT_OEM_PROPERTIES),)
-	$(hide) echo "#" >> $@; \
-	        echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
-	        echo "#" >> $@;
-	$(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \
-	    echo "import /oem/oem.prop $(prop)" >> $@;)
-endif
-	$(hide) PRODUCT_BRAND="$(PRODUCT_SYSTEM_BRAND)" \
-	        PRODUCT_MANUFACTURER="$(PRODUCT_SYSTEM_MANUFACTURER)" \
-	        PRODUCT_MODEL="$(PRODUCT_SYSTEM_MODEL)" \
-	        PRODUCT_NAME="$(PRODUCT_SYSTEM_NAME)" \
-	        PRODUCT_DEVICE="$(PRODUCT_SYSTEM_DEVICE)" \
-	        $(call generate-common-build-props-with-product-vars-set,system,$@)
-	$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
-	        TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
-	        TARGET_DEVICE="$(TARGET_DEVICE)" \
-	        PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
-	        PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
-	        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)" \
-	        PLATFORM_VERSION="$(PLATFORM_VERSION)" \
-	        PLATFORM_SECURITY_PATCH="$(PLATFORM_SECURITY_PATCH)" \
-	        PLATFORM_BASE_OS="$(PLATFORM_BASE_OS)" \
-	        PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
-	        PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \
-	        PLATFORM_PREVIEW_SDK_FINGERPRINT="$$(cat $(API_FINGERPRINT))" \
-	        PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \
-	        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)" \
-	        $(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)" \
-	        TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \
-	        TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \
-	        TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
-	        bash $(BUILDINFO_SH) >> $@
-	$(hide) $(foreach file,$(system_prop_file), \
-	    if [ -f "$(file)" ]; then \
-	        echo Target buildinfo from: "$(file)"; \
-	        echo "" >> $@; \
-	        echo "#" >> $@; \
-	        echo "# from $(file)" >> $@; \
-	        echo "#" >> $@; \
-	        cat $(file) >> $@; \
-	        echo "# end of $(file)" >> $@; \
-	    fi;)
-	$(if $(FINAL_BUILD_PROPERTIES), \
-	    $(hide) echo >> $@; \
-	            echo "#" >> $@; \
-	            echo "# ADDITIONAL_BUILD_PROPERTIES" >> $@; \
-	            echo "#" >> $@; )
-	$(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-	$(hide) $(POST_PROCESS_PROPS) $@ $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
-
-build_desc :=
-
 INSTALLED_RECOVERYIMAGE_TARGET :=
 ifdef BUILDING_RECOVERY_IMAGE
 ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
@@ -457,204 +168,7 @@
 endif
 endif
 
-$(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop)
-	@echo "Target build info: $@"
-	$(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@
-
-# -----------------------------------------------------------------
-# vendor build.prop
-#
-# For verifying that the vendor build is what we think it is
-INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop
-ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_BUILD_PROP_TARGET)
-
-ifdef TARGET_VENDOR_PROP
-vendor_prop_files := $(TARGET_VENDOR_PROP)
-else
-vendor_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/vendor.prop)
-endif
-
-ifdef property_overrides_split_enabled
-FINAL_VENDOR_BUILD_PROPERTIES += \
-    $(call collapse-pairs, $(PRODUCT_PROPERTY_OVERRIDES))
-FINAL_VENDOR_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_VENDOR_BUILD_PROPERTIES),=)
-endif  # property_overrides_split_enabled
-
-$(INSTALLED_VENDOR_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(intermediate_system_build_prop) $(vendor_prop_files)
-	@echo Target vendor buildinfo: $@
-	@mkdir -p $(dir $@)
-	$(hide) rm -f $@ && touch $@
-ifdef property_overrides_split_enabled
-	$(hide) $(foreach line,$(FINAL_VENDOR_DEFAULT_PROPERTIES), \
-	  echo "$(line)" >> $@;)
-endif
-ifeq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
-	$(hide) echo ro.boot.dynamic_partitions=true >> $@
-endif
-ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
-	$(hide) echo ro.boot.dynamic_partitions_retrofit=true >> $@
-endif
-	$(hide) grep 'ro.product.first_api_level' $(intermediate_system_build_prop) >> $@ || true
-	$(hide) echo ro.vendor.build.security_patch="$(VENDOR_SECURITY_PATCH)">>$@
-	$(hide) echo ro.vendor.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@
-	$(hide) echo ro.vendor.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@
-	$(hide) echo ro.vendor.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@
-	$(hide) echo ro.product.board="$(TARGET_BOOTLOADER_BOARD_NAME)">>$@
-	$(hide) echo ro.board.platform="$(TARGET_BOARD_PLATFORM)">>$@
-	$(hide) echo ro.hwui.use_vulkan="$(TARGET_USES_VULKAN)">>$@
-ifdef TARGET_SCREEN_DENSITY
-	$(hide) echo ro.sf.lcd_density="$(TARGET_SCREEN_DENSITY)">>$@
-endif
-ifeq ($(AB_OTA_UPDATER),true)
-	$(hide) echo ro.build.ab_update=true >> $@
-endif
-	$(hide) $(call generate-common-build-props,vendor,$@)
-	$(hide) echo "#" >> $@; \
-	        echo "# BOOTIMAGE_BUILD_PROPERTIES" >> $@; \
-	        echo "#" >> $@;
-	$(hide) echo ro.bootimage.build.date=`$(DATE_FROM_FILE)`>>$@
-	$(hide) echo ro.bootimage.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
-	$(hide) echo ro.bootimage.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
-	$(hide) echo "#" >> $@; \
-	        echo "# ADDITIONAL VENDOR BUILD PROPERTIES" >> $@; \
-	        echo "#" >> $@;
-	$(hide) cat $(INSTALLED_ANDROID_INFO_TXT_TARGET) | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' >> $@
-ifdef property_overrides_split_enabled
-	$(hide) $(foreach file,$(vendor_prop_files), \
-	    if [ -f "$(file)" ]; then \
-	        echo Target vendor properties from: "$(file)"; \
-	        echo "" >> $@; \
-	        echo "#" >> $@; \
-	        echo "# from $(file)" >> $@; \
-	        echo "#" >> $@; \
-	        cat $(file) >> $@; \
-	        echo "# end of $(file)" >> $@; \
-	    fi;)
-	$(hide) $(foreach line,$(FINAL_VENDOR_BUILD_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-endif  # property_overrides_split_enabled
-	$(hide) $(POST_PROCESS_PROPS) $@ $(PRODUCT_VENDOR_PROPERTY_BLACKLIST)
-
-# -----------------------------------------------------------------
-# product build.prop
-INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/build.prop
-ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_BUILD_PROP_TARGET)
-
-ifdef TARGET_PRODUCT_PROP
-product_prop_files := $(TARGET_PRODUCT_PROP)
-else
-product_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/product.prop)
-endif
-
-FINAL_PRODUCT_PROPERTIES += \
-    $(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES) $(ADDITIONAL_PRODUCT_PROPERTIES))
-FINAL_PRODUCT_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_PRODUCT_PROPERTIES),=)
-
-$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(product_prop_files)
-	@echo Target product buildinfo: $@
-	@mkdir -p $(dir $@)
-	$(hide) rm -f $@ && touch $@
-ifdef BOARD_USES_PRODUCTIMAGE
-	$(hide) $(call generate-common-build-props,product,$@)
-endif  # BOARD_USES_PRODUCTIMAGE
-	$(hide) $(foreach file,$(product_prop_files), \
-	    if [ -f "$(file)" ]; then \
-	        echo Target product properties from: "$(file)"; \
-	        echo "" >> $@; \
-	        echo "#" >> $@; \
-	        echo "# from $(file)" >> $@; \
-	        echo "#" >> $@; \
-	        cat $(file) >> $@; \
-	        echo "# end of $(file)" >> $@; \
-	    fi;)
-	$(hide) echo "#" >> $@; \
-	        echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \
-	        echo "#" >> $@; \
-	        echo "ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)" >> $@;
-	$(hide) $(foreach line,$(FINAL_PRODUCT_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-	$(hide) $(POST_PROCESS_PROPS) $@
-
-# ----------------------------------------------------------------
-# odm build.prop
-INSTALLED_ODM_BUILD_PROP_TARGET := $(TARGET_OUT_ODM)/etc/build.prop
-ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_ODM_BUILD_PROP_TARGET)
-
-ifdef TARGET_ODM_PROP
-odm_prop_files := $(TARGET_ODM_PROP)
-else
-odm_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/odm.prop)
-endif
-
-FINAL_ODM_BUILD_PROPERTIES += \
-    $(call collapse-pairs, $(PRODUCT_ODM_PROPERTIES))
-FINAL_ODM_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_ODM_BUILD_PROPERTIES),=)
-
-$(INSTALLED_ODM_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(odm_prop_files)
-	@echo Target odm buildinfo: $@
-	@mkdir -p $(dir $@)
-	$(hide) rm -f $@ && touch $@
-	$(hide) echo ro.odm.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@
-	$(hide) echo ro.odm.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@
-	$(hide) echo ro.odm.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@
-	$(hide) $(call generate-common-build-props,odm,$@)
-	$(hide) $(foreach file,$(odm_prop_files), \
-	    if [ -f "$(file)" ]; then \
-	        echo Target odm properties from: "$(file)"; \
-	        echo "" >> $@; \
-	        echo "#" >> $@; \
-	        echo "# from $(file)" >> $@; \
-	        echo "#" >> $@; \
-	        cat $(file) >> $@; \
-	        echo "# end of $(file)" >> $@; \
-	    fi;)
-	$(hide) echo "#" >> $@; \
-	        echo "# ADDITIONAL ODM BUILD PROPERTIES" >> $@; \
-	        echo "#" >> $@;
-	$(hide) $(foreach line,$(FINAL_ODM_BUILD_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-	$(hide) $(POST_PROCESS_PROPS) $@
-
-# -----------------------------------------------------------------
-# system_ext build.prop
-INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/build.prop
-ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)
-
-ifdef TARGET_SYSTEM_EXT_PROP
-system_ext_prop_files := $(TARGET_SYSTEM_EXT_PROP)
-else
-system_ext_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop)
-endif
-
-FINAL_SYSTEM_EXT_PROPERTIES += \
-    $(call collapse-pairs, $(PRODUCT_SYSTEM_EXT_PROPERTIES))
-FINAL_SYSTEM_EXT_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_SYSTEM_EXT_PROPERTIES),=)
-
-$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(system_ext_prop_files)
-	@echo Target system_ext buildinfo: $@
-	@mkdir -p $(dir $@)
-	$(hide) rm -f $@ && touch $@
-	$(hide) $(call generate-common-build-props,system_ext,$@)
-	$(hide) $(foreach file,$(system_ext_prop_files), \
-	    if [ -f "$(file)" ]; then \
-	        echo Target system_ext properties from: "$(file)"; \
-	        echo "" >> $@; \
-	        echo "#" >> $@; \
-	        echo "# from $(file)" >> $@; \
-	        echo "#" >> $@; \
-	        cat $(file) >> $@; \
-	        echo "# end of $(file)" >> $@; \
-	    fi;)
-	$(hide) echo "#" >> $@; \
-	        echo "# ADDITIONAL SYSTEM_EXT BUILD PROPERTIES" >> $@; \
-	        echo "#" >> $@;
-	$(hide) $(foreach line,$(FINAL_SYSTEM_EXT_PROPERTIES), \
-	    echo "$(line)" >> $@;)
-	$(hide) $(POST_PROCESS_PROPS) $@
+include $(BUILD_SYSTEM)/sysprop.mk
 
 # ----------------------------------------------------------------
 
@@ -979,7 +493,7 @@
 # directory).
 event_log_tags_src := \
     $(sort $(foreach m,\
-      $(PRODUCT_PACKAGES) \
+      $(call resolve-bitness-for-modules,TARGET,$(PRODUCT_PACKAGES)) \
       $(call module-names-for-tag-list,user), \
       $(ALL_MODULES.$(m).EVENT_LOG_TAGS)) \
       $(filter-out vendor/% device/% out/%,$(all_event_log_tags_src)))
@@ -1093,6 +607,15 @@
   BUILT_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
 endif
 
+ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
+  BOARD_KERNEL_BOOTIMAGE_PARTITION_SIZE := $(BOARD_BOOTIMAGE_PARTITION_SIZE)
+endif
+
+# $1: boot image file name
+# $2: boot image variant (boot, boot-debug)
+define get-bootimage-partition-size
+  $(BOARD_$(call to-upper,$(subst .img,,$(subst $(2),kernel,$(notdir $(1)))))_BOOTIMAGE_PARTITION_SIZE)
+endef
 
 ifneq ($(strip $(TARGET_NO_KERNEL)),true)
 INTERNAL_BOOTIMAGE_ARGS := \
@@ -2181,11 +1704,11 @@
   $(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
     $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
   $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
-    $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))), \
+    $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot))), \
     $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))))
   $(if $(filter true,$(BOARD_AVB_ENABLE)), \
     $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
-      $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
+      $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(call get-bootimage-partition-size,$(1),boot) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
       $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_RECOVERYIMAGE_PARTITION_SIZE) --partition_name recovery $(INTERNAL_AVB_RECOVERY_SIGNING_ARGS) $(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)))
 endef
 
@@ -2372,13 +1895,13 @@
 INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS := --algorithm SHA256_RSA2048 --key $(BOARD_AVB_BOOT_TEST_KEY_PATH)
 # $(1): the bootimage to sign
 define test-key-sign-bootimage
-$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
+$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot-debug)))
 $(AVBTOOL) add_hash_footer \
   --image $(1) \
-  --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+  --partition_size $(call get-bootimage-partition-size,$(1),boot-debug)\
   --partition_name boot $(INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS) \
   $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
-$(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+$(call assert-max-image-size,$(1),$(call get-bootimage-partition-size,$(1),boot-debug))
 endef
 
 # $(1): output file
@@ -3356,10 +2879,10 @@
 # When building a standalone recovery image for non-A/B devices, recovery image must be self-signed
 # to be verified independently, and cannot be chained into vbmeta.img. See the link below for
 # details.
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
 $(if $(BOARD_AVB_RECOVERY_KEY_PATH),,\
-    $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for non-A/B devices. \
+    $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for if non-A/B is supported. \
             See https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery))
 endif
 endif
@@ -3450,7 +2973,7 @@
 
 # The recovery partition in non-A/B devices should be verified separately. Skip adding the chain
 # partition descriptor for recovery partition into vbmeta.img.
-$(if $(or $(filter true,$(AB_OTA_UPDATER)),$(filter-out recovery,$(part))),\
+$(if $(or $(filter-out true,$(TARGET_OTA_ALLOW_NON_AB)),$(filter-out recovery,$(part))),\
     $(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
         --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey))
 
@@ -4122,6 +3645,11 @@
 endif
 .KATI_READONLY := tool_extensions
 
+# $1: boot image file name
+define misc_boot_size
+$(subst .img,_size,$(1))=$(BOARD_KERNEL$(call to-upper,$(subst boot,,$(subst .img,,$(1))))_BOOTIMAGE_PARTITION_SIZE)
+endef
+
 $(INSTALLED_MISC_INFO_TARGET):
 	rm -f $@
 	$(call pretty,"Target misc_info.txt: $@")
@@ -4130,8 +3658,9 @@
 ifdef BOARD_FLASH_BLOCK_SIZE
 	$(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" >> $@
 endif
-ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
-	$(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $@
+ifneq ($(strip $(BOARD_BOOTIMAGE_PARTITION_SIZE))$(strip $(BOARD_KERNEL_BINARIES)),)
+	$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),\
+		echo "$(call misc_boot_size,$(notdir $(b)))" >> $@;)
 endif
 ifeq ($(INSTALLED_BOOTIMAGE_TARGET),)
 	$(hide) echo "no_boot=true" >> $@
@@ -4239,6 +3768,9 @@
 	$(hide) echo "build_type=$(TARGET_BUILD_VARIANT)" >> $@
 	$(hide) echo "ab_update=true" >> $@
 endif
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
+	$(hide) echo "allow_non_ab=true" >> $@
+endif
 ifdef BOARD_PREBUILT_DTBOIMAGE
 	$(hide) echo "has_dtbo=true" >> $@
 ifeq ($(BOARD_AVB_ENABLE),true)
@@ -4316,10 +3848,13 @@
 
 ifeq ($(AB_OTA_UPDATER),true)
 updater_dep := system/update_engine/update_engine.conf
-else
-# Build OTA tools if not using the AB Updater.
+endif
+
+# Build OTA tools if non-A/B is allowed
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
 updater_dep := $(built_ota_tools)
 endif
+
 $(BUILT_TARGET_FILES_PACKAGE): $(updater_dep)
 
 # If we are using recovery as boot, output recovery files to BOOT/.
@@ -4595,7 +4130,7 @@
 	@# Extra contents of the OTA package
 	$(hide) mkdir -p $(zip_root)/OTA
 	$(hide) cp $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
 ifneq ($(built_ota_tools),)
 	$(hide) mkdir -p $(zip_root)/OTA/bin
 	$(hide) cp $(PRIVATE_OTA_TOOLS) $(zip_root)/OTA/bin/
@@ -4632,7 +4167,7 @@
 	$(hide) cp $(PRODUCT_ODM_BASE_FS_PATH) \
 	  $(zip_root)/META/$(notdir $(PRODUCT_ODM_BASE_FS_PATH))
 endif
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
 	$(hide) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	    $(MAKE_RECOVERY_PATCH) $(zip_root) $(zip_root)
diff --git a/core/board_config.mk b/core/board_config.mk
index 2279c3f..0ff28c5 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -550,13 +550,31 @@
 .KATI_READONLY := BUILDING_ODM_IMAGE
 
 ###########################################
-# Ensure that only TARGET_RECOVERY_UPDATER_LIBS *or* AB_OTA_UPDATER is set.
+# Ensure consistency among TARGET_RECOVERY_UPDATER_LIBS, AB_OTA_UPDATER, and PRODUCT_OTA_FORCE_NON_AB_PACKAGE.
 TARGET_RECOVERY_UPDATER_LIBS ?=
 AB_OTA_UPDATER ?=
 .KATI_READONLY := TARGET_RECOVERY_UPDATER_LIBS AB_OTA_UPDATER
-ifeq ($(AB_OTA_UPDATER),true)
+
+# Ensure that if PRODUCT_OTA_FORCE_NON_AB_PACKAGE == true, then AB_OTA_UPDATER must be true
+ifeq ($(PRODUCT_OTA_FORCE_NON_AB_PACKAGE),true)
+  ifneq ($(AB_OTA_UPDATER),true)
+    $(error AB_OTA_UPDATER must be set to true when PRODUCT_OTA_FORCE_NON_AB_PACKAGE is true)
+  endif
+endif
+
+# In some configurations, A/B and non-A/B may coexist. Check TARGET_OTA_ALLOW_NON_AB
+# to see if non-A/B is supported.
+TARGET_OTA_ALLOW_NON_AB := false
+ifneq ($(AB_OTA_UPDATER),true)
+  TARGET_OTA_ALLOW_NON_AB := true
+else ifeq ($(PRODUCT_OTA_FORCE_NON_AB_PACKAGE),true)
+  TARGET_OTA_ALLOW_NON_AB := true
+endif
+.KATI_READONLY := TARGET_OTA_ALLOW_NON_AB
+
+ifneq ($(TARGET_OTA_ALLOW_NON_AB),true)
   ifneq ($(strip $(TARGET_RECOVERY_UPDATER_LIBS)),)
-    $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using AB_OTA_UPDATER)
+    $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using TARGET_OTA_ALLOW_NON_AB)
   endif
 endif
 
diff --git a/core/main.mk b/core/main.mk
index 68303cf..9c52b01 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -115,7 +115,7 @@
 # -----------------------------------------------------------------
 # Validate ADDITIONAL_DEFAULT_PROPERTIES.
 ifneq ($(ADDITIONAL_DEFAULT_PROPERTIES),)
-$(error ADDITIONAL_DEFAULT_PROPERTIES must not be set before here: $(ADDITIONAL_DEFAULT_PROPERTIES))
+$(error ADDITIONAL_DEFAULT_PROPERTIES is deprecated)
 endif
 
 #
@@ -207,9 +207,9 @@
 # Sets ro.actionable_compatible_property.enabled to know on runtime whether the whitelist
 # of actionable compatible properties is enabled or not.
 ifeq ($(PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE),true)
-ADDITIONAL_DEFAULT_PROPERTIES += ro.actionable_compatible_property.enabled=false
+ADDITIONAL_BUILD_PROPERTIES += ro.actionable_compatible_property.enabled=false
 else
-ADDITIONAL_DEFAULT_PROPERTIES += ro.actionable_compatible_property.enabled=${PRODUCT_COMPATIBLE_PROPERTY}
+ADDITIONAL_BUILD_PROPERTIES += ro.actionable_compatible_property.enabled=${PRODUCT_COMPATIBLE_PROPERTY}
 endif
 
 # Add the system server compiler filter if they are specified for the product.
@@ -229,7 +229,7 @@
 #
 # It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to
 # mount system_other partition.
-ADDITIONAL_DEFAULT_PROPERTIES += ro.postinstall.fstab.prefix=/system
+ADDITIONAL_BUILD_PROPERTIES += ro.postinstall.fstab.prefix=/system
 
 # Set ro.product.vndk.version to know the VNDK version required by product
 # modules. It uses the version in PRODUCT_PRODUCT_VNDK_VERSION. If the value
@@ -261,11 +261,11 @@
 tags_to_install :=
 ifneq (,$(user_variant))
   # Target is secure in user builds.
-  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
-  ADDITIONAL_DEFAULT_PROPERTIES += security.perf_harden=1
+  ADDITIONAL_BUILD_PROPERTIES += ro.secure=1
+  ADDITIONAL_BUILD_PROPERTIES += security.perf_harden=1
 
   ifeq ($(user_variant),user)
-    ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1
+    ADDITIONAL_BUILD_PROPERTIES += ro.adb.secure=1
   endif
 
   ifeq ($(user_variant),userdebug)
@@ -277,25 +277,25 @@
   endif
 
   # Disallow mock locations by default for user builds
-  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0
+  ADDITIONAL_BUILD_PROPERTIES += ro.allow.mock.location=0
 
 else # !user_variant
   # Turn on checkjni for non-user builds.
   ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1
   # Set device insecure for non-user builds.
-  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
+  ADDITIONAL_BUILD_PROPERTIES += ro.secure=0
   # Allow mock locations by default for non user builds
-  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1
+  ADDITIONAL_BUILD_PROPERTIES += ro.allow.mock.location=1
 endif # !user_variant
 
 ifeq (true,$(strip $(enable_target_debugging)))
   # Target is more debuggable and adbd is on by default
-  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1
+  ADDITIONAL_BUILD_PROPERTIES += ro.debuggable=1
   # Enable Dalvik lock contention logging.
   ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.lockprof.threshold=500
 else # !enable_target_debugging
   # Target is less debuggable and adbd is off by default
-  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0
+  ADDITIONAL_BUILD_PROPERTIES += ro.debuggable=0
 endif # !enable_target_debugging
 
 ## eng ##
@@ -388,8 +388,6 @@
 
 # Strip and readonly a few more variables so they won't be modified.
 $(readonly-final-product-vars)
-ADDITIONAL_DEFAULT_PROPERTIES := $(strip $(ADDITIONAL_DEFAULT_PROPERTIES))
-.KATI_READONLY := ADDITIONAL_DEFAULT_PROPERTIES
 ADDITIONAL_BUILD_PROPERTIES := $(strip $(ADDITIONAL_BUILD_PROPERTIES))
 .KATI_READONLY := ADDITIONAL_BUILD_PROPERTIES
 ADDITIONAL_PRODUCT_PROPERTIES := $(strip $(ADDITIONAL_PRODUCT_PROPERTIES))
@@ -487,6 +485,21 @@
 # brought in as requirements of other modules.
 #
 # Resolve the required module name to 32-bit or 64-bit variant.
+
+# TODO(b/155869107): Replace get-32-bit-modules with get-modules-for-2nd-arch
+# Get a list of corresponding module names for the second arch, if they exist.
+# $(1): TARGET, HOST or HOST_CROSS
+# $(2): A list of module names
+define get-modules-for-2nd-arch
+$(strip \
+  $(foreach m,$(2), \
+    $(if $(filter true,$(ALL_MODULES.$(m)$($(1)_2ND_ARCH_MODULE_SUFFIX).FOR_2ND_ARCH)), \
+      $(m)$($(1)_2ND_ARCH_MODULE_SUFFIX) \
+    ) \
+  ) \
+)
+endef
+
 # Get a list of corresponding 32-bit module names, if one exists.
 define get-32-bit-modules
 $(sort $(foreach m,$(1),\
@@ -1030,6 +1043,45 @@
 
 endef
 
+# Resolves module bitness for PRODUCT_PACKAGES and PRODUCT_HOST_PACKAGES.
+# The returned list of module names can be used to access
+# ALL_MODULES.<module>.<*> variables.
+# Name resolution for PRODUCT_PACKAGES / PRODUCT_HOST_PACKAGES:
+#   foo:32 resolves to foo_32;
+#   foo:64 resolves to foo;
+#   foo resolves to both foo and foo_32 (if foo_32 is defined).
+#
+# Name resolution for HOST_CROSS modules:
+#   foo:32 resolves to foo;
+#   foo:64 resolves to foo_64;
+#   foo resolves to both foo and foo_64 (if foo_64 is defined).
+#
+# $(1): TARGET, HOST or HOST_CROSS
+# $(2): A list of simple module names with :32 and :64 suffix
+define resolve-bitness-for-modules
+$(strip \
+  $(eval modules_32 := $(patsubst %:32,%,$(filter %:32,$(2)))) \
+  $(eval modules_64 := $(patsubst %:64,%,$(filter %:64,$(2)))) \
+  $(eval modules_both := $(filter-out %:32 %:64,$(2))) \
+  $(eval ### For host cross modules, the primary arch is windows x86 and secondary is x86_64) \
+  $(if $(filter HOST_CROSS,$(1)), \
+    $(eval modules_1st_arch := $(modules_32)) \
+    $(eval modules_2nd_arch := $(modules_64)), \
+    $(eval modules_1st_arch := $(modules_64)) \
+    $(eval modules_2nd_arch := $(modules_32))) \
+  $(eval ### Note for 32-bit product, 32 and 64 will be added as their original module names.) \
+  $(eval modules := $(modules_1st_arch)) \
+  $(if $($(1)_2ND_ARCH), \
+    $(eval modules += $(call get-modules-for-2nd-arch,$(1),$(modules_2nd_arch))), \
+    $(eval modules += $(modules_2nd_arch))) \
+  $(eval ### For the rest we add both) \
+  $(eval modules += $(modules_both)) \
+  $(if $($(1)_2ND_ARCH), \
+    $(eval modules += $(call get-modules-for-2nd-arch,$(1),$(modules_both)))) \
+  $(modules) \
+)
+endef
+
 # Lists most of the files a particular product installs, including:
 # - PRODUCT_PACKAGES, and their LOCAL_REQUIRED_MODULES
 # - PRODUCT_COPY_FILES
@@ -1059,15 +1111,7 @@
   $(eval _pif_overrides := $(call module-overrides,$(_pif_modules))) \
   $(eval _pif_modules := $(filter-out $(_pif_overrides), $(_pif_modules))) \
   $(eval ### Resolve the :32 :64 module name) \
-  $(eval _pif_modules_32 := $(patsubst %:32,%,$(filter %:32, $(_pif_modules)))) \
-  $(eval _pif_modules_64 := $(patsubst %:64,%,$(filter %:64, $(_pif_modules)))) \
-  $(eval _pif_modules_rest := $(filter-out %:32 %:64,$(_pif_modules))) \
-  $(eval ### Note for 32-bit product, 32 and 64 will be added as their original module names.) \
-  $(eval _pif_modules := $(call get-32-bit-modules-if-we-can, $(_pif_modules_32))) \
-  $(eval _pif_modules += $(_pif_modules_64)) \
-  $(eval ### For the rest we add both) \
-  $(eval _pif_modules += $(call get-32-bit-modules, $(_pif_modules_rest))) \
-  $(eval _pif_modules += $(_pif_modules_rest)) \
+  $(eval _pif_modules := $(sort $(call resolve-bitness-for-modules,TARGET,$(_pif_modules)))) \
   $(call expand-required-modules,_pif_modules,$(_pif_modules),$(_pif_overrides)) \
   $(filter-out $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(_pif_modules))) \
   $(call resolve-product-relative-paths,\
@@ -1078,18 +1122,12 @@
 # This does support the :32 / :64 syntax, but does not support module overrides.
 define host-installed-files
   $(eval _hif_modules := $(call get-product-var,$(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)) \
   $(eval ### Split host vs host cross modules) \
   $(eval _hcif_modules := $(filter host_cross_%,$(_hif_modules))) \
   $(eval _hif_modules := $(filter-out host_cross_%,$(_hif_modules))) \
+  $(eval ### Resolve the :32 :64 module name) \
+  $(eval _hif_modules := $(sort $(call resolve-bitness-for-modules,HOST,$(_hif_modules)))) \
+  $(eval _hcif_modules := $(sort $(call resolve-bitness-for-modules,HOST_CROSS,$(_hcif_modules)))) \
   $(call expand-required-host-modules,_hif_modules,$(_hif_modules),HOST) \
   $(call expand-required-host-modules,_hcif_modules,$(_hcif_modules),HOST_CROSS) \
   $(filter $(HOST_OUT)/%,$(call module-installed-files, $(_hif_modules))) \
@@ -1146,15 +1184,17 @@
 
   # Some modules produce only host installed files when building with TARGET_BUILD_APPS
   ifeq ($(TARGET_BUILD_APPS),)
-    _modules := $(foreach m,$(PRODUCT_PACKAGES) \
-                            $(PRODUCT_PACKAGES_DEBUG) \
-                            $(PRODUCT_PACKAGES_DEBUG_ASAN) \
-                            $(PRODUCT_PACKAGES_ENG) \
-                            $(PRODUCT_PACKAGES_TESTS),\
+    _modules := $(call resolve-bitness-for-modules,TARGET, \
+      $(PRODUCT_PACKAGES) \
+      $(PRODUCT_PACKAGES_DEBUG) \
+      $(PRODUCT_PACKAGES_DEBUG_ASAN) \
+      $(PRODUCT_PACKAGES_ENG) \
+      $(PRODUCT_PACKAGES_TESTS))
+    _host_modules := $(foreach m,$(_modules), \
                   $(if $(ALL_MODULES.$(m).INSTALLED),\
                     $(if $(filter-out $(HOST_OUT_ROOT)/%,$(ALL_MODULES.$(m).INSTALLED)),,\
                       $(m))))
-    $(call maybe-print-list-and-error,$(sort $(_modules)),\
+    $(call maybe-print-list-and-error,$(sort $(_host_modules)),\
       Host modules should be in PRODUCT_HOST_PACKAGES$(comma) not PRODUCT_PACKAGES)
   endif
 
diff --git a/core/product.mk b/core/product.mk
index ea9be72..0aa07ef 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -393,6 +393,13 @@
 # If set, device retrofits virtual A/B.
 _product_single_value_vars += PRODUCT_VIRTUAL_AB_OTA_RETROFIT
 
+# If set, forcefully generate a non-A/B update package.
+# Note: A device configuration should inherit from virtual_ab_ota_plus_non_ab.mk
+# instead of setting this variable directly.
+# Note: Use TARGET_OTA_ALLOW_NON_AB in the build system because
+# TARGET_OTA_ALLOW_NON_AB takes the value of AB_OTA_UPDATER into account.
+_product_single_value_vars += PRODUCT_OTA_FORCE_NON_AB_PACKAGE
+
 # If set, Java module in product partition cannot use hidden APIs.
 _product_single_value_vars += PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
 
diff --git a/core/soong_android_app_set.mk b/core/soong_android_app_set.mk
index e84371c..4c27e53 100644
--- a/core/soong_android_app_set.mk
+++ b/core/soong_android_app_set.mk
@@ -24,8 +24,10 @@
 endef
 
 $(eval $(call extract-master-from-apk-set,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_APK_SET_MASTER_FILE)))
+# unzip returns 11 it there was nothing to extract, which is expected,
+# $(LOCAL_APK_SET_MASTER_FILE) has is already there.
 LOCAL_POST_INSTALL_CMD := unzip -qo -j -d $(dir $(LOCAL_INSTALLED_MODULE)) \
-	$(LOCAL_PREBUILT_MODULE_FILE) -x $(LOCAL_APK_SET_MASTER_FILE)
+	$(LOCAL_PREBUILT_MODULE_FILE) -x $(LOCAL_APK_SET_MASTER_FILE) || [[ $$? -eq 11 ]]
 $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
 PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 
diff --git a/core/sysprop.mk b/core/sysprop.mk
new file mode 100644
index 0000000..ed13c03
--- /dev/null
+++ b/core/sysprop.mk
@@ -0,0 +1,507 @@
+#
+# Copyright (C) 2020 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.
+#
+
+# sysprop.mk defines rules for generating <partition>/build.prop files
+
+# -----------------------------------------------------------------
+# property_overrides_split_enabled
+property_overrides_split_enabled :=
+ifeq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true)
+  property_overrides_split_enabled := true
+endif
+
+# -----------------------------------------------------------------
+# FINAL_VENDOR_DEFAULT_PROPERTIES will be installed in vendor/build.prop if
+# property_overrides_split_enabled is true. Otherwise it will be installed in
+# /system/build.prop
+ifdef BOARD_VNDK_VERSION
+  ifeq ($(BOARD_VNDK_VERSION),current)
+    FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION)
+  else
+    FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION)
+  endif
+  ifdef BOARD_VNDK_RUNTIME_DISABLE
+    FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true
+  endif
+else
+  FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION)
+  FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true
+endif
+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_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_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).
+ifdef TARGET_RECOVERY_DEFAULT_ROTATION
+FINAL_VENDOR_DEFAULT_PROPERTIES += \
+    ro.minui.default_rotation=$(TARGET_RECOVERY_DEFAULT_ROTATION)
+endif
+ifdef TARGET_RECOVERY_OVERSCAN_PERCENT
+FINAL_VENDOR_DEFAULT_PROPERTIES += \
+    ro.minui.overscan_percent=$(TARGET_RECOVERY_OVERSCAN_PERCENT)
+endif
+ifdef TARGET_RECOVERY_PIXEL_FORMAT
+FINAL_VENDOR_DEFAULT_PROPERTIES += \
+    ro.minui.pixel_format=$(TARGET_RECOVERY_PIXEL_FORMAT)
+endif
+FINAL_VENDOR_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_VENDOR_DEFAULT_PROPERTIES),=)
+
+BUILDINFO_SH := build/make/tools/buildinfo.sh
+BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh
+POST_PROCESS_PROPS :=$= build/make/tools/post_process_props.py
+
+# Generates a set of sysprops common to all partitions to a file.
+# $(1): Partition name
+# $(2): Output file name
+define generate-common-build-props
+	PRODUCT_BRAND="$(PRODUCT_BRAND)" \
+	PRODUCT_DEVICE="$(TARGET_DEVICE)" \
+	PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
+	PRODUCT_MODEL="$(PRODUCT_MODEL)" \
+	PRODUCT_NAME="$(TARGET_PRODUCT)" \
+	$(call generate-common-build-props-with-product-vars-set,$(1),$(2))
+endef
+
+# Like the above macro, but requiring the relevant PRODUCT_ environment
+# variables to be set when called.
+define generate-common-build-props-with-product-vars-set
+	BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
+	BUILD_ID="$(BUILD_ID)" \
+	BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
+	BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
+	DATE="$(DATE_FROM_FILE)" \
+	PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
+	PLATFORM_VERSION_LAST_STABLE="$(PLATFORM_VERSION_LAST_STABLE)" \
+	PLATFORM_VERSION="$(PLATFORM_VERSION)" \
+	TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
+	bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2)
+endef
+
+# -----------------------------------------------------------------
+# build.prop
+intermediate_system_build_prop := $(call intermediates-dir-for,ETC,system_build_prop)/build.prop
+INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_BUILD_PROP_TARGET)
+
+# TODO(b/117892318) merge DEFAULT into BUILD
+FINAL_DEFAULT_PROPERTIES := \
+    $(call collapse-pairs, $(PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
+FINAL_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_DEFAULT_PROPERTIES),=)
+
+FINAL_BUILD_PROPERTIES := \
+    $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))
+FINAL_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_BUILD_PROPERTIES),=)
+
+# A list of arbitrary tags describing the build configuration.
+# Force ":=" so we can use +=
+BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
+ifeq ($(TARGET_BUILD_TYPE),debug)
+  BUILD_VERSION_TAGS += debug
+endif
+# The "test-keys" tag marks builds signed with the old test keys,
+# which are available in the SDK.  "dev-keys" marks builds signed with
+# non-default dev keys (usually private keys from a vendor directory).
+# Both of these tags will be removed and replaced with "release-keys"
+# when the target-files is signed in a post-build step.
+ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
+BUILD_KEYS := test-keys
+else
+BUILD_KEYS := dev-keys
+endif
+BUILD_VERSION_TAGS += $(BUILD_KEYS)
+BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
+
+# A human-readable string that descibes this build in detail.
+build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER_FROM_FILE) $(BUILD_VERSION_TAGS)
+$(intermediate_system_build_prop): PRIVATE_BUILD_DESC := $(build_desc)
+
+# 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 := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M)
+  else
+    BF_BUILD_NUMBER := $(file <$(BUILD_NUMBER_FILE))
+  endif
+  BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+endif
+# unset it for safety.
+BF_BUILD_NUMBER :=
+
+BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
+ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE)))
+  $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))")
+endif
+BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE))
+# unset it for safety.
+BUILD_FINGERPRINT :=
+
+# The string used to uniquely identify the system build; used by the OTA server.
+# This purposefully excludes any product-specific variables.
+ifeq (,$(strip $(BUILD_THUMBPRINT)))
+  BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+endif
+
+BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt
+ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE)))
+  $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))")
+endif
+BUILD_THUMBPRINT_FROM_FILE := $$(cat $(BUILD_THUMBPRINT_FILE))
+# unset it for safety.
+BUILD_THUMBPRINT :=
+
+KNOWN_OEM_THUMBPRINT_PROPERTIES := \
+    ro.product.brand \
+    ro.product.name \
+    ro.product.device
+OEM_THUMBPRINT_PROPERTIES := $(filter $(KNOWN_OEM_THUMBPRINT_PROPERTIES),\
+    $(PRODUCT_OEM_PROPERTIES))
+
+# Display parameters shown under Settings -> About Phone
+ifeq ($(TARGET_BUILD_VARIANT),user)
+  # User builds should show:
+  # release build number or branch.buld_number non-release builds
+
+  # Dev. branches should have DISPLAY_BUILD_NUMBER set
+  ifeq (true,$(DISPLAY_BUILD_NUMBER))
+    BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER_FROM_FILE) $(BUILD_KEYS)
+  else
+    BUILD_DISPLAY_ID := $(BUILD_ID) $(BUILD_KEYS)
+  endif
+else
+  # Non-user builds should show detailed build information
+  BUILD_DISPLAY_ID := $(build_desc)
+endif
+
+# Accepts a whitespace separated list of product locales such as
+# (en_US en_AU en_GB...) and returns the first locale in the list with
+# underscores replaced with hyphens. In the example above, this will
+# return "en-US".
+define get-default-product-locale
+$(strip $(subst _,-, $(firstword $(1))))
+endef
+
+# TARGET_BUILD_FLAVOR and ro.build.flavor are used only by the test
+# harness to distinguish builds. Only add _asan for a sanitized build
+# if it isn't already a part of the flavor (via a dedicated lunch
+# config for example).
+TARGET_BUILD_FLAVOR := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)
+ifneq (, $(filter address, $(SANITIZE_TARGET)))
+ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR)))
+TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan
+endif
+endif
+
+ifdef TARGET_SYSTEM_PROP
+system_prop_file := $(TARGET_SYSTEM_PROP)
+else
+system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
+endif
+$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT) $(POST_PROCESS_PROPS)
+	@echo Target buildinfo: $@
+	@mkdir -p $(dir $@)
+	$(hide) rm -f $@ && touch $@
+	$(hide) $(foreach line,$(FINAL_DEFAULT_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+ifndef property_overrides_split_enabled
+	$(hide) $(foreach line,$(FINAL_VENDOR_DEFAULT_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+endif
+ifneq ($(PRODUCT_OEM_PROPERTIES),)
+	$(hide) echo "#" >> $@; \
+	        echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
+	        echo "#" >> $@;
+	$(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \
+	    echo "import /oem/oem.prop $(prop)" >> $@;)
+endif
+	$(hide) PRODUCT_BRAND="$(PRODUCT_SYSTEM_BRAND)" \
+	        PRODUCT_MANUFACTURER="$(PRODUCT_SYSTEM_MANUFACTURER)" \
+	        PRODUCT_MODEL="$(PRODUCT_SYSTEM_MODEL)" \
+	        PRODUCT_NAME="$(PRODUCT_SYSTEM_NAME)" \
+	        PRODUCT_DEVICE="$(PRODUCT_SYSTEM_DEVICE)" \
+	        $(call generate-common-build-props-with-product-vars-set,system,$@)
+	$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
+	        TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
+	        TARGET_DEVICE="$(TARGET_DEVICE)" \
+	        PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
+	        PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
+	        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)" \
+	        PLATFORM_VERSION="$(PLATFORM_VERSION)" \
+	        PLATFORM_VERSION_LAST_STABLE="$(PLATFORM_VERSION_LAST_STABLE)" \
+	        PLATFORM_SECURITY_PATCH="$(PLATFORM_SECURITY_PATCH)" \
+	        PLATFORM_BASE_OS="$(PLATFORM_BASE_OS)" \
+	        PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
+	        PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \
+	        PLATFORM_PREVIEW_SDK_FINGERPRINT="$$(cat $(API_FINGERPRINT))" \
+	        PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \
+	        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)" \
+	        $(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)" \
+	        TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \
+	        TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \
+	        TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
+	        bash $(BUILDINFO_SH) >> $@
+	$(hide) $(foreach file,$(system_prop_file), \
+	    if [ -f "$(file)" ]; then \
+	        echo Target buildinfo from: "$(file)"; \
+	        echo "" >> $@; \
+	        echo "#" >> $@; \
+	        echo "# from $(file)" >> $@; \
+	        echo "#" >> $@; \
+	        cat $(file) >> $@; \
+	        echo "# end of $(file)" >> $@; \
+	    fi;)
+	$(if $(FINAL_BUILD_PROPERTIES), \
+	    $(hide) echo >> $@; \
+	            echo "#" >> $@; \
+	            echo "# ADDITIONAL_BUILD_PROPERTIES" >> $@; \
+	            echo "#" >> $@; )
+	$(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+	$(hide) $(POST_PROCESS_PROPS) $@ $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
+
+build_desc :=
+
+$(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop)
+	@echo "Target build info: $@"
+	$(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@
+
+# -----------------------------------------------------------------
+# vendor build.prop
+#
+# For verifying that the vendor build is what we think it is
+INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_BUILD_PROP_TARGET)
+
+ifdef TARGET_VENDOR_PROP
+vendor_prop_files := $(TARGET_VENDOR_PROP)
+else
+vendor_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/vendor.prop)
+endif
+
+ifdef property_overrides_split_enabled
+FINAL_VENDOR_BUILD_PROPERTIES += \
+    $(call collapse-pairs, $(PRODUCT_PROPERTY_OVERRIDES))
+FINAL_VENDOR_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_VENDOR_BUILD_PROPERTIES),=)
+endif  # property_overrides_split_enabled
+
+$(INSTALLED_VENDOR_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(intermediate_system_build_prop) $(vendor_prop_files)
+	@echo Target vendor buildinfo: $@
+	@mkdir -p $(dir $@)
+	$(hide) rm -f $@ && touch $@
+ifdef property_overrides_split_enabled
+	$(hide) $(foreach line,$(FINAL_VENDOR_DEFAULT_PROPERTIES), \
+	  echo "$(line)" >> $@;)
+endif
+ifeq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
+	$(hide) echo ro.boot.dynamic_partitions=true >> $@
+endif
+ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
+	$(hide) echo ro.boot.dynamic_partitions_retrofit=true >> $@
+endif
+	$(hide) grep 'ro.product.first_api_level' $(intermediate_system_build_prop) >> $@ || true
+	$(hide) echo ro.vendor.build.security_patch="$(VENDOR_SECURITY_PATCH)">>$@
+	$(hide) echo ro.vendor.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@
+	$(hide) echo ro.vendor.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@
+	$(hide) echo ro.vendor.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@
+	$(hide) echo ro.product.board="$(TARGET_BOOTLOADER_BOARD_NAME)">>$@
+	$(hide) echo ro.board.platform="$(TARGET_BOARD_PLATFORM)">>$@
+	$(hide) echo ro.hwui.use_vulkan="$(TARGET_USES_VULKAN)">>$@
+ifdef TARGET_SCREEN_DENSITY
+	$(hide) echo ro.sf.lcd_density="$(TARGET_SCREEN_DENSITY)">>$@
+endif
+ifeq ($(AB_OTA_UPDATER),true)
+	$(hide) echo ro.build.ab_update=true >> $@
+endif
+	$(hide) $(call generate-common-build-props,vendor,$@)
+	$(hide) echo "#" >> $@; \
+	        echo "# BOOTIMAGE_BUILD_PROPERTIES" >> $@; \
+	        echo "#" >> $@;
+	$(hide) echo ro.bootimage.build.date=`$(DATE_FROM_FILE)`>>$@
+	$(hide) echo ro.bootimage.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
+	$(hide) echo ro.bootimage.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
+	$(hide) echo "#" >> $@; \
+	        echo "# ADDITIONAL VENDOR BUILD PROPERTIES" >> $@; \
+	        echo "#" >> $@;
+	$(hide) cat $(INSTALLED_ANDROID_INFO_TXT_TARGET) | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' >> $@
+ifdef property_overrides_split_enabled
+	$(hide) $(foreach file,$(vendor_prop_files), \
+	    if [ -f "$(file)" ]; then \
+	        echo Target vendor properties from: "$(file)"; \
+	        echo "" >> $@; \
+	        echo "#" >> $@; \
+	        echo "# from $(file)" >> $@; \
+	        echo "#" >> $@; \
+	        cat $(file) >> $@; \
+	        echo "# end of $(file)" >> $@; \
+	    fi;)
+	$(hide) $(foreach line,$(FINAL_VENDOR_BUILD_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+endif  # property_overrides_split_enabled
+	$(hide) $(POST_PROCESS_PROPS) $@ $(PRODUCT_VENDOR_PROPERTY_BLACKLIST)
+
+
+# -----------------------------------------------------------------
+# product build.prop
+INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/build.prop
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_BUILD_PROP_TARGET)
+
+ifdef TARGET_PRODUCT_PROP
+product_prop_files := $(TARGET_PRODUCT_PROP)
+else
+product_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/product.prop)
+endif
+
+FINAL_PRODUCT_PROPERTIES += \
+    $(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES) $(ADDITIONAL_PRODUCT_PROPERTIES))
+FINAL_PRODUCT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_PRODUCT_PROPERTIES),=)
+
+$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(product_prop_files)
+	@echo Target product buildinfo: $@
+	@mkdir -p $(dir $@)
+	$(hide) rm -f $@ && touch $@
+ifdef BOARD_USES_PRODUCTIMAGE
+	$(hide) $(call generate-common-build-props,product,$@)
+endif  # BOARD_USES_PRODUCTIMAGE
+	$(hide) $(foreach file,$(product_prop_files), \
+	    if [ -f "$(file)" ]; then \
+	        echo Target product properties from: "$(file)"; \
+	        echo "" >> $@; \
+	        echo "#" >> $@; \
+	        echo "# from $(file)" >> $@; \
+	        echo "#" >> $@; \
+	        cat $(file) >> $@; \
+	        echo "# end of $(file)" >> $@; \
+	    fi;)
+	$(hide) echo "#" >> $@; \
+	        echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \
+	        echo "#" >> $@; \
+	        echo "ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)" >> $@;
+	$(hide) $(foreach line,$(FINAL_PRODUCT_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+	$(hide) $(POST_PROCESS_PROPS) $@
+
+# ----------------------------------------------------------------
+# odm build.prop
+INSTALLED_ODM_BUILD_PROP_TARGET := $(TARGET_OUT_ODM)/etc/build.prop
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_ODM_BUILD_PROP_TARGET)
+
+ifdef TARGET_ODM_PROP
+odm_prop_files := $(TARGET_ODM_PROP)
+else
+odm_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/odm.prop)
+endif
+
+FINAL_ODM_BUILD_PROPERTIES += \
+    $(call collapse-pairs, $(PRODUCT_ODM_PROPERTIES))
+FINAL_ODM_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_ODM_BUILD_PROPERTIES),=)
+
+$(INSTALLED_ODM_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(odm_prop_files)
+	@echo Target odm buildinfo: $@
+	@mkdir -p $(dir $@)
+	$(hide) rm -f $@ && touch $@
+	$(hide) echo ro.odm.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@
+	$(hide) echo ro.odm.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@
+	$(hide) echo ro.odm.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@
+	$(hide) $(call generate-common-build-props,odm,$@)
+	$(hide) $(foreach file,$(odm_prop_files), \
+	    if [ -f "$(file)" ]; then \
+	        echo Target odm properties from: "$(file)"; \
+	        echo "" >> $@; \
+	        echo "#" >> $@; \
+	        echo "# from $(file)" >> $@; \
+	        echo "#" >> $@; \
+	        cat $(file) >> $@; \
+	        echo "# end of $(file)" >> $@; \
+	    fi;)
+	$(hide) echo "#" >> $@; \
+	        echo "# ADDITIONAL ODM BUILD PROPERTIES" >> $@; \
+	        echo "#" >> $@;
+	$(hide) $(foreach line,$(FINAL_ODM_BUILD_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+	$(hide) $(POST_PROCESS_PROPS) $@
+
+# -----------------------------------------------------------------
+# system_ext build.prop
+INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/build.prop
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)
+
+ifdef TARGET_SYSTEM_EXT_PROP
+system_ext_prop_files := $(TARGET_SYSTEM_EXT_PROP)
+else
+system_ext_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop)
+endif
+
+FINAL_SYSTEM_EXT_PROPERTIES += \
+    $(call collapse-pairs, $(PRODUCT_SYSTEM_EXT_PROPERTIES))
+FINAL_SYSTEM_EXT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_SYSTEM_EXT_PROPERTIES),=)
+
+$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(system_ext_prop_files)
+	@echo Target system_ext buildinfo: $@
+	@mkdir -p $(dir $@)
+	$(hide) rm -f $@ && touch $@
+	$(hide) $(call generate-common-build-props,system_ext,$@)
+	$(hide) $(foreach file,$(system_ext_prop_files), \
+	    if [ -f "$(file)" ]; then \
+	        echo Target system_ext properties from: "$(file)"; \
+	        echo "" >> $@; \
+	        echo "#" >> $@; \
+	        echo "# from $(file)" >> $@; \
+	        echo "#" >> $@; \
+	        cat $(file) >> $@; \
+	        echo "# end of $(file)" >> $@; \
+	    fi;)
+	$(hide) echo "#" >> $@; \
+	        echo "# ADDITIONAL SYSTEM_EXT BUILD PROPERTIES" >> $@; \
+	        echo "#" >> $@;
+	$(hide) $(foreach line,$(FINAL_SYSTEM_EXT_PROPERTIES), \
+	    echo "$(line)" >> $@;)
+	$(hide) $(POST_PROCESS_PROPS) $@
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index 87582a5..89b0b9b 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -30,6 +30,7 @@
 test_artifacts := $(COMPATIBILITY.$(test_suite_name).FILES)
 test_tools := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar \
   $(HOST_OUT_JAVA_LIBRARIES)/tradefed.jar \
+  $(HOST_OUT_JAVA_LIBRARIES)/tradefed-test-framework.jar \
   $(HOST_OUT_JAVA_LIBRARIES)/loganalysis.jar \
   $(HOST_OUT_JAVA_LIBRARIES)/compatibility-host-util.jar \
   $(HOST_OUT_JAVA_LIBRARIES)/compatibility-host-util-tests.jar \
diff --git a/envsetup.sh b/envsetup.sh
index 0ec7e6f..8699a19 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -51,8 +51,7 @@
 }
 
 # Get all the build variables needed by this script in a single call to the build system.
-function build_build_var_cache()
-{
+function build_build_var_cache() {
     local T=$(gettop)
     # Grep out the variable names from the script.
     cached_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`)
@@ -64,8 +63,7 @@
                         --var-prefix=var_cache_ \
                         --abs-var-prefix=abs_var_cache_`
     local ret=$?
-    if [ $ret -ne 0 ]
-    then
+    if [ $ret -ne 0 ]; then
         unset build_dicts_script
         return $ret
     fi
@@ -73,8 +71,7 @@
     eval "$build_dicts_script"
     ret=$?
     unset build_dicts_script
-    if [ $ret -ne 0 ]
-    then
+    if [ $ret -ne 0 ]; then
         return $ret
     fi
     BUILD_VAR_CACHE_READY="true"
@@ -82,8 +79,7 @@
 
 # Delete the build var cache, so that we can still call into the build system
 # to get build variables not listed in this script.
-function destroy_build_var_cache()
-{
+function destroy_build_var_cache() {
     unset BUILD_VAR_CACHE_READY
     local v
     for v in $cached_vars; do
@@ -97,12 +93,10 @@
 }
 
 # Get the value of a build variable as an absolute path.
-function get_abs_build_var()
-{
-    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
-    then
+function get_abs_build_var() {
+    if [ "$BUILD_VAR_CACHE_READY" == "true" ]; then
         eval "echo \"\${abs_var_cache_$1}\""
-    return
+        return
     fi
 
     local T=$(gettop)
@@ -114,10 +108,8 @@
 }
 
 # Get the exact value of a build variable.
-function get_build_var()
-{
-    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
-    then
+function get_build_var() {
+    if [ "$BUILD_VAR_CACHE_READY" == "true" ]; then
         eval "echo \"\${var_cache_$1}\""
         return 0
     fi
@@ -131,8 +123,7 @@
 }
 
 # check to see if the supplied product is one we can build
-function check_product()
-{
+function check_product() {
     local T=$(gettop)
     if [ ! "$T" ]; then
         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
@@ -149,21 +140,18 @@
 VARIANT_CHOICES=(user userdebug eng)
 
 # check to see if the supplied variant is valid
-function check_variant()
-{
+function check_variant() {
     local v
     for v in ${VARIANT_CHOICES[@]}
     do
-        if [ "$v" = "$1" ]
-        then
+        if [ "$v" == "$1" ]; then
             return 0
         fi
     done
     return 1
 }
 
-function setpaths()
-{
+function setpaths() {
     local T=$(gettop)
     if [ ! "$T" ]; then
         echo "Couldn't locate the top of the tree.  Try setting TOP."
@@ -185,10 +173,10 @@
     # due to "C:\Program Files" being in the path.
 
     # out with the old
-    if [ -n "$ANDROID_BUILD_PATHS" ] ; then
+    if [ -n "$ANDROID_BUILD_PATHS" ]; then
         export PATH=${PATH/$ANDROID_BUILD_PATHS/}
     fi
-    if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then
+    if [ -n "$ANDROID_PRE_BUILD_PATHS" ]; then
         export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/}
         # strip leading ':', if any
         export PATH=${PATH/:%/}
@@ -209,14 +197,18 @@
     local ARCH=$(get_build_var TARGET_ARCH)
     local toolchaindir toolchaindir2=
     case $ARCH in
-        x86) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
+        x86)
+            toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
             ;;
-        x86_64) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
+        x86_64)
+            toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
             ;;
-        arm) toolchaindir=arm/arm-linux-androideabi-$targetgccversion/bin
+        arm)
+            toolchaindir=arm/arm-linux-androideabi-$targetgccversion/bin
             ;;
-        arm64) toolchaindir=aarch64/aarch64-linux-android-$targetgccversion/bin;
-               toolchaindir2=arm/arm-linux-androideabi-$targetgccversion2/bin
+        arm64)
+            toolchaindir=aarch64/aarch64-linux-android-$targetgccversion/bin
+            toolchaindir2=arm/arm-linux-androideabi-$targetgccversion2/bin
             ;;
         *)
             echo "Can't find toolchain for unknown architecture: $ARCH"
@@ -317,8 +309,7 @@
     #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
 }
 
-function printconfig()
-{
+function printconfig() {
     local T=$(gettop)
     if [ ! "$T" ]; then
         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
@@ -327,8 +318,7 @@
     get_build_var report_config
 }
 
-function set_stuff_for_environment()
-{
+function set_stuff_for_environment() {
     setpaths
     set_sequence_number
 
@@ -337,8 +327,7 @@
     export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
 }
 
-function set_sequence_number()
-{
+function set_sequence_number() {
     export BUILD_ENV_SEQUENCE_NUMBER=13
 }
 
@@ -353,8 +342,7 @@
     return 0
 }
 
-function addcompletions()
-{
+function addcompletions() {
     local T dir f
 
     # Keep us from trying to run in something that's neither bash nor zsh.
@@ -382,7 +370,7 @@
         fi
     done
 
-    if should_add_completion bit ; then
+    if should_add_completion bit; then
         complete -C "bit --tab" bit
     fi
     if [ -z "$ZSH_VERSION" ]; then
@@ -395,8 +383,7 @@
     complete -F _complete_android_module_names m
 }
 
-function choosetype()
-{
+function choosetype() {
     echo "Build type choices are:"
     echo "     1. release"
     echo "     2. debug"
@@ -411,7 +398,7 @@
     while [ -z $TARGET_BUILD_TYPE ]
     do
         echo -n "Which would you like? ["$DEFAULT_NUM"] "
-        if [ -z "$1" ] ; then
+        if [ -z "$1" ]; then
             read ANSWER
         else
             echo $1
@@ -439,7 +426,7 @@
             echo
             ;;
         esac
-        if [ -n "$1" ] ; then
+        if [ -n "$1" ]; then
             break
         fi
     done
@@ -455,10 +442,9 @@
 # that kinda works with a generic product, but really, you should
 # pick a product by name.
 #
-function chooseproduct()
-{
+function chooseproduct() {
     local default_value
-    if [ "x$TARGET_PRODUCT" != x ] ; then
+    if [ "x$TARGET_PRODUCT" != x ]; then
         default_value=$TARGET_PRODUCT
     else
         default_value=aosp_arm
@@ -470,24 +456,23 @@
     while [ -z "$TARGET_PRODUCT" ]
     do
         echo -n "Which product would you like? [$default_value] "
-        if [ -z "$1" ] ; then
+        if [ -z "$1" ]; then
             read ANSWER
         else
             echo $1
             ANSWER=$1
         fi
 
-        if [ -z "$ANSWER" ] ; then
+        if [ -z "$ANSWER" ]; then
             export TARGET_PRODUCT=$default_value
         else
-            if check_product $ANSWER
-            then
+            if check_product $ANSWER; then
                 export TARGET_PRODUCT=$ANSWER
             else
                 echo "** Not a valid product: $ANSWER"
             fi
         fi
-        if [ -n "$1" ] ; then
+        if [ -n "$1" ]; then
             break
         fi
     done
@@ -497,8 +482,7 @@
     destroy_build_var_cache
 }
 
-function choosevariant()
-{
+function choosevariant() {
     echo "Variant choices are:"
     local index=1
     local v
@@ -517,35 +501,33 @@
     while [ -z "$TARGET_BUILD_VARIANT" ]
     do
         echo -n "Which would you like? [$default_value] "
-        if [ -z "$1" ] ; then
+        if [ -z "$1" ]; then
             read ANSWER
         else
             echo $1
             ANSWER=$1
         fi
 
-        if [ -z "$ANSWER" ] ; then
+        if [ -z "$ANSWER" ]; then
             export TARGET_BUILD_VARIANT=$default_value
-        elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
-            if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
+        elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$"); then
+            if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ]; then
                 export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[@]:$(($ANSWER-1)):1}
             fi
         else
-            if check_variant $ANSWER
-            then
+            if check_variant $ANSWER; then
                 export TARGET_BUILD_VARIANT=$ANSWER
             else
                 echo "** Not a valid variant: $ANSWER"
             fi
         fi
-        if [ -n "$1" ] ; then
+        if [ -n "$1" ]; then
             break
         fi
     done
 }
 
-function choosecombo()
-{
+function choosecombo() {
     choosetype $1
 
     echo
@@ -563,8 +545,7 @@
     destroy_build_var_cache
 }
 
-function add_lunch_combo()
-{
+function add_lunch_combo() {
     if [ -n "$ZSH_VERSION" ]; then
         echo -n "${funcfiletrace[1]}: "
     else
@@ -573,8 +554,7 @@
     echo "add_lunch_combo is obsolete. Use COMMON_LUNCH_CHOICES in your AndroidProducts.mk instead."
 }
 
-function print_lunch_menu()
-{
+function print_lunch_menu() {
     local uname=$(uname)
     local choices
     choices=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
@@ -584,8 +564,7 @@
     echo "You're building on" $uname
     echo
 
-    if [ $ret -ne 0 ]
-    then
+    if [ $ret -ne 0 ]; then
         echo "Warning: Cannot display lunch menu."
         echo
         echo "Note: You can invoke lunch with an explicit target:"
@@ -608,8 +587,7 @@
     echo
 }
 
-function lunch()
-{
+function lunch() {
     local answer
 
     if [[ $# -gt 1 ]]; then
@@ -627,17 +605,13 @@
 
     local selection=
 
-    if [ -z "$answer" ]
-    then
+    if [ -z "$answer" ]; then
         selection=aosp_arm-eng
-    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
-    then
+    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$"); then
         local choices=($(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES))
-        if [ $answer -le ${#choices[@]} ]
-        then
+        if [ $answer -le ${#choices[@]} ]; then
             # array in zsh starts from 1 instead of 0.
-            if [ -n "$ZSH_VERSION" ]
-            then
+            if [ -n "$ZSH_VERSION" ]; then
                 selection=${choices[$(($answer))]}
             else
                 selection=${choices[$(($answer-1))]}
@@ -660,8 +634,7 @@
         fi
     fi
 
-    if [ -z "$product" ]
-    then
+    if [ -z "$product" ]; then
         echo
         echo "Invalid lunch combo: $selection"
         return 1
@@ -671,8 +644,7 @@
     TARGET_BUILD_VARIANT=$variant \
     TARGET_PLATFORM_VERSION=$version \
     build_build_var_cache
-    if [ $? -ne 0 ]
-    then
+    if [ $? -ne 0 ]; then
         return 1
     fi
 
@@ -694,8 +666,7 @@
 
 unset COMMON_LUNCH_CHOICES_CACHE
 # Tab completion for lunch.
-function _lunch()
-{
+function _lunch() {
     local cur prev opts
     COMPREPLY=()
     cur="${COMP_WORDS[COMP_CWORD]}"
@@ -711,8 +682,7 @@
 
 # Configures the build to build unbundled apps.
 # Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
-function tapas()
-{
+function tapas() {
     local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
     local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|arm64|x86_64)$' | xargs)"
     local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
@@ -739,9 +709,15 @@
 
     local product=aosp_arm
     case $arch in
-      x86)    product=aosp_x86;;
-      arm64)  product=aosp_arm64;;
-      x86_64) product=aosp_x86_64;;
+        x86)
+            product=aosp_x86
+            ;;
+        arm64)
+            product=aosp_arm64
+            ;;
+        x86_64)
+            product=aosp_x86_64
+            ;;
     esac
     if [ -z "$variant" ]; then
         variant=eng
@@ -765,14 +741,13 @@
     destroy_build_var_cache
 }
 
-function gettop
-{
+function gettop {
     local TOPFILE=build/make/core/envsetup.mk
-    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
+    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ]; then
         # The following circumlocution ensures we remove symlinks from TOP.
         (cd $TOP; PWD= /bin/pwd)
     else
-        if [ -f $TOPFILE ] ; then
+        if [ -f $TOPFILE ]; then
             # The following circumlocution (repeated below as well) ensures
             # that we record the true directory name and not one that is
             # faked up with symlink names.
@@ -792,8 +767,7 @@
     fi
 }
 
-function croot()
-{
+function croot() {
     local T=$(gettop)
     if [ "$T" ]; then
         if [ "$1" ]; then
@@ -806,8 +780,7 @@
     fi
 }
 
-function _croot()
-{
+function _croot() {
     local T=$(gettop)
     if [ "$T" ]; then
         local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -818,8 +791,7 @@
     fi
 }
 
-function cproj()
-{
+function cproj() {
     local TOPFILE=build/make/core/envsetup.mk
     local HERE=$PWD
     local T=
@@ -840,17 +812,17 @@
 function qpid() {
     local prepend=''
     local append=''
-    if [ "$1" = "--exact" ]; then
+    if [ "$1" == "--exact" ]; then
         prepend=' '
         append='$'
         shift
-    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
+    elif [ "$1" == "--help" -o "$1" == "-h" ]; then
         echo "usage: qpid [[--exact] <process name|pid>"
         return 255
     fi
 
     local EXE="$1"
-    if [ "$EXE" ] ; then
+    if [ "$EXE" ]; then
         qpid | \grep "$prepend$EXE$append"
     else
         adb shell ps \
@@ -866,92 +838,87 @@
 #       if its core-file-size limit is not set already.
 # NOTE: Core dumps are written to ramdisk; they will not survive a reboot!
 
-function coredump_setup()
-{
-    echo "Getting root...";
-    adb root;
-    adb wait-for-device;
+function coredump_setup() {
+    echo "Getting root..."
+    adb root
+    adb wait-for-device
 
-    echo "Remounting root partition read-write...";
-    adb shell mount -w -o remount -t rootfs rootfs;
-    sleep 1;
-    adb wait-for-device;
-    adb shell mkdir -p /cores;
-    adb shell mount -t tmpfs tmpfs /cores;
-    adb shell chmod 0777 /cores;
+    echo "Remounting root partition read-write..."
+    adb shell mount -w -o remount -t rootfs rootfs
+    sleep 1
+    adb wait-for-device
+    adb shell mkdir -p /cores
+    adb shell mount -t tmpfs tmpfs /cores
+    adb shell chmod 0777 /cores
 
-    echo "Granting SELinux permission to dump in /cores...";
-    adb shell restorecon -R /cores;
+    echo "Granting SELinux permission to dump in /cores..."
+    adb shell restorecon -R /cores
 
-    echo "Set core pattern.";
-    adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern';
+    echo "Set core pattern."
+    adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern'
 
     echo "Done."
 }
 
 # coredump_enable - enable core dumps for the specified process
-# $1 = PID of process (e.g., $(pid mediaserver))
+# $1 == PID of process (e.g., $(pid mediaserver))
 #
 # NOTE: coredump_setup must have been called as well for a core
 #       dump to actually be generated.
 
-function coredump_enable()
-{
-    local PID=$1;
+function coredump_enable() {
+    local PID=$1
     if [ -z "$PID" ]; then
-        printf "Expecting a PID!\n";
-        return;
-    fi;
-    echo "Setting core limit for $PID to infinite...";
+        printf "Expecting a PID!\n"
+        return
+    fi
+    echo "Setting core limit for $PID to infinite..."
     adb shell /system/bin/ulimit -p $PID -c unlimited
 }
 
 # core - send SIGV and pull the core for process
-# $1 = PID of process (e.g., $(pid mediaserver))
+# $1 == PID of process (e.g., $(pid mediaserver))
 #
 # NOTE: coredump_setup must be called once per boot for core dumps to be
 #       enabled globally.
 
-function core()
-{
-    local PID=$1;
+function core() {
+    local PID=$1
 
     if [ -z "$PID" ]; then
-        printf "Expecting a PID!\n";
-        return;
-    fi;
+        printf "Expecting a PID!\n"
+        return
+    fi
 
-    local CORENAME=core.$PID;
-    local COREPATH=/cores/$CORENAME;
-    local SIG=SEGV;
+    local CORENAME=core.$PID
+    local COREPATH=/cores/$CORENAME
+    local SIG=SEGV
 
-    coredump_enable $1;
+    coredump_enable $1
 
-    local done=0;
+    local done=0
     while [ $(adb shell "[ -d /proc/$PID ] && echo -n yes") ]; do
-        printf "\tSending SIG%s to %d...\n" $SIG $PID;
-        adb shell kill -$SIG $PID;
-        sleep 1;
-    done;
+        printf "\tSending SIG%s to %d...\n" $SIG $PID
+        adb shell kill -$SIG $PID
+        sleep 1
+    done
 
-    adb shell "while [ ! -f $COREPATH ] ; do echo waiting for $COREPATH to be generated; sleep 1; done"
-    echo "Done: core is under $COREPATH on device.";
+    adb shell "while [ ! -f $COREPATH ]; do echo waiting for $COREPATH to be generated; sleep 1; done"
+    echo "Done: core is under $COREPATH on device."
 }
 
 # systemstack - dump the current stack trace of all threads in the system process
 # to the usual ANR traces file
-function systemstack()
-{
+function systemstack() {
     stacks system_server
 }
 
 # Read the ELF header from /proc/$PID/exe to determine if the process is
 # 64-bit.
-function is64bit()
-{
+function is64bit() {
     local PID="$1"
-    if [ "$PID" ] ; then
-        if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -p)" -eq "02" ]] ; then
+    if [ "$PID" ]; then
+        if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -p)" -eq "02" ]]; then
             echo "64"
         else
             echo ""
@@ -963,107 +930,90 @@
 
 case `uname -s` in
     Darwin)
-        function sgrep()
-        {
+        function sgrep() {
             find -E . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.(c|h|cc|cpp|hpp|S|java|xml|sh|mk|aidl|vts|proto)' \
                 -exec grep --color -n "$@" {} +
         }
-
         ;;
     *)
-        function sgrep()
-        {
+        function sgrep() {
             find . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.\(c\|h\|cc\|cpp\|hpp\|S\|java\|xml\|sh\|mk\|aidl\|vts\|proto\)' \
                 -exec grep --color -n "$@" {} +
         }
         ;;
 esac
 
-function gettargetarch
-{
+function gettargetarch {
     get_build_var TARGET_ARCH
 }
 
-function ggrep()
-{
+function ggrep() {
     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.gradle" \
         -exec grep --color -n "$@" {} +
 }
 
-function gogrep()
-{
+function gogrep() {
     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.go" \
         -exec grep --color -n "$@" {} +
 }
 
-function jgrep()
-{
+function jgrep() {
     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" \
         -exec grep --color -n "$@" {} +
 }
 
-function cgrep()
-{
+function cgrep() {
     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) \
         -exec grep --color -n "$@" {} +
 }
 
-function resgrep()
-{
+function resgrep() {
     local dir
     for dir in `find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -name res -type d`; do
         find $dir -type f -name '*\.xml' -exec grep --color -n "$@" {} +
     done
 }
 
-function mangrep()
-{
+function mangrep() {
     find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'AndroidManifest.xml' \
         -exec grep --color -n "$@" {} +
 }
 
-function owngrep()
-{
+function owngrep() {
     find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'OWNERS' \
         -exec grep --color -n "$@" {} +
 }
 
-function sepgrep()
-{
+function sepgrep() {
     find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -name sepolicy -type d \
         -exec grep --color -n -r --exclude-dir=\.git "$@" {} +
 }
 
-function rcgrep()
-{
+function rcgrep() {
     find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.rc*" \
         -exec grep --color -n "$@" {} +
 }
 
 case `uname -s` in
     Darwin)
-        function mgrep()
-        {
+        function mgrep() {
             find -E . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o \( -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk|.*\.bp)' -o -regex '(.*/)?(build|soong)/.*[^/]*\.go' \) -type f \
                 -exec grep --color -n "$@" {} +
         }
 
-        function treegrep()
-        {
+        function treegrep() {
             find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|hpp|S|java|xml)' \
                 -exec grep --color -n -i "$@" {} +
         }
 
         ;;
     *)
-        function mgrep()
-        {
+        function mgrep() {
             find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o \( -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk|.*\.bp)' -o -regextype posix-extended -regex '(.*/)?(build|soong)/.*[^/]*\.go' \) -type f \
                 -exec grep --color -n "$@" {} +
         }
 
-        function treegrep()
-        {
+        function treegrep() {
             find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '.*\.(c|h|cpp|hpp|S|java|xml)' -type f \
                 -exec grep --color -n -i "$@" {} +
         }
@@ -1071,13 +1021,11 @@
         ;;
 esac
 
-function getprebuilt
-{
+function getprebuilt {
     get_abs_build_var ANDROID_PREBUILTS
 }
 
-function tracedmdump()
-{
+function tracedmdump() {
     local T=$(gettop)
     if [ ! "$T" ]; then
         echo "Couldn't locate the top of the tree.  Try setting TOP."
@@ -1088,18 +1036,18 @@
     local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
 
     local TRACE=$1
-    if [ ! "$TRACE" ] ; then
+    if [ ! "$TRACE" ]; then
         echo "usage:  tracedmdump  tracename"
         return
     fi
 
-    if [ ! -r "$KERNEL" ] ; then
+    if [ ! -r "$KERNEL" ]; then
         echo "Error: cannot find kernel: '$KERNEL'"
         return
     fi
 
     local BASETRACE=$(basename $TRACE)
-    if [ "$BASETRACE" = "$TRACE" ] ; then
+    if [ "$BASETRACE" == "$TRACE" ]; then
         TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
     fi
 
@@ -1125,24 +1073,23 @@
 
 # communicate with a running device or emulator, set up necessary state,
 # and run the hat command.
-function runhat()
-{
+function runhat() {
     # process standard adb options
     local adbTarget=""
-    if [ "$1" = "-d" -o "$1" = "-e" ]; then
+    if [ "$1" == "-d" -o "$1" == "-e" ]; then
         adbTarget=$1
         shift 1
-    elif [ "$1" = "-s" ]; then
+    elif [ "$1" == "-s" ]; then
         adbTarget="$1 $2"
         shift 2
     fi
     local adbOptions=${adbTarget}
-    #echo adbOptions = ${adbOptions}
+    #echo adbOptions == ${adbOptions}
 
     # runhat options
     local targetPid=$1
 
-    if [ "$targetPid" = "" ]; then
+    if [ "$targetPid" == "" ]; then
         echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
         return
     fi
@@ -1175,8 +1122,7 @@
     hat -JXmx512m $localFile
 }
 
-function getbugreports()
-{
+function getbugreports() {
     local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)
 
     if [ ! "$reports" ]; then
@@ -1193,21 +1139,18 @@
     done
 }
 
-function getsdcardpath()
-{
+function getsdcardpath() {
     adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
 }
 
-function getscreenshotpath()
-{
+function getscreenshotpath() {
     echo "$(getsdcardpath)/Pictures/Screenshots"
 }
 
-function getlastscreenshot()
-{
+function getlastscreenshot() {
     local screenshot_path=$(getscreenshotpath)
     local screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
-    if [ "$screenshot" = "" ]; then
+    if [ "$screenshot" == "" ]; then
         echo "No screenshots found."
         return
     fi
@@ -1215,8 +1158,7 @@
     adb ${adbOptions} pull ${screenshot_path}/${screenshot}
 }
 
-function startviewserver()
-{
+function startviewserver() {
     local port=4939
     if [ $# -gt 0 ]; then
             port=$1
@@ -1224,33 +1166,27 @@
     adb shell service call window 1 i32 $port
 }
 
-function stopviewserver()
-{
+function stopviewserver() {
     adb shell service call window 2
 }
 
-function isviewserverstarted()
-{
+function isviewserverstarted() {
     adb shell service call window 3
 }
 
-function key_home()
-{
+function key_home() {
     adb shell input keyevent 3
 }
 
-function key_back()
-{
+function key_back() {
     adb shell input keyevent 4
 }
 
-function key_menu()
-{
+function key_menu() {
     adb shell input keyevent 82
 }
 
-function smoketest()
-{
+function smoketest() {
     if [ ! "$ANDROID_PRODUCT_OUT" ]; then
         echo "Couldn't locate output files.  Try running 'lunch' first." >&2
         return
@@ -1270,8 +1206,7 @@
 }
 
 # simple shortcut to the runtest command
-function runtest()
-{
+function runtest() {
     local T=$(gettop)
     if [ ! "$T" ]; then
         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
@@ -1287,7 +1222,7 @@
     fi
     local T=$(gettop)
     local FILELIST
-    if [ ! "$OUT_DIR" = "" ]; then
+    if [ ! "$OUT_DIR" == "" ]; then
         mkdir -p $OUT_DIR
         FILELIST=$OUT_DIR/filelist
     else
@@ -1301,7 +1236,7 @@
     fi
     local lines
     lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
-    if [[ ${#lines[@]} = 0 ]]; then
+    if [[ ${#lines[@]} == 0 ]]; then
         echo "Not found"
         return
     fi
@@ -1421,8 +1356,7 @@
 function pez {
     "$@"
     local retval=$?
-    if [ $retval -ne 0 ]
-    then
+    if [ $retval -ne 0 ]; then
         echo $'\E'"[0;31mFAILURE\e[00m"
     else
         echo $'\E'"[0;32mSUCCESS\e[00m"
@@ -1430,8 +1364,7 @@
     return $retval
 }
 
-function get_make_command()
-{
+function get_make_command() {
     # If we're in the top of an Android tree, use soong_ui.bash instead of make
     if [ -f build/soong/soong_ui.bash ]; then
         # Always use the real make if -C is passed in
@@ -1447,8 +1380,7 @@
     fi
 }
 
-function _wrap_build()
-{
+function _wrap_build() {
     if [[ "${ANDROID_QUIET_BUILD:-}" == true ]]; then
       "$@"
       return $?
@@ -1472,16 +1404,16 @@
         color_reset=""
     fi
     echo
-    if [ $ret -eq 0 ] ; then
+    if [ $ret -eq 0 ]; then
         echo -n "${color_success}#### build completed successfully "
     else
         echo -n "${color_failed}#### failed to build some targets "
     fi
-    if [ $hours -gt 0 ] ; then
+    if [ $hours -gt 0 ]; then
         printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
-    elif [ $mins -gt 0 ] ; then
+    elif [ $mins -gt 0 ]; then
         printf "(%02g:%02g (mm:ss))" $mins $secs
-    elif [ $secs -gt 0 ] ; then
+    elif [ $secs -gt 0 ]; then
         printf "(%s seconds)" $secs
     fi
     echo " ####${color_reset}"
@@ -1524,13 +1456,11 @@
     _trigger_build "modules-in-dirs" "$@"
 )
 
-function make()
-{
+function make() {
     _wrap_build $(get_make_command "$@") "$@"
 }
 
-function provision()
-{
+function provision() {
     if [ ! "$ANDROID_PRODUCT_OUT" ]; then
         echo "Couldn't locate output files.  Try running 'lunch' first." >&2
         return 1
@@ -1541,7 +1471,7 @@
     fi
 
     # Check if user really wants to do this.
-    if [ "$1" = "--no-confirmation" ]; then
+    if [ "$1" == "--no-confirmation" ]; then
         shift 1
     else
         echo "This action will reflash your device."
@@ -1550,7 +1480,7 @@
         echo ""
         echo -n "Are you sure you want to do this (yes/no)? "
         read
-        if [[ "${REPLY}" != "yes" ]] ; then
+        if [[ "${REPLY}" != "yes" ]]; then
             echo "Not taking any action. Exiting." >&2
             return 1
         fi
@@ -1575,7 +1505,8 @@
             ;;
         *zsh*)
             function check_type() { type "$1"; }
-            enable_zsh_completion ;;
+            enable_zsh_completion
+            ;;
         *)
             echo -e "WARNING: Only bash and zsh are supported.\nUse of other shell would lead to erroneous results."
             ;;
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index a2e5518..e9fb096 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -33,8 +33,6 @@
   # emulator needs super.img
   BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
 
-  BOARD_EXT4_SHARE_DUP_BLOCKS := true
-
   # 3G + header
   BOARD_SUPER_PARTITION_SIZE := 3229614080
   BOARD_SUPER_PARTITION_GROUPS := emulator_dynamic_partitions
diff --git a/target/board/BoardConfigMainlineCommon.mk b/target/board/BoardConfigMainlineCommon.mk
index c57968e..bf015e5 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -6,6 +6,8 @@
 TARGET_NO_BOOTLOADER := true
 TARGET_NO_RECOVERY := true
 
+BOARD_EXT4_SHARE_DUP_BLOCKS := true
+
 TARGET_USERIMAGES_USE_EXT4 := true
 
 # Mainline devices must have /system_ext, /vendor and /product partitions.
diff --git a/target/board/emulator_arm64/device.mk b/target/board/emulator_arm64/device.mk
index 6753c11..57675d0 100644
--- a/target/board/emulator_arm64/device.mk
+++ b/target/board/emulator_arm64/device.mk
@@ -14,6 +14,9 @@
 # limitations under the License.
 #
 
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
 # Cuttlefish has GKI kernel prebuilts, so use those for the GKI boot.img.
 ifeq ($(TARGET_PREBUILT_KERNEL),)
     LOCAL_KERNEL := device/google/cuttlefish_kernel/5.4-arm64/kernel
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index 0a32415..cfb15f0 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -14,6 +14,9 @@
 # limitations under the License.
 #
 
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
 # 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
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index d793c38..2963ee4 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -54,13 +54,13 @@
 
 include build/make/target/board/BoardConfigGsiCommon.mk
 
-BOARD_EXT4_SHARE_DUP_BLOCKS := true
-
 TARGET_NO_KERNEL := false
 TARGET_NO_VENDOR_BOOT := true
 BOARD_USES_RECOVERY_AS_BOOT := true
 
-BOARD_BOOTIMAGE_PARTITION_SIZE := 0x04000000
+BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
+BOARD_KERNEL-5.4-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
+BOARD_KERNEL-5.4-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
 
 BOARD_BOOT_HEADER_VERSION := 3
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index bbab2b4..2b10a3d 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,6 +14,9 @@
 # limitations under the License.
 #
 
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
 ifdef NET_ETH0_STARTONBOOT
   PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
 endif
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index bbab2b4..2b10a3d 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -14,6 +14,9 @@
 # limitations under the License.
 #
 
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
 ifdef NET_ETH0_STARTONBOOT
   PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
 endif
diff --git a/target/board/generic_x86_64_arm64/device.mk b/target/board/generic_x86_64_arm64/device.mk
index fa1eb67..76242c9 100755
--- a/target/board/generic_x86_64_arm64/device.mk
+++ b/target/board/generic_x86_64_arm64/device.mk
@@ -13,3 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index fa1eb67..76242c9 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -13,3 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 68130e3..a1acaab 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -14,6 +14,9 @@
 # limitations under the License.
 #
 
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
 # This is a generic phone product that isn't specialized for a specific device.
 # It includes the base Android platform.
 
diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota_plus_non_ab.mk
new file mode 100644
index 0000000..325d75e
--- /dev/null
+++ b/target/product/virtual_ab_ota_plus_non_ab.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2020 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/virtual_ab_ota.mk)
+
+PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true
+
+PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.allow_non_ab=true
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 72f065d..8b6a690 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -1558,6 +1558,7 @@
     split_large_apks = []
     cache_size = common.OPTIONS.cache_size
     split_threshold = 0.125
+    assert cache_size is not None
     max_blocks_per_transfer = int(cache_size * split_threshold /
                                   self.tgt.blocksize)
     empty = RangeSet()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 42c29c0..96f93a8 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -677,9 +677,14 @@
   makeint("userdata_size")
   makeint("cache_size")
   makeint("recovery_size")
-  makeint("boot_size")
   makeint("fstab_version")
 
+  boot_images = "boot.img"
+  if "boot_images" in d:
+    boot_images = d["boot_images"]
+  for b in boot_images.split():
+    makeint(b.replace(".img","_size"))
+
   # Load recovery fstab if applicable.
   d["fstab"] = _FindAndLoadRecoveryFstab(d, input_file, read_helper)
 
@@ -843,12 +848,13 @@
 def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
                       system_root_image=False):
   class Partition(object):
-    def __init__(self, mount_point, fs_type, device, length, context):
+    def __init__(self, mount_point, fs_type, device, length, context, slotselect):
       self.mount_point = mount_point
       self.fs_type = fs_type
       self.device = device
       self.length = length
       self.context = context
+      self.slotselect = slotselect
 
   try:
     data = read_helper(recovery_fstab_path)
@@ -876,10 +882,13 @@
 
     # It's a good line, parse it.
     length = 0
+    slotselect = False
     options = options.split(",")
     for i in options:
       if i.startswith("length="):
         length = int(i[7:])
+      elif i == "slotselect":
+        slotselect = True
       else:
         # Ignore all unknown options in the unified fstab.
         continue
@@ -893,7 +902,8 @@
 
     mount_point = pieces[1]
     d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[2],
-                               device=pieces[0], length=length, context=context)
+                               device=pieces[0], length=length, context=context,
+                               slotselect=slotselect)
 
   # / is used for the system mount point when the root directory is included in
   # system. Other areas assume system is always at "/system" so point /system
@@ -908,7 +918,8 @@
   """Finds the path to recovery fstab and loads its contents."""
   # recovery fstab is only meaningful when installing an update via recovery
   # (i.e. non-A/B OTA). Skip loading fstab if device used A/B OTA.
-  if info_dict.get('ab_update') == 'true':
+  if info_dict.get('ab_update') == 'true' and \
+     info_dict.get("allow_non_ab") != "true":
     return None
 
   # We changed recovery.fstab path in Q, from ../RAMDISK/etc/recovery.fstab to
@@ -1334,7 +1345,10 @@
   # AVB: if enabled, calculate and add hash to boot.img or recovery.img.
   if info_dict.get("avb_enable") == "true":
     avbtool = info_dict["avb_avbtool"]
-    part_size = info_dict[partition_name + "_size"]
+    if partition_name == "recovery":
+      part_size = info_dict["recovery_size"]
+    else:
+      part_size = info_dict[image_name.replace(".img","_size")]
     cmd = [avbtool, "add_hash_footer", "--image", img.name,
            "--partition_size", str(part_size), "--partition_name",
            partition_name]
@@ -2672,11 +2686,12 @@
       self.device = 'map_partition("%s")' % partition
     else:
       if OPTIONS.source_info_dict is None:
-        _, device_path = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+        _, device_expr = GetTypeAndDeviceExpr("/" + partition,
+                                              OPTIONS.info_dict)
       else:
-        _, device_path = GetTypeAndDevice("/" + partition,
-                                          OPTIONS.source_info_dict)
-      self.device = '"%s"' % device_path
+        _, device_expr = GetTypeAndDeviceExpr("/" + partition,
+                                              OPTIONS.source_info_dict)
+      self.device = device_expr
 
   @property
   def required_cache(self):
@@ -2908,16 +2923,51 @@
     "squashfs": "EMMC"
 }
 
-
-def GetTypeAndDevice(mount_point, info):
+def GetTypeAndDevice(mount_point, info, check_no_slot=True):
+  """
+  Use GetTypeAndDeviceExpr whenever possible. This function is kept for
+  backwards compatibility. It aborts if the fstab entry has slotselect option
+  (unless check_no_slot is explicitly set to False).
+  """
   fstab = info["fstab"]
   if fstab:
+    if check_no_slot:
+      assert not fstab[mount_point].slotselect, \
+             "Use GetTypeAndDeviceExpr instead"
     return (PARTITION_TYPES[fstab[mount_point].fs_type],
             fstab[mount_point].device)
   else:
     raise KeyError
 
 
+def GetTypeAndDeviceExpr(mount_point, info):
+  """
+  Return the filesystem of the partition, and an edify expression that evaluates
+  to the device at runtime.
+  """
+  fstab = info["fstab"]
+  if fstab:
+    p = fstab[mount_point]
+    device_expr = '"%s"' % fstab[mount_point].device
+    if p.slotselect:
+      device_expr = 'add_slot_suffix(%s)' % device_expr
+    return (PARTITION_TYPES[fstab[mount_point].fs_type], device_expr)
+  else:
+    raise KeyError
+
+
+def GetEntryForDevice(fstab, device):
+  """
+  Returns:
+    The first entry in fstab whose device is the given value.
+  """
+  if not fstab:
+    return None
+  for mount_point in fstab:
+    if fstab[mount_point].device == device:
+      return fstab[mount_point]
+  return None
+
 def ParseCertificate(data):
   """Parses and converts a PEM-encoded certificate into DER-encoded.
 
@@ -3042,8 +3092,10 @@
   try:
     # The following GetTypeAndDevice()s need to use the path in the target
     # info_dict instead of source_info_dict.
-    boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
-    recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
+    boot_type, boot_device = GetTypeAndDevice("/boot", info_dict,
+                                              check_no_slot=False)
+    recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict,
+                                                      check_no_slot=False)
   except KeyError:
     return
 
@@ -3085,8 +3137,8 @@
        'recovery_size': recovery_img.size,
        'recovery_sha1': recovery_img.sha1,
        'boot_type': boot_type,
-       'boot_device': boot_device,
-       'recovery_type': recovery_type,
+       'boot_device': boot_device + '$(getprop ro.boot.slot_suffix)',
+       'recovery_type': recovery_type + '$(getprop ro.boot.slot_suffix)',
        'recovery_device': recovery_device,
        'bonus_args': bonus_args}
 
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 7ed85fe..99e21f1 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -183,11 +183,30 @@
     It checks the checksums of the given partitions. If none of them matches the
     expected checksum, updater will additionally look for a backup on /cache.
     """
+    self._CheckSecondTokenNotSlotSuffixed(target, "PatchPartitionExprCheck")
+    self._CheckSecondTokenNotSlotSuffixed(source, "PatchPartitionExprCheck")
+    self.PatchPartitionExprCheck('"%s"' % target, '"%s"' % source)
+
+  def PatchPartitionExprCheck(self, target_expr, source_expr):
+    """Checks whether updater can patch the given partitions.
+
+    It checks the checksums of the given partitions. If none of them matches the
+    expected checksum, updater will additionally look for a backup on /cache.
+
+    Args:
+      target_expr: an Edify expression that serves as the target arg to
+        patch_partition. Must be evaluated to a string in the form of
+        foo:bar:baz:quux
+      source_expr: an Edify expression that serves as the source arg to
+        patch_partition. Must be evaluated to a string in the form of
+        foo:bar:baz:quux
+    """
     self.script.append(self.WordWrap((
-        'patch_partition_check("{target}",\0"{source}") ||\n    abort('
-        '"E{code}: \\"{target}\\" or \\"{source}\\" has unexpected '
-        'contents.");').format(
-            target=target, source=source,
+        'patch_partition_check({target},\0{source}) ||\n    abort('
+        'concat("E{code}: \\"",{target},"\\" or \\"",{source},"\\" has '
+        'unexpected contents."));').format(
+            target=target_expr,
+            source=source_expr,
             code=common.ErrorCode.BAD_PATCH_FILE)))
 
   def CacheFreeSpaceCheck(self, amount):
@@ -218,8 +237,9 @@
       mount_flags = mount_dict.get(p.fs_type, "")
       if p.context is not None:
         mount_flags = p.context + ("," + mount_flags if mount_flags else "")
-      self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % (
-          p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device,
+      self.script.append('mount("%s", "%s", %s, "%s", "%s");' % (
+          p.fs_type, common.PARTITION_TYPES[p.fs_type],
+          self._GetSlotSuffixDeviceForEntry(p),
           p.mount_point, mount_flags))
       self.mounts.add(p.mount_point)
 
@@ -242,8 +262,9 @@
         raise ValueError("Partition %s cannot be tuned\n" % (partition,))
     self.script.append(
         'tune2fs(' + "".join(['"%s", ' % (i,) for i in options]) +
-        '"%s") || abort("E%d: Failed to tune partition %s");' % (
-            p.device, common.ErrorCode.TUNE_PARTITION_FAILURE, partition))
+        '%s) || abort("E%d: Failed to tune partition %s");' % (
+            self._GetSlotSuffixDeviceForEntry(p),
+            common.ErrorCode.TUNE_PARTITION_FAILURE, partition))
 
   def FormatPartition(self, partition):
     """Format the given partition, specified by its mount point (eg,
@@ -252,18 +273,19 @@
     fstab = self.fstab
     if fstab:
       p = fstab[partition]
-      self.script.append('format("%s", "%s", "%s", "%s", "%s");' %
+      self.script.append('format("%s", "%s", %s, "%s", "%s");' %
                          (p.fs_type, common.PARTITION_TYPES[p.fs_type],
-                          p.device, p.length, p.mount_point))
+                          self._GetSlotSuffixDeviceForEntry(p),
+                          p.length, p.mount_point))
 
   def WipeBlockDevice(self, partition):
     if partition not in ("/system", "/vendor"):
       raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,))
     fstab = self.fstab
     size = self.info.get(partition.lstrip("/") + "_size", None)
-    device = fstab[partition].device
+    device = self._GetSlotSuffixDeviceForEntry(fstab[partition])
 
-    self.script.append('wipe_block_device("%s", %s);' % (device, size))
+    self.script.append('wipe_block_device(%s, %s);' % (device, size))
 
   def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
     """Apply binary patches (in *patchpairs) to the given srcfile to
@@ -296,14 +318,69 @@
     self.PatchPartition(target, source, patch)
 
   def PatchPartition(self, target, source, patch):
-    """Applies the patch to the source partition and writes it to target."""
+    """
+    Applies the patch to the source partition and writes it to target.
+
+    Args:
+      target: the target arg to patch_partition. Must be in the form of
+        foo:bar:baz:quux
+      source: the source arg to patch_partition. Must be in the form of
+        foo:bar:baz:quux
+      patch: the patch arg to patch_partition. Must be an unquoted string.
+    """
+    self._CheckSecondTokenNotSlotSuffixed(target, "PatchPartitionExpr")
+    self._CheckSecondTokenNotSlotSuffixed(source, "PatchPartitionExpr")
+    self.PatchPartitionExpr('"%s"' % target, '"%s"' % source, '"%s"' % patch)
+
+  def PatchPartitionExpr(self, target_expr, source_expr, patch_expr):
+    """
+    Applies the patch to the source partition and writes it to target.
+
+    Args:
+      target_expr: an Edify expression that serves as the target arg to
+        patch_partition. Must be evaluated to a string in the form of
+        foo:bar:baz:quux
+      source_expr: an Edify expression that serves as the source arg to
+        patch_partition. Must be evaluated to a string in the form of
+        foo:bar:baz:quux
+      patch_expr: an Edify expression that serves as the patch arg to
+        patch_partition. Must be evaluated to a string.
+    """
     self.script.append(self.WordWrap((
-        'patch_partition("{target}",\0"{source}",\0'
-        'package_extract_file("{patch}")) ||\n'
-        '    abort("E{code}: Failed to apply patch to {source}");').format(
-            target=target, source=source, patch=patch,
+        'patch_partition({target},\0{source},\0'
+        'package_extract_file({patch})) ||\n'
+        '    abort(concat('
+        '        "E{code}: Failed to apply patch to ",{source}));').format(
+            target=target_expr,
+            source=source_expr,
+            patch=patch_expr,
             code=common.ErrorCode.APPLY_PATCH_FAILURE)))
 
+  def _GetSlotSuffixDeviceForEntry(self, entry=None):
+    """
+    Args:
+      entry: the fstab entry of device "foo"
+    Returns:
+      An edify expression. Caller must not quote result.
+      If foo is slot suffixed, it returns
+        'add_slot_suffix("foo")'
+      Otherwise it returns
+        '"foo"' (quoted)
+    """
+    assert entry is not None
+    if entry.slotselect:
+      return 'add_slot_suffix("%s")' % entry.device
+    return '"%s"' % entry.device
+
+  def _CheckSecondTokenNotSlotSuffixed(self, s, fn):
+    lst = s.split(':')
+    assert(len(s) == 4), "{} does not contain 4 tokens".format(s)
+    if self.fstab:
+      entry = common.GetEntryForDevice(s[1])
+      if entry is not None:
+        assert not entry.slotselect, \
+          "Use %s because %s is slot suffixed" % (fn, s[1])
+
   def WriteRawImage(self, mount_point, fn, mapfn=None):
     """Write the given package file into the partition for the given
     mount point."""
@@ -312,15 +389,16 @@
     if fstab:
       p = fstab[mount_point]
       partition_type = common.PARTITION_TYPES[p.fs_type]
-      args = {'device': p.device, 'fn': fn}
+      device = self._GetSlotSuffixDeviceForEntry(p)
+      args = {'device': device, 'fn': fn}
       if partition_type == "EMMC":
         if mapfn:
           args["map"] = mapfn
           self.script.append(
-              'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args)
+              'package_extract_file("%(fn)s", %(device)s, "%(map)s");' % args)
         else:
           self.script.append(
-              'package_extract_file("%(fn)s", "%(device)s");' % args)
+              'package_extract_file("%(fn)s", %(device)s);' % args)
       else:
         raise ValueError(
             "don't know how to write \"%s\" partitions" % p.fs_type)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index ad001d1..16b278a 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -78,6 +78,13 @@
       Write a copy of the metadata to a separate file. Therefore, users can
       read the post build fingerprint without extracting the OTA package.
 
+  --force_non_ab
+      This flag can only be set on an A/B device that also supports non-A/B
+      updates. Implies --two_step.
+      If set, generate that non-A/B update package.
+      If not set, generates A/B package for A/B device and non-A/B package for
+      non-A/B device.
+
 Non-A/B OTA specific options
 
   -b  (--binary) <file>
@@ -251,6 +258,7 @@
 OPTIONS.output_metadata_path = None
 OPTIONS.disable_fec_computation = False
 OPTIONS.boot_variable_values = None
+OPTIONS.force_non_ab = False
 
 
 METADATA_NAME = 'META-INF/com/android/metadata'
@@ -933,7 +941,7 @@
           'ro.build.version.security_patch'),
   }
 
-  if target_info.is_ab:
+  if target_info.is_ab and not OPTIONS.force_non_ab:
     metadata['ota-type'] = 'AB'
     metadata['ota-required-cache'] = '0'
   else:
@@ -1455,7 +1463,8 @@
   required_cache_sizes = [diff.required_cache for diff in
                           block_diff_dict.values()]
   if updating_boot:
-    boot_type, boot_device = common.GetTypeAndDevice("/boot", source_info)
+    boot_type, boot_device_expr = common.GetTypeAndDeviceExpr("/boot",
+                                                              source_info)
     d = common.Difference(target_boot, source_boot)
     _, _, d = d.ComputePatch()
     if d is None:
@@ -1470,11 +1479,11 @@
 
       common.ZipWriteStr(output_zip, "boot.img.p", d)
 
-      script.PatchPartitionCheck(
-          "{}:{}:{}:{}".format(
-              boot_type, boot_device, target_boot.size, target_boot.sha1),
-          "{}:{}:{}:{}".format(
-              boot_type, boot_device, source_boot.size, source_boot.sha1))
+      target_expr = 'concat("{}:",{},":{}:{}")'.format(
+          boot_type, boot_device_expr, target_boot.size, target_boot.sha1)
+      source_expr = 'concat("{}:",{},":{}:{}")'.format(
+          boot_type, boot_device_expr, source_boot.size, source_boot.sha1)
+      script.PatchPartitionExprCheck(target_expr, source_expr)
 
       required_cache_sizes.append(target_boot.size)
 
@@ -1542,12 +1551,11 @@
         logger.info("boot image changed; including patch.")
         script.Print("Patching boot image...")
         script.ShowProgress(0.1, 10)
-        script.PatchPartition(
-            '{}:{}:{}:{}'.format(
-                boot_type, boot_device, target_boot.size, target_boot.sha1),
-            '{}:{}:{}:{}'.format(
-                boot_type, boot_device, source_boot.size, source_boot.sha1),
-            'boot.img.p')
+        target_expr = 'concat("{}:",{},":{}:{}")'.format(
+            boot_type, boot_device_expr, target_boot.size, target_boot.sha1)
+        source_expr = 'concat("{}:",{},":{}:{}")'.format(
+            boot_type, boot_device_expr, source_boot.size, source_boot.sha1)
+        script.PatchPartitionExpr(target_expr, source_expr, '"boot.img.p"')
     else:
       logger.info("boot image unchanged; skipping.")
 
@@ -2067,6 +2075,8 @@
       OPTIONS.output_metadata_path = a
     elif o == "--disable_fec_computation":
       OPTIONS.disable_fec_computation = True
+    elif o == "--force_non_ab":
+      OPTIONS.force_non_ab = True
     else:
       return False
     return True
@@ -2103,6 +2113,7 @@
                                  "skip_compatibility_check",
                                  "output_metadata_path=",
                                  "disable_fec_computation",
+                                 "force_non_ab",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
@@ -2164,11 +2175,17 @@
     OPTIONS.skip_postinstall = True
 
   ab_update = OPTIONS.info_dict.get("ab_update") == "true"
+  allow_non_ab = OPTIONS.info_dict.get("allow_non_ab") == "true"
+  if OPTIONS.force_non_ab:
+    assert allow_non_ab, "--force_non_ab only allowed on devices that supports non-A/B"
+    assert ab_update, "--force_non_ab only allowed on A/B devices"
+
+  generate_ab = not OPTIONS.force_non_ab and ab_update
 
   # Use the default key to sign the package if not specified with package_key.
   # package_keys are needed on ab_updates, so always define them if an
-  # ab_update is getting created.
-  if not OPTIONS.no_signing or ab_update:
+  # A/B update is getting created.
+  if not OPTIONS.no_signing or generate_ab:
     if OPTIONS.package_key is None:
       OPTIONS.package_key = OPTIONS.info_dict.get(
           "default_system_dev_certificate",
@@ -2176,7 +2193,7 @@
     # Get signing keys
     OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
 
-  if ab_update:
+  if generate_ab:
     GenerateAbOtaPackage(
         target_file=args[0],
         output_file=args[1],