Merge "Fix dynamic partition size check for devices with recovery"
diff --git a/Changes.md b/Changes.md
index e356109..35b8944 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,15 @@
 # Build System Changes for Android.mk Writers
 
+## `*.c.arm` / `*.cpp.arm` deprecation  {#file_arm}
+
+In Android.mk files, you used to be able to change LOCAL_ARM_MODE for each
+source file by appending `.arm` to the end of the filename in
+`LOCAL_SRC_FILES`.
+
+Soong does not support this uncommonly used behavior, instead expecting those
+files to be split out into a separate static library that chooses `arm` over
+`thumb` for the entire library. This must now also be done in Android.mk files.
+
 ## Windows cross-compiles no longer supported in Android.mk
 
 Modules that build for Windows (our only `HOST_CROSS` OS currently) must now be
diff --git a/core/Makefile b/core/Makefile
index 71b9046..fa43918 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -181,10 +181,24 @@
 FINAL_VENDOR_DEFAULT_PROPERTIES += \
     $(call collapse-pairs, $(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
 
+# Add cpu properties for bionic and ART.
 FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH)
-FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT)
+FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME)
 FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_arch=$(TARGET_2ND_ARCH)
-FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT)
+FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT_RUNTIME)
+
+FINAL_VENDOR_DEFAULT_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so
+FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT_RUNTIME)
+ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
+  FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
+endif
+
+ifdef TARGET_2ND_ARCH
+  FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME)
+  ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
+    FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
+  endif
+endif
 
 # Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger
 # mode (via libminui).
@@ -690,8 +704,10 @@
 
 ifneq (,$(TARGET_BUILD_APPS))
   $(call dist-for-goals, apps_only, $(APKCERTS_FILE):apkcerts.txt)
+  $(call dist-for-goals, apps_only, $(SOONG_APEX_KEYS_FILE):apexkeys.txt)
 endif
 
+
 # -----------------------------------------------------------------
 # build system stats
 BUILD_SYSTEM_STATS := $(PRODUCT_OUT)/build_system_stats.txt
@@ -3428,6 +3444,8 @@
   $(HOST_OUT_EXECUTABLES)/lib/shflags/shflags \
   $(HOST_OUT_EXECUTABLES)/delta_generator \
   $(HOST_OUT_EXECUTABLES)/care_map_generator \
+  $(HOST_OUT_EXECUTABLES)/fc_sort \
+  $(HOST_OUT_EXECUTABLES)/sefcontext_compile \
   $(LPMAKE) \
   $(AVBTOOL) \
   $(BLK_ALLOC_TO_BASE_FS) \
@@ -3663,6 +3681,7 @@
 	    $(LPMAKE) \
 	    $(SELINUX_FC) \
 	    $(APKCERTS_FILE) \
+	    $(SOONG_APEX_KEYS_FILE) \
 	    $(SOONG_ZIP) \
 	    $(HOST_OUT_EXECUTABLES)/fs_config \
 	    $(HOST_OUT_EXECUTABLES)/imgdiff \
@@ -3796,6 +3815,7 @@
 	@# build them.
 	$(hide) mkdir -p $(zip_root)/META
 	$(hide) cp $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
+	$(hide) cp $(SOONG_APEX_KEYS_FILE) $(zip_root)/META/apexkeys.txt
 ifneq ($(tool_extension),)
 	$(hide) cp $(PRIVATE_TOOL_EXTENSION) $(zip_root)/META/
 endif
@@ -4078,6 +4098,8 @@
 
 INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
 
+INTERNAL_OTA_METADATA := $(PRODUCT_OUT)/ota_metadata
+
 $(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
 
 ifeq ($(AB_OTA_UPDATER),true)
@@ -4086,10 +4108,12 @@
 $(INTERNAL_OTA_PACKAGE_TARGET): $(BROTLI)
 endif
 
+$(INTERNAL_OTA_PACKAGE_TARGET): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_OTA_METADATA)
+
 $(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) \
 	    build/make/tools/releasetools/ota_from_target_files
 	@echo "Package OTA: $@"
-	$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR))
+	$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --output_metadata_path $(INTERNAL_OTA_METADATA))
 
 .PHONY: otapackage
 otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)
@@ -4600,9 +4624,3 @@
 ifneq ($(sdk_repo_goal),)
 include $(TOPDIR)development/build/tools/sdk_repo.mk
 endif
-
-#------------------------------------------------------------------
-# Find lsdump paths
-FIND_LSDUMPS_FILE := $(PRODUCT_OUT)/lsdump_paths.txt
-$(FIND_LSDUMPS_FILE) : $(LSDUMP_PATHS)
-	$(hide) rm -rf $@ && echo "$^" | sed -e 's/ /\n/g' > $@
diff --git a/core/android_vts_host_config.mk b/core/android_vts_host_config.mk
new file mode 100644
index 0000000..38ba19d
--- /dev/null
+++ b/core/android_vts_host_config.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_MODULE_CLASS := FAKE
+LOCAL_IS_HOST_MODULE := true
+LOCAL_COMPATIBILITY_SUITE := vts
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE):
+	@echo "VTS host-driven test target: $(PRIVATE_MODULE)"
+	$(hide) touch $@
+
diff --git a/core/binary.mk b/core/binary.mk
index ccf5580..ad3d76b 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -440,9 +440,6 @@
 ifneq ($(foreach i,$(my_c_includes),$(filter %/..,$(i))$(findstring /../,$(i))),)
 my_soong_problems += dotdot_incs
 endif
-ifneq ($(filter %.arm,$(my_src_files)),)
-my_soong_problems += srcs_dotarm
-endif
 
 ####################################################
 ## Add FDO flags if FDO is turned on and supported
@@ -506,19 +503,15 @@
 ###########################################################
 LOCAL_ARM_MODE := $(strip $(LOCAL_ARM_MODE))
 ifeq ($($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH),arm)
-arm_objects_mode := $(if $(LOCAL_ARM_MODE),$(LOCAL_ARM_MODE),arm)
 normal_objects_mode := $(if $(LOCAL_ARM_MODE),$(LOCAL_ARM_MODE),thumb)
 
 # Read the values from something like TARGET_arm_CFLAGS or
 # TARGET_thumb_CFLAGS.  HOST_(arm|thumb)_CFLAGS values aren't
 # actually used (although they are usually empty).
-arm_objects_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)$(arm_objects_mode)_CFLAGS)
 normal_objects_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)$(normal_objects_mode)_CFLAGS)
 
 else
-arm_objects_mode :=
 normal_objects_mode :=
-arm_objects_cflags :=
 normal_objects_cflags :=
 endif
 
@@ -657,7 +650,7 @@
 proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
 
 my_rename_cpp_ext :=
-ifneq (,$(filter nanopb-c nanopb-c-enable_malloc, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
+ifneq (,$(filter nanopb-c nanopb-c-enable_malloc nanopb-c-16bit nanopb-c-enable_malloc-16bit nanopb-c-32bit nanopb-c-enable_malloc-32bit, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
 my_proto_source_suffix := .c
 my_proto_c_includes := external/nanopb-c
 my_protoc_flags := --nanopb_out=$(proto_gen_dir) \
@@ -712,6 +705,14 @@
     my_static_libraries += libprotobuf-c-nano-enable_malloc
 else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c)
     my_static_libraries += libprotobuf-c-nano
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-enable_malloc-16bit)
+    my_static_libraries += libprotobuf-c-nano-enable_malloc-16bit
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-16bit)
+    my_static_libraries += libprotobuf-c-nano-16bit
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-enable_malloc-32bit)
+    my_static_libraries += libprotobuf-c-nano-enable_malloc-32bit
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-32bit)
+    my_static_libraries += libprotobuf-c-nano-32bit
 else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),full)
     ifdef LOCAL_SDK_VERSION
         my_static_libraries += libprotobuf-cpp-full-ndk
@@ -853,22 +854,9 @@
 ## C++: Compile .cpp files to .o.
 ###########################################################
 
-# we also do this on host modules, even though
-# it's not really arm, because there are files that are shared.
-cpp_arm_sources := $(patsubst %$(LOCAL_CPP_EXTENSION).arm,%$(LOCAL_CPP_EXTENSION),$(filter %$(LOCAL_CPP_EXTENSION).arm,$(my_src_files)))
-dotdot_arm_sources := $(filter ../%,$(cpp_arm_sources))
-cpp_arm_sources := $(filter-out ../%,$(cpp_arm_sources))
-cpp_arm_objects := $(addprefix $(intermediates)/,$(cpp_arm_sources:$(LOCAL_CPP_EXTENSION)=.o))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(cpp_arm_sources)),$(cpp_arm_objects))
-
-# For source files starting with ../, we remove all the ../ in the object file path,
-# to avoid object file escaping the intermediate directory.
-dotdot_arm_objects :=
-$(foreach s,$(dotdot_arm_sources),\
-  $(eval $(call compile-dotdot-cpp-file,$(s),\
-  $(my_additional_dependencies),\
-  dotdot_arm_objects)))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
+ifneq ($(filter %$(LOCAL_CPP_EXTENSION).arm,$(my_src_files)),)
+$(call pretty-error,Files ending in $(LOCAL_CPP_EXTENSION).arm are deprecated. See $(CHANGES_URL)#file_arm)
+endif
 
 dotdot_sources := $(filter ../%$(LOCAL_CPP_EXTENSION),$(my_src_files))
 dotdot_objects :=
@@ -879,15 +867,11 @@
 $(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
 
 cpp_normal_sources := $(filter-out ../%,$(filter %$(LOCAL_CPP_EXTENSION),$(my_src_files)))
-cpp_normal_objects := $(addprefix $(intermediates)/,$(cpp_normal_sources:$(LOCAL_CPP_EXTENSION)=.o))
-$(call track-src-file-obj,$(cpp_normal_sources),$(cpp_normal_objects))
+cpp_objects := $(addprefix $(intermediates)/,$(cpp_normal_sources:$(LOCAL_CPP_EXTENSION)=.o))
+$(call track-src-file-obj,$(cpp_normal_sources),$(cpp_objects))
 
-$(dotdot_arm_objects) $(cpp_arm_objects): PRIVATE_ARM_MODE := $(arm_objects_mode)
-$(dotdot_arm_objects) $(cpp_arm_objects): PRIVATE_ARM_CFLAGS := $(arm_objects_cflags)
-$(dotdot_objects) $(cpp_normal_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
-$(dotdot_objects) $(cpp_normal_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-
-cpp_objects        := $(cpp_arm_objects) $(cpp_normal_objects)
+$(dotdot_objects) $(cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
+$(dotdot_objects) $(cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 
 ifneq ($(strip $(cpp_objects)),)
 $(cpp_objects): $(intermediates)/%.o: \
@@ -897,7 +881,7 @@
 $(call include-depfiles-for-objs, $(cpp_objects))
 endif
 
-cpp_objects += $(dotdot_arm_objects) $(dotdot_objects)
+cpp_objects += $(dotdot_objects)
 
 ###########################################################
 ## C++: Compile generated .cpp files to .o.
@@ -909,7 +893,6 @@
 
 ifneq ($(strip $(gen_cpp_objects)),)
 # Compile all generated files as thumb.
-# TODO: support compiling certain generated files as arm.
 $(gen_cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(gen_cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(gen_cpp_objects): $(intermediates)/%.o: \
@@ -957,20 +940,9 @@
 ## C: Compile .c files to .o.
 ###########################################################
 
-c_arm_sources := $(patsubst %.c.arm,%.c,$(filter %.c.arm,$(my_src_files)))
-dotdot_arm_sources := $(filter ../%,$(c_arm_sources))
-c_arm_sources := $(filter-out ../%,$(c_arm_sources))
-c_arm_objects := $(addprefix $(intermediates)/,$(c_arm_sources:.c=.o))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(c_arm_sources)),$(c_arm_objects))
-
-# For source files starting with ../, we remove all the ../ in the object file path,
-# to avoid object file escaping the intermediate directory.
-dotdot_arm_objects :=
-$(foreach s,$(dotdot_arm_sources),\
-  $(eval $(call compile-dotdot-c-file,$(s),\
-    $(my_additional_dependencies),\
-    dotdot_arm_objects)))
-$(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
+ifneq ($(filter %.c.arm,$(my_src_files)),)
+$(call pretty-error,Files ending in .c.arm are deprecated. See $(CHANGES_URL)#file_arm)
+endif
 
 dotdot_sources := $(filter ../%.c, $(my_src_files))
 dotdot_objects :=
@@ -981,15 +953,11 @@
 $(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
 
 c_normal_sources := $(filter-out ../%,$(filter %.c,$(my_src_files)))
-c_normal_objects := $(addprefix $(intermediates)/,$(c_normal_sources:.c=.o))
-$(call track-src-file-obj,$(c_normal_sources),$(c_normal_objects))
+c_objects := $(addprefix $(intermediates)/,$(c_normal_sources:.c=.o))
+$(call track-src-file-obj,$(c_normal_sources),$(c_objects))
 
-$(dotdot_arm_objects) $(c_arm_objects): PRIVATE_ARM_MODE := $(arm_objects_mode)
-$(dotdot_arm_objects) $(c_arm_objects): PRIVATE_ARM_CFLAGS := $(arm_objects_cflags)
-$(dotdot_objects) $(c_normal_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
-$(dotdot_objects) $(c_normal_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-
-c_objects        := $(c_arm_objects) $(c_normal_objects)
+$(dotdot_objects) $(c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
+$(dotdot_objects) $(c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 
 ifneq ($(strip $(c_objects)),)
 $(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c \
@@ -998,7 +966,7 @@
 $(call include-depfiles-for-objs, $(c_objects))
 endif
 
-c_objects += $(dotdot_arm_objects) $(dotdot_objects)
+c_objects += $(dotdot_objects)
 
 ###########################################################
 ## C: Compile generated .c files to .o.
@@ -1010,7 +978,6 @@
 
 ifneq ($(strip $(gen_c_objects)),)
 # Compile all generated files as thumb.
-# TODO: support compiling certain generated files as arm.
 $(gen_c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(gen_c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c \
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index c20dbef..1e3f6ae 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -222,7 +222,7 @@
 LOCAL_PROGUARD_FLAGS:=
 LOCAL_PROPRIETARY_MODULE:=
 LOCAL_PROTOC_FLAGS:=
-# lite(default),micro,nano,stream,full,nanopb-c,nanopb-c-enable_malloc
+# lite(default),micro,nano,stream,full,nanopb-c,nanopb-c-enable_malloc,nanopb-c-16bit,nanopb-c-enable_malloc-16bit,nanopb-c-32bit,nanopb-c-enable_malloc-32bit
 LOCAL_PROTOC_OPTIMIZE_TYPE:=
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS:=
 LOCAL_R8_FLAG_FILES:=
diff --git a/core/config.mk b/core/config.mk
index 518e138..5f08f2f 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -298,12 +298,24 @@
 $(call validate-kernel-headers,$(TARGET_PRODUCT_KERNEL_HEADERS))
 
 # Clean up/verify variables defined by the board config file.
+# TODO: Move this to right after the BoardConfig parsing.
 TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))
 TARGET_CPU_ABI := $(strip $(TARGET_CPU_ABI))
 ifeq ($(TARGET_CPU_ABI),)
   $(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
 endif
 TARGET_CPU_ABI2 := $(strip $(TARGET_CPU_ABI2))
+TARGET_CPU_VARIANT := $(strip $(TARGET_CPU_VARIANT))
+TARGET_CPU_VARIANT_RUNTIME := $(strip $(TARGET_CPU_VARIANT_RUNTIME))
+
+TARGET_2ND_CPU_ABI := $(strip $(TARGET_2ND_CPU_ABI))
+TARGET_2ND_CPU_ABI2 := $(strip $(TARGET_2ND_CPU_ABI2))
+TARGET_2ND_CPU_VARIANT := $(strip $(TARGET_2ND_CPU_VARIANT))
+TARGET_2ND_CPU_VARIANT_RUNTIME := $(strip $(TARGET_2ND_CPU_VARIANT_RUNTIME))
+
+# Default *_CPU_VARIANT_RUNTIME to CPU_VARIANT if unspecified.
+TARGET_CPU_VARIANT_RUNTIME := $(or $(TARGET_CPU_VARIANT_RUNTIME),$(TARGET_CPU_VARIANT))
+TARGET_2ND_CPU_VARIANT_RUNTIME := $(or $(TARGET_2ND_CPU_VARIANT_RUNTIME),$(TARGET_2ND_CPU_VARIANT))
 
 BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
 BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
@@ -1135,11 +1147,13 @@
 first_non_empty_of_three = $(if $(1),$(1),$(if $(2),$(2),$(3)))
 DEX2OAT_TARGET_ARCH := $(TARGET_ARCH)
 DEX2OAT_TARGET_CPU_VARIANT := $(call first_non_empty_of_three,$(TARGET_CPU_VARIANT),$(TARGET_ARCH_VARIANT),default)
+DEX2OAT_TARGET_CPU_VARIANT_RUNTIME := $(call first_non_empty_of_three,$(TARGET_CPU_VARIANT_RUNTIME),$(TARGET_ARCH_VARIANT),default)
 DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES := default
 
 ifdef TARGET_2ND_ARCH
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH := $(TARGET_2ND_ARCH)
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT := $(call first_non_empty_of_three,$(TARGET_2ND_CPU_VARIANT),$(TARGET_2ND_ARCH_VARIANT),default)
+$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME := $(call first_non_empty_of_three,$(TARGET_2ND_CPU_VARIANT_RUNTIME),$(TARGET_2ND_ARCH_VARIANT),default)
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES := default
 endif
 
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 7471c47..d43158e 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -13,36 +13,24 @@
 install-on-system-other = $(filter-out $(PRODUCT_DEXPREOPT_SPEED_APPS) $(PRODUCT_SYSTEM_SERVER_APPS),$(basename $(notdir $(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(1)))))
 endif
 
-# Special rules for building stripped boot jars that override java_library.mk rules
+# Install boot images. Note that there can be multiple.
+DEFAULT_DEX_PREOPT_INSTALLED_IMAGE :=
+$(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE :=
+$(foreach my_boot_image_name,$(DEXPREOPT_IMAGE_NAMES),$(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk))
 
-# $(1): boot jar module name
-define _dexpreopt-boot-jar-remove-classes.dex
-_dbj_jar_no_dex := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(1)_nodex.jar
-_dbj_src_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,$(1),,COMMON)/javalib.jar
+boot_profile_jars_zip := $(PRODUCT_OUT)/boot_profile_jars.zip
+bootclasspath_jars := $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
+system_server_jars := $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(PRODUCT_OUT)/system/framework/$(m).jar)
 
-$(call dexpreopt-copy-jar,$$(_dbj_src_jar),$$(_dbj_jar_no_dex),$(filter-out nostripping,$(DEX_PREOPT_DEFAULT)))
-
-_dbj_jar_no_dex :=
-_dbj_src_jar :=
-endef
-
-$(foreach b,$(DEXPREOPT_BOOT_JARS_MODULES),$(eval $(call _dexpreopt-boot-jar-remove-classes.dex,$(b))))
-
-include $(BUILD_SYSTEM)/dex_preopt_libart.mk
+$(boot_profile_jars_zip): PRIVATE_BOOTCLASSPATH_JARS := $(bootclasspath_jars)
+$(boot_profile_jars_zip): PRIVATE_SYSTEM_SERVER_JARS := $(system_server_jars)
+$(boot_profile_jars_zip): $(bootclasspath_jars) $(system_server_jars) $(SOONG_ZIP)
+	@echo "Create boot profiles package: $@"
+	rm -f $@
+	$(SOONG_ZIP) -o $@ \
+	  -C $(dir $(firstword $(PRIVATE_BOOTCLASSPATH_JARS)))/.. $(addprefix -f ,$(PRIVATE_BOOTCLASSPATH_JARS)) \
+	  -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_SYSTEM_SERVER_JARS))
 
 ifeq ($(PRODUCT_DIST_BOOT_AND_SYSTEM_JARS),true)
-boot_profile_jars_zip := $(PRODUCT_OUT)/boot_profile_jars.zip
-all_boot_jars := \
-  $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES) \
-  $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(PRODUCT_OUT)/system/framework/$(m).jar)
-
-$(boot_profile_jars_zip): PRIVATE_JARS := $(all_boot_jars)
-$(boot_profile_jars_zip): $(all_boot_jars) $(SOONG_ZIP)
-	echo "Create boot profiles package: $@"
-	rm -f $@
-	$(SOONG_ZIP) -o $@ -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_JARS))
-
-droidcore: $(boot_profile_jars_zip)
-
 $(call dist-for-goals, droidcore, $(boot_profile_jars_zip))
 endif
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index e3b720b..9bf2be8 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -47,9 +47,9 @@
 # Default to debug version to help find bugs.
 # Set USE_DEX2OAT_DEBUG to false for only building non-debug versions.
 ifeq ($(USE_DEX2OAT_DEBUG),false)
-DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oat$(HOST_EXECUTABLE_SUFFIX)
+DEX2OAT := $(SOONG_HOST_OUT_EXECUTABLES)/dex2oat$(HOST_EXECUTABLE_SUFFIX)
 else
-DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
+DEX2OAT := $(SOONG_HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
 endif
 
 DEX2OAT_DEPENDENCY += $(DEX2OAT)
@@ -62,25 +62,6 @@
 DIRTY_IMAGE_OBJECTS := $(call word-colon,1,$(firstword \
     $(filter %system/etc/dirty-image-objects,$(PRODUCT_COPY_FILES))))
 
-# If we use a boot image profile.
-my_use_profile_for_boot_image := $(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE)
-ifeq (,$(my_use_profile_for_boot_image))
-  # If not set, set the default to true if we are not a PDK build. PDK builds
-  # can't build the profile since they don't have frameworks/base.
-  ifneq (true,$(TARGET_BUILD_PDK))
-    my_use_profile_for_boot_image := true
-  endif
-endif
-
-ifeq (true,$(my_use_profile_for_boot_image))
-  boot_image_profiles := $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION)
-
-  ifeq (,$(boot_image_profiles))
-  # If not set, use the default.
-  boot_image_profiles := frameworks/base/config/boot-image-profile.txt
-  endif
-endif
-
 define get-product-default-property
 $(strip \
   $(eval _prop := $(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))))\
@@ -107,15 +88,18 @@
   $(call json_start)
 
   $(call add_json_bool, DefaultNoStripping,                 $(filter nostripping,$(DEX_PREOPT_DEFAULT)))
+  $(call add_json_bool, DisablePreopt,                      $(call invert_bool,$(filter true,$(WITH_DEXPREOPT))))
   $(call add_json_list, DisablePreoptModules,               $(DEXPREOPT_DISABLED_MODULES))
   $(call add_json_bool, OnlyPreoptBootImageAndSystemServer, $(filter true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY)))
+  $(call add_json_bool, GenerateApexImage,                  $(filter true,$(DEXPREOPT_GENERATE_APEX_IMAGE)))
   $(call add_json_bool, DontUncompressPrivAppsDex,          $(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS)))
   $(call add_json_list, ModulesLoadedByPrivilegedModules,   $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
   $(call add_json_bool, HasSystemOther,                     $(BOARD_USES_SYSTEM_OTHER_ODEX))
   $(call add_json_list, PatternsOnSystemOther,              $(SYSTEM_OTHER_ODEX_FILTER))
   $(call add_json_bool, DisableGenerateProfile,             $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE)))
+  $(call add_json_str,  ProfileDir,                         $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
   $(call add_json_list, BootJars,                           $(PRODUCT_BOOT_JARS))
-  $(call add_json_list, TargetCoreJars,                     $(TARGET_CORE_JARS))
+  $(call add_json_list, RuntimeApexJars,                    $(RUNTIME_APEX_JARS))
   $(call add_json_list, ProductUpdatableBootModules,        $(PRODUCT_UPDATABLE_BOOT_MODULES))
   $(call add_json_list, ProductUpdatableBootLocations,      $(PRODUCT_UPDATABLE_BOOT_LOCATIONS))
   $(call add_json_list, SystemServerJars,                   $(PRODUCT_SYSTEM_SERVER_JARS))
@@ -155,15 +139,16 @@
 
   $(call add_json_str,  DirtyImageObjects,                  $(DIRTY_IMAGE_OBJECTS))
   $(call add_json_str,  PreloadedClasses,                   $(PRELOADED_CLASSES))
-  $(call add_json_list, BootImageProfiles,                  $(boot_image_profiles))
+  $(call add_json_list, BootImageProfiles,                  $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
+  $(call add_json_bool, UseProfileForBootImage,             $(call invert_bool,$(filter false,$(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))))
   $(call add_json_str,  BootFlags,                          $(PRODUCT_DEX_PREOPT_BOOT_FLAGS))
   $(call add_json_str,  Dex2oatImageXmx,                    $(DEX2OAT_IMAGE_XMX))
   $(call add_json_str,  Dex2oatImageXms,                    $(DEX2OAT_IMAGE_XMS))
 
   $(call add_json_map,  Tools)
-  $(call add_json_str,  Profman,                            $(PROFMAN))
+  $(call add_json_str,  Profman,                            $(SOONG_HOST_OUT_EXECUTABLES)/profman)
   $(call add_json_str,  Dex2oat,                            $(DEX2OAT))
-  $(call add_json_str,  Aapt,                               $(AAPT))
+  $(call add_json_str,  Aapt,                               $(SOONG_HOST_OUT_EXECUTABLES)/aapt)
   $(call add_json_str,  SoongZip,                           $(SOONG_ZIP))
   $(call add_json_str,  Zip2zip,                            $(ZIP2ZIP))
   $(call add_json_str,  VerifyUsesLibraries,                $(BUILD_SYSTEM)/verify_uses_libraries.sh)
@@ -190,9 +175,9 @@
 	@#empty
 
 DEXPREOPT_GEN_DEPS := \
-  $(PROFMAN) \
+  $(SOONG_HOST_OUT_EXECUTABLES)/profman \
   $(DEX2OAT) \
-  $(AAPT) \
+  $(SOONG_HOST_OUT_EXECUTABLES)/aapt \
   $(SOONG_ZIP) \
   $(ZIP2ZIP) \
   $(BUILD_SYSTEM)/verify_uses_libraries.sh \
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 2bfe881..edd82df 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -1,5 +1,7 @@
 ####################################
-# dexpreopt support for ART
+# ART boot image installation
+# Input variable:
+#   my_boot_image_name: the boot image to install
 #
 ####################################
 
@@ -10,7 +12,7 @@
 
 # Install primary arch vdex files into a shared location, and then symlink them to both the primary
 # and secondary arch directories.
-my_vdex_copy_pairs := $(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(TARGET_ARCH))
+my_vdex_copy_pairs := $(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_ARCH))
 my_installed := $(foreach v,$(my_vdex_copy_pairs),$(PRODUCT_OUT)$(call word-colon,2,$(v)))
 $(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed))
 
diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk
index ec9aad7..34b8526 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -1,19 +1,21 @@
-# Rules to install boot.art built by dexpreopt_bootjars.go
+# Rules to install a boot image built by dexpreopt_bootjars.go
 # Input variables:
+#   my_boot_image_name: the boot image to install
 #   my_2nd_arch_prefix: indicates if this is to build for the 2nd arch.
 #   my_dexpreopt_image_extra_deps: extra dependencies to add on the installed boot.art
 
 # Install the boot images compiled by Soong
 # The first file (generally boot.art) is saved as DEFAULT_DEX_PREOPT_INSTALLED_IMAGE,
 # and the rest are added as dependencies of the first.
-my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(PRODUCT_OUT))
+
+my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(PRODUCT_OUT))
 $(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed))
-$(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE := $(firstword $(my_installed))
+$(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE += $(firstword $(my_installed))
 
 # Install the unstripped boot images compiled by Soong into the symbols directory
 # The first file (generally boot.art) made a dependency of DEFAULT_DEX_PREOPT_INSTALLED_IMAGE,
 # and the rest are added as dependencies of the first.
-my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(TARGET_OUT_UNSTRIPPED))
+my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(TARGET_OUT_UNSTRIPPED))
 $(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed))
 $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(firstword $(my_installed))
 
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 0beead9..3d02cdc 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -150,13 +150,13 @@
     # #################################################
     # Odex for the 1st arch
     my_dexpreopt_archs += $(TARGET_ARCH)
-    my_dexpreopt_images += $(DEXPREOPT_IMAGE_$(TARGET_ARCH))
+    my_dexpreopt_images += $(DEXPREOPT_IMAGE_boot_$(TARGET_ARCH))
     # Odex for the 2nd arch
     ifdef TARGET_2ND_ARCH
       ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
         ifneq (first,$(my_module_multilib))
           my_dexpreopt_archs += $(TARGET_2ND_ARCH)
-          my_dexpreopt_images += $(DEXPREOPT_IMAGE_$(TARGET_2ND_ARCH))
+          my_dexpreopt_images += $(DEXPREOPT_IMAGE_boot_$(TARGET_2ND_ARCH))
         endif  # my_module_multilib is not first.
       endif  # TARGET_TRANSLATE_2ND_ARCH not true
     endif  # TARGET_2ND_ARCH
@@ -166,13 +166,13 @@
     # Save the module multilib since setup_one_odex modifies it.
     my_2nd_arch_prefix := $(LOCAL_2ND_ARCH_VAR_PREFIX)
     my_dexpreopt_archs += $(TARGET_$(my_2nd_arch_prefix)ARCH)
-    my_dexpreopt_images += $(DEXPREOPT_IMAGE_$(TARGET_$(my_2nd_arch_prefix)ARCH))
+    my_dexpreopt_images += $(DEXPREOPT_IMAGE_boot_$(TARGET_$(my_2nd_arch_prefix)ARCH))
     ifdef TARGET_2ND_ARCH
       ifeq ($(my_module_multilib),both)
         # The non-preferred arch
         my_2nd_arch_prefix := $(if $(LOCAL_2ND_ARCH_VAR_PREFIX),,$(TARGET_2ND_ARCH_VAR_PREFIX))
         my_dexpreopt_archs += $(TARGET_$(my_2nd_arch_prefix)ARCH)
-        my_dexpreopt_images += $(DEXPREOPT_IMAGE_$(TARGET_$(my_2nd_arch_prefix)ARCH))
+        my_dexpreopt_images += $(DEXPREOPT_IMAGE_boot_$(TARGET_$(my_2nd_arch_prefix)ARCH))
       endif  # LOCAL_MULTILIB is both
     endif  # TARGET_2ND_ARCH
   endif  # LOCAL_MODULE_CLASS
@@ -190,10 +190,12 @@
 
   $(call json_start)
 
+  # DexPath, StripInputPath, and StripOutputPath are not set, they will
+  # be filled in by dexpreopt_gen.
+
   $(call add_json_str,  Name,                           $(LOCAL_MODULE))
   $(call add_json_str,  DexLocation,                    $(patsubst $(PRODUCT_OUT)%,%,$(LOCAL_INSTALLED_MODULE)))
   $(call add_json_str,  BuildPath,                      $(LOCAL_BUILT_MODULE))
-  $(call add_json_str,  DexPath,                        $$1)
   $(call add_json_str,  ExtrasOutputPath,               $$2)
   $(call add_json_bool, Privileged,                     $(filter true,$(LOCAL_PRIVILEGED_MODULE)))
   $(call add_json_bool, UncompressedDex,                $(filter true,$(LOCAL_UNCOMPRESS_DEX)))
@@ -218,8 +220,6 @@
   $(call add_json_bool, PresignedPrebuilt,              $(filter PRESIGNED,$(LOCAL_CERTIFICATE)))
 
   $(call add_json_bool, NoStripping,                    $(filter nostripping,$(LOCAL_DEX_PREOPT)))
-  $(call add_json_str,  StripInputPath,                 $$1)
-  $(call add_json_str,  StripOutputPath,                $$2)
 
   $(call json_end)
 
@@ -244,7 +244,8 @@
   $(my_dexpreopt_script): $(my_dexpreopt_config) $(PRODUCT_OUT)/dexpreopt.config
 	@echo "$(PRIVATE_MODULE) dexpreopt gen"
 	$(DEXPREOPT_GEN) -global $(PRIVATE_GLOBAL_CONFIG) -module $(PRIVATE_MODULE_CONFIG) \
-	-dexpreopt_script $@ -strip_script $(PRIVATE_STRIP_SCRIPT)
+	-dexpreopt_script $@ -strip_script $(PRIVATE_STRIP_SCRIPT) \
+	-out_dir $(OUT_DIR)
 
   my_dexpreopt_deps := $(my_dex_jar)
   my_dexpreopt_deps += $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE))
diff --git a/core/envsetup.mk b/core/envsetup.mk
index e62636e..cc427ca 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -206,7 +206,10 @@
 #################################################################
 # Set up minimal BOOTCLASSPATH list of jars to build/execute
 # java code with dalvikvm/art.
-TARGET_CORE_JARS := core-oj core-libart conscrypt okhttp bouncycastle apache-xml
+# Jars present in the runtime apex. These should match exactly the list of
+# Java libraries in the runtime apex build rule.
+RUNTIME_APEX_JARS := core-oj core-libart okhttp bouncycastle apache-xml
+TARGET_CORE_JARS := $(RUNTIME_APEX_JARS) conscrypt
 ifeq ($(EMMA_INSTRUMENT),true)
   ifneq ($(EMMA_INSTRUMENT_STATIC),true)
     # For instrumented build, if Jacoco is not being included statically
diff --git a/core/main.mk b/core/main.mk
index 610ab28..b63fd61 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -252,6 +252,11 @@
 ADDITIONAL_PRODUCT_PROPERTIES += ro.boot.dynamic_partitions_retrofit=true
 endif
 
+# Add the system server compiler filter if they are specified for the product.
+ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
+ADDITIONAL_PRODUCT_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)
+endif
+
 # -----------------------------------------------------------------
 ###
 ### In this section we set up the things that are different
@@ -264,26 +269,6 @@
 is_sdk_build := true
 endif
 
-# Add build properties for ART. These define system properties used by installd
-# to pass flags to dex2oat.
-ADDITIONAL_BUILD_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so
-ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT)
-ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
-  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
-endif
-
-ifdef TARGET_2ND_ARCH
-  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT)
-  ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),)
-    ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
-  endif
-endif
-
-# Add the system server compiler filter if they are specified for the product.
-ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
-ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)
-endif
-
 ## user/userdebug ##
 
 user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
@@ -1454,6 +1439,7 @@
   $(call dist-for-goals, droidcore, \
     $(INTERNAL_UPDATE_PACKAGE_TARGET) \
     $(INTERNAL_OTA_PACKAGE_TARGET) \
+    $(INTERNAL_OTA_METADATA) \
     $(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET) \
     $(BUILT_OTATOOLS_PACKAGE) \
     $(SYMBOLS_ZIP) \
@@ -1581,8 +1567,15 @@
 .PHONY: findbugs
 findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET)
 
+LSDUMP_PATHS_FILE := $(PRODUCT_OUT)/lsdump_paths.txt
+
 .PHONY: findlsdumps
-findlsdumps: $(FIND_LSDUMPS_FILE)
+findlsdumps: $(LSDUMP_PATHS_FILE) $(LSDUMP_PATHS)
+
+$(LSDUMP_PATHS_FILE): PRIVATE_LSDUMP_PATHS := $(LSDUMP_PATHS)
+$(LSDUMP_PATHS_FILE):
+	@echo "Generate $@"
+	@rm -rf $@ && echo "$(PRIVATE_LSDUMP_PATHS)" | sed -e 's/ /\n/g' > $@
 
 .PHONY: check-elf-files
 check-elf-files:
diff --git a/core/pdk_config.mk b/core/pdk_config.mk
index 383c11a..ce78ece 100644
--- a/core/pdk_config.mk
+++ b/core/pdk_config.mk
@@ -20,8 +20,6 @@
   target/common/obj/JAVA_LIBRARIES/conscrypt_intermediates \
   target/common/obj/JAVA_LIBRARIES/core-oj_intermediates \
   target/common/obj/JAVA_LIBRARIES/core-libart_intermediates \
-  target/common/obj/JAVA_LIBRARIES/legacy-test_intermediates \
-  target/common/obj/JAVA_LIBRARIES/legacy-android-test_intermediates \
   target/common/obj/JAVA_LIBRARIES/ext_intermediates \
   target/common/obj/JAVA_LIBRARIES/framework_intermediates \
   target/common/obj/JAVA_LIBRARIES/hwbinder_intermediates \
diff --git a/core/product.mk b/core/product.mk
index 2ddbeaf..efe029b 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -368,69 +368,75 @@
 
 
 _product_stash_var_list := $(_product_var_list) \
-	PRODUCT_BOOTCLASSPATH \
-	PRODUCT_SYSTEM_SERVER_CLASSPATH \
-	TARGET_ARCH \
-	TARGET_ARCH_VARIANT \
-	TARGET_CPU_VARIANT \
-	TARGET_BOARD_PLATFORM \
-	TARGET_BOARD_PLATFORM_GPU \
-	TARGET_BOARD_KERNEL_HEADERS \
-	TARGET_DEVICE_KERNEL_HEADERS \
-	TARGET_PRODUCT_KERNEL_HEADERS \
-	TARGET_BOOTLOADER_BOARD_NAME \
-	TARGET_NO_BOOTLOADER \
-	TARGET_NO_KERNEL \
-	TARGET_NO_RECOVERY \
-	TARGET_NO_RADIOIMAGE \
-	TARGET_HARDWARE_3D \
-	TARGET_CPU_ABI \
-	TARGET_CPU_ABI2 \
+  PRODUCT_BOOTCLASSPATH \
+  PRODUCT_SYSTEM_SERVER_CLASSPATH \
+  TARGET_ARCH \
+  TARGET_ARCH_VARIANT \
+  TARGET_CPU_ABI \
+  TARGET_CPU_ABI2 \
+  TARGET_CPU_VARIANT \
+  TARGET_CPU_VARIANT_RUNTIME \
+  TARGET_2ND_ARCH \
+  TARGET_2ND_ARCH_VARIANT \
+  TARGET_2ND_CPU_ABI \
+  TARGET_2ND_CPU_ABI2 \
+  TARGET_2ND_CPU_VARIANT \
+  TARGET_2ND_CPU_VARIANT_RUNTIME \
+  TARGET_BOARD_PLATFORM \
+  TARGET_BOARD_PLATFORM_GPU \
+  TARGET_BOARD_KERNEL_HEADERS \
+  TARGET_DEVICE_KERNEL_HEADERS \
+  TARGET_PRODUCT_KERNEL_HEADERS \
+  TARGET_BOOTLOADER_BOARD_NAME \
+  TARGET_NO_BOOTLOADER \
+  TARGET_NO_KERNEL \
+  TARGET_NO_RECOVERY \
+  TARGET_NO_RADIOIMAGE \
+  TARGET_HARDWARE_3D \
+
+_product_stash_var_list += \
+  BOARD_WPA_SUPPLICANT_DRIVER \
+  BOARD_WLAN_DEVICE \
+  BOARD_USES_GENERIC_AUDIO \
+  BOARD_KERNEL_CMDLINE \
+  BOARD_KERNEL_BASE \
+  BOARD_HAVE_BLUETOOTH \
+  BOARD_VENDOR_USE_AKMD \
+  BOARD_EGL_CFG \
+  BOARD_BOOTIMAGE_PARTITION_SIZE \
+  BOARD_RECOVERYIMAGE_PARTITION_SIZE \
+  BOARD_SYSTEMIMAGE_PARTITION_SIZE \
+  BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_USERDATAIMAGE_PARTITION_SIZE \
+  BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_CACHEIMAGE_PARTITION_SIZE \
+  BOARD_FLASH_BLOCK_SIZE \
+  BOARD_VENDORIMAGE_PARTITION_SIZE \
+  BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_PRODUCTIMAGE_PARTITION_SIZE \
+  BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE \
+  BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_ODMIMAGE_PARTITION_SIZE \
+  BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_INSTALLER_CMDLINE \
 
 
 _product_stash_var_list += \
-	BOARD_WPA_SUPPLICANT_DRIVER \
-	BOARD_WLAN_DEVICE \
-	BOARD_USES_GENERIC_AUDIO \
-	BOARD_KERNEL_CMDLINE \
-	BOARD_KERNEL_BASE \
-	BOARD_HAVE_BLUETOOTH \
-	BOARD_VENDOR_USE_AKMD \
-	BOARD_EGL_CFG \
-	BOARD_BOOTIMAGE_PARTITION_SIZE \
-	BOARD_RECOVERYIMAGE_PARTITION_SIZE \
-	BOARD_SYSTEMIMAGE_PARTITION_SIZE \
-	BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_USERDATAIMAGE_PARTITION_SIZE \
-	BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_CACHEIMAGE_PARTITION_SIZE \
-	BOARD_FLASH_BLOCK_SIZE \
-	BOARD_VENDORIMAGE_PARTITION_SIZE \
-	BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_PRODUCTIMAGE_PARTITION_SIZE \
-	BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE \
-	BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_ODMIMAGE_PARTITION_SIZE \
-	BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \
-	BOARD_INSTALLER_CMDLINE \
-
-
-_product_stash_var_list += \
-	DEFAULT_SYSTEM_DEV_CERTIFICATE \
-	WITH_DEXPREOPT \
-	WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
+  DEFAULT_SYSTEM_DEV_CERTIFICATE \
+  WITH_DEXPREOPT \
+  WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
 
 # Logical partitions related variables.
 _dynamic_partitions_var_list += \
-	BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE \
-	BOARD_SUPER_PARTITION_SIZE \
-	BOARD_SUPER_PARTITION_GROUPS \
+  BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_SUPER_PARTITION_SIZE \
+  BOARD_SUPER_PARTITION_GROUPS \
 
 _product_stash_var_list += $(_dynamic_partitions_var_list)
 _product_strip_var_list := $(_dynamic_partitions_var_list)
@@ -440,8 +446,8 @@
 #
 define readonly-product-vars
 $(foreach v,$(_product_stash_var_list), \
-	$(eval $(v) ?=) \
-	$(eval .KATI_READONLY := $(v)) \
+  $(eval $(v) ?=) \
+  $(eval .KATI_READONLY := $(v)) \
  )
 endef
 
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 1fb0c29..3c82e88 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -114,11 +114,6 @@
 $(call add_json_list, ModulesLoadedByPrivilegedModules,  $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
 
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
-$(call add_json_list, PreoptBootJars,                    $(DEXPREOPT_BOOT_JARS_MODULES))
-
-$(call add_json_bool, DisableDexPreopt,                  $(call invert_bool,$(filter true,$(WITH_DEXPREOPT))))
-$(call add_json_list, DisableDexPreoptModules,           $(DEXPREOPT_DISABLED_MODULES))
-$(call add_json_str,  DexPreoptProfileDir,               $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
 
 $(call add_json_bool, Product_is_iot,                    $(filter true,$(PRODUCT_IOT)))
 
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index a3cd3ac..835d9fe 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -252,7 +252,7 @@
     #  It must be of the form "YYYY-MM-DD" on production devices.
     #  It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
     #  If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
-      PLATFORM_SECURITY_PATCH := 2019-01-05
+      PLATFORM_SECURITY_PATCH := 2019-02-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
diff --git a/envsetup.sh b/envsetup.sh
index 0953487..9e381a2 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -267,6 +267,13 @@
         export ANDROID_EMULATOR_PREBUILTS
     fi
 
+    # Append asuite prebuilts path to ANDROID_BUILD_PATHS.
+    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
+    local ACLOUD_PATH="$T/prebuilts/asuite/acloud/$os_arch:"
+    local AIDEGEN_PATH="$T/prebuilts/asuite/aidegen/$os_arch:"
+    local ATEST_PATH="$T/prebuilts/asuite/atest/$os_arch:"
+    export ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS$ACLOUD_PATH$AIDEGEN_PATH$ATEST_PATH
+
     export PATH=$ANDROID_BUILD_PATHS$PATH
 
     # out with the duplicate old
@@ -355,7 +362,7 @@
     local completion_files=(
       system/core/adb/adb.bash
       system/core/fastboot/fastboot.bash
-      tools/tradefederation/core/atest/atest_completion.sh
+      tools/asuite/asuite.sh
     )
     # Completion can be disabled selectively to allow users to use non-standard completion.
     # e.g.
@@ -1689,23 +1696,6 @@
     "$ANDROID_PRODUCT_OUT/provision-device" "$@"
 }
 
-function atest()
-{
-    # Let's use the built version over the prebuilt, then source code.
-    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
-    local built_atest=${ANDROID_HOST_OUT}/bin/atest
-    local prebuilt_atest="$(gettop)"/prebuilts/asuite/atest/$os_arch/atest
-    if [[ -x $built_atest ]]; then
-        $built_atest "$@"
-    elif [[ -x $prebuilt_atest ]]; then
-        $prebuilt_atest "$@"
-    else
-        # TODO: once prebuilt atest released, remove the source code section
-        # and change the location of atest_completion.sh in addcompletions().
-        "$(gettop)"/tools/tradefederation/core/atest/atest.py "$@"
-    fi
-}
-
 # Zsh needs bashcompinit called to support bash-style completion.
 function enable_zsh_completion() {
     # Don't override user's options if bash-style completion is already enabled.
@@ -1730,40 +1720,6 @@
     esac
 }
 
-function acloud()
-{
-    # Let's use the built version over the prebuilt.
-    local built_acloud=${ANDROID_HOST_OUT}/bin/acloud
-    if [ -f $built_acloud ]; then
-        $built_acloud "$@"
-        return $?
-    fi
-
-    local host_os_arch=$(get_build_var HOST_PREBUILT_TAG)
-    case $host_os_arch in
-        linux-x86) "$(gettop)"/prebuilts/asuite/acloud/linux-x86/acloud "$@"
-        ;;
-        darwin-x86) "$(gettop)"/prebuilts/asuite/acloud/darwin-x86/acloud "$@"
-        ;;
-    *)
-        echo "acloud is not supported on your host arch: $host_os_arch"
-        ;;
-    esac
-}
-
-function aidegen()
-{
-    # Always use the prebuilt version.
-    local host_os_arch=$(get_build_var HOST_PREBUILT_TAG)
-    case $host_os_arch in
-        linux-x86) "$(gettop)"/prebuilts/asuite/aidegen/linux-x86/aidegen "$@"
-        ;;
-    *)
-        echo "aidegen is not supported on your host arch: $host_os_arch"
-        ;;
-    esac
-}
-
 # Execute the contents of any vendorsetup.sh files we can find.
 # Unless we find an allowed-vendorsetup_sh-files file, in which case we'll only
 # load those.
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index 1e325b9..3e8d342 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -20,10 +20,10 @@
 # the GLES renderer disables itself if host GL acceleration isn't available.
 USE_OPENGL_RENDERER := true
 
-# ~100 MB vendor image. Please adjust system image / vendor image sizes
+# ~140 MB vendor image. Please adjust system image / vendor image sizes
 # when finalizing them. The partition size needs to be a multiple of image
 # block size: 4096.
-BOARD_VENDORIMAGE_PARTITION_SIZE := 100003840
+BOARD_VENDORIMAGE_PARTITION_SIZE := 140963840
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
 BOARD_FLASH_BLOCK_SIZE := 512
 DEVICE_MATRIX_FILE   := device/generic/goldfish/compatibility_matrix.xml
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 88bc7da..68d29c8 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -34,11 +34,14 @@
 
 # Android Verified Boot (AVB):
 #   Set AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED (--flags 2) in
-#   vbmeta.img to disable AVB verification.
+#   vbmeta.img to disable AVB verification. Also set the rollback index
+#   to zero, to prevent the device bootloader from updating the last seen
+#   rollback index in the tamper-evident storage.
 #
 # To disable AVB for GSI, use the vbmeta.img and the GSI together.
 # To enable AVB for GSI, include the GSI public key into the device-specific
 # vbmeta.img.
+BOARD_AVB_ROLLBACK_INDEX := 0
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 2
 
 # Enable chain partition for system.
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index fe1954e..f8ff22f 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -114,6 +114,7 @@
     libandroidfw \
     libandroid_runtime \
     libandroid_servers \
+    libartpalette-system \
     libashmemd_client \
     libaudioeffect_jni \
     libaudioflinger \
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 8a60f7d..cfa81e1 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -191,7 +191,7 @@
 
 
 def RunAndWait(args, verbose=None, **kwargs):
-  """Runs the given command and returns the exit code.
+  """Runs the given command waiting for it to complete.
 
   Args:
     args: The command represented as a list of strings.
@@ -201,12 +201,16 @@
         stdin, etc. stdout and stderr will default to subprocess.PIPE and
         subprocess.STDOUT respectively unless caller specifies any of them.
 
-  Returns:
-    The process return code.
+  Raises:
+    ExternalError: On non-zero exit from the command.
   """
   proc = Run(args, verbose=verbose, **kwargs)
   proc.wait()
-  return proc.returncode
+
+  if proc.returncode != 0:
+    raise ExternalError(
+        "Failed to run command '{}' (exit code {})".format(
+            args, proc.returncode))
 
 
 def RunAndCheckOutput(args, verbose=None, **kwargs):
@@ -764,30 +768,46 @@
     shutil.copyfileobj(in_file, out_file)
 
 
+def UnzipToDir(filename, dirname, pattern=None):
+  """Unzips the archive to the given directory.
+
+  Args:
+    filename: The name of the zip file to unzip.
+
+    dirname: Where the unziped files will land.
+
+    pattern: Files to unzip from the archive. If omitted, will unzip the entire
+    archvie.
+  """
+
+  cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
+  if pattern is not None:
+    cmd.extend(pattern)
+  RunAndCheckOutput(cmd)
+
+
 def UnzipTemp(filename, pattern=None):
   """Unzips the given archive into a temporary directory and returns the name.
 
-  If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a temp dir,
-  then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
+  Args:
+    filename: If filename is of the form "foo.zip+bar.zip", unzip foo.zip into
+    a temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
+
+    pattern: Files to unzip from the archive. If omitted, will unzip the entire
+    archvie.
 
   Returns:
     The name of the temporary directory.
   """
 
-  def unzip_to_dir(filename, dirname):
-    cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
-    if pattern is not None:
-      cmd.extend(pattern)
-    RunAndCheckOutput(cmd)
-
   tmp = MakeTempDir(prefix="targetfiles-")
   m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)
   if m:
-    unzip_to_dir(m.group(1), tmp)
-    unzip_to_dir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"))
+    UnzipToDir(m.group(1), tmp, pattern)
+    UnzipToDir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"), pattern)
     filename = m.group(1)
   else:
-    unzip_to_dir(filename, tmp)
+    UnzipToDir(filename, tmp, pattern)
 
   return tmp
 
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index b02363c..2645829 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -35,7 +35,6 @@
 
 from __future__ import print_function
 
-import argparse
 import fnmatch
 import logging
 import os
@@ -48,6 +47,10 @@
 logger = logging.getLogger(__name__)
 OPTIONS = common.OPTIONS
 OPTIONS.verbose = True
+OPTIONS.system_target_files = None
+OPTIONS.other_target_files = None
+OPTIONS.output_target_files = None
+OPTIONS.keep_tmp = False
 
 # system_extract_as_is_item_list is a list of items to extract from the partial
 # system target files package as is, meaning these items will land in the
@@ -139,9 +142,6 @@
     will land.
 
     extract_item_list: A list of items to extract.
-
-  Returns:
-    On success, 0. Otherwise, a non-zero exit code from unzip.
   """
 
   logger.info('extracting from %s', target_files)
@@ -163,25 +163,13 @@
     else:
       filtered_extract_item_list.append(pattern)
 
-  # Extract the filtered_extract_item_list from target_files into
-  # target_files_temp_dir.
+  # Extract from target_files into target_files_temp_dir the
+  # filtered_extract_item_list.
 
-  # TODO(b/124464492): Extend common.UnzipTemp() to handle this use case.
-  command = [
-      'unzip',
-      '-n',
-      '-q',
-      '-d', target_files_temp_dir,
-      target_files
-  ] + filtered_extract_item_list
-
-  result = common.RunAndWait(command, verbose=True)
-
-  if result != 0:
-    logger.error('extract_items command %s failed %d', str(command), result)
-    return result
-
-  return 0
+  common.UnzipToDir(
+      target_files,
+      target_files_temp_dir,
+      filtered_extract_item_list)
 
 
 def process_ab_partitions_txt(
@@ -302,9 +290,6 @@
     already contain plat_file_contexts and vendor_file_contexts (in the
     appropriate sub directories), and to which META/file_contexts.bin will be
     written.
-
-  Returns:
-    On success, 0. Otherwise, a non-zero exit code.
   """
 
   # To create a merged file_contexts.bin file, we use the system and vendor
@@ -349,12 +334,7 @@
 
   sorted_file_contexts_txt = os.path.join(temp_dir, 'sorted_file_contexts.txt')
   command = ['fc_sort', merged_file_contexts_txt, sorted_file_contexts_txt]
-
-  # TODO(b/124521133): Refector RunAndWait to raise exception on failure.
-  result = common.RunAndWait(command, verbose=True)
-
-  if result != 0:
-    return result
+  common.RunAndWait(command, verbose=True)
 
   # Finally, the compile step creates the final META/file_contexts.bin.
 
@@ -368,12 +348,7 @@
       sorted_file_contexts_txt,
   ]
 
-  result = common.RunAndWait(command, verbose=True)
-
-  if result != 0:
-    return result
-
-  return 0
+  common.RunAndWait(command, verbose=True)
 
 
 def process_special_cases(
@@ -399,9 +374,6 @@
     output_target_files_temp_dir: The name of a directory that will be used
     to create the output target files package after all the special cases
     are processed.
-
-  Returns:
-    On success, 0. Otherwise, a non-zero exit code.
   """
 
   process_ab_partitions_txt(
@@ -414,15 +386,10 @@
       other_target_files_temp_dir=other_target_files_temp_dir,
       output_target_files_temp_dir=output_target_files_temp_dir)
 
-  result = process_file_contexts_bin(
+  process_file_contexts_bin(
       temp_dir=temp_dir,
       output_target_files_temp_dir=output_target_files_temp_dir)
 
-  if result != 0:
-    return result
-
-  return 0
-
 
 def merge_target_files(
     temp_dir,
@@ -448,9 +415,6 @@
 
     output_target_files: The name of the output zip archive target files
     package created by merging system and other.
-
-  Returns:
-    On success, 0. Otherwise, a non-zero exit code.
   """
 
   # Create directory names that we'll use when we extract files from system,
@@ -464,64 +428,49 @@
   # We extract them directly into the output temporary directory since the
   # items do not need special case processing.
 
-  result = extract_items(
+  extract_items(
       target_files=system_target_files,
       target_files_temp_dir=output_target_files_temp_dir,
       extract_item_list=system_extract_as_is_item_list)
 
-  if result != 0:
-    return result
-
   # Extract "as is" items from the input other partial target files package. We
   # extract them directly into the output temporary directory since the items
   # do not need special case processing.
 
-  result = extract_items(
+  extract_items(
       target_files=other_target_files,
       target_files_temp_dir=output_target_files_temp_dir,
       extract_item_list=other_extract_as_is_item_list)
 
-  if result != 0:
-    return result
-
   # Extract "special" items from the input system partial target files package.
   # We extract these items to different directory since they require special
   # processing before they will end up in the output directory.
 
-  result = extract_items(
+  extract_items(
       target_files=system_target_files,
       target_files_temp_dir=system_target_files_temp_dir,
       extract_item_list=system_extract_special_item_list)
 
-  if result != 0:
-    return result
-
   # Extract "special" items from the input other partial target files package.
   # We extract these items to different directory since they require special
   # processing before they will end up in the output directory.
 
-  result = extract_items(
+  extract_items(
       target_files=other_target_files,
       target_files_temp_dir=other_target_files_temp_dir,
       extract_item_list=other_extract_special_item_list)
 
-  if result != 0:
-    return result
-
   # Now that the temporary directories contain all the extracted files, perform
   # special case processing on any items that need it. After this function
   # completes successfully, all the files we need to create the output target
   # files package are in place.
 
-  result = process_special_cases(
+  process_special_cases(
       temp_dir=temp_dir,
       system_target_files_temp_dir=system_target_files_temp_dir,
       other_target_files_temp_dir=other_target_files_temp_dir,
       output_target_files_temp_dir=output_target_files_temp_dir)
 
-  if result != 0:
-    return result
-
   # Regenerate IMAGES in the temporary directory.
 
   add_img_args = [
@@ -561,21 +510,14 @@
     f.write(other_content)
 
   command = [
-      # TODO(124468071): Use soong_zip from otatools.zip
-      'prebuilts/build-tools/linux-x86/bin/soong_zip',
+      'soong_zip',
       '-d',
       '-o', output_zip,
       '-C', output_target_files_temp_dir,
       '-l', output_target_files_list,
   ]
   logger.info('creating %s', output_target_files)
-  result = common.RunAndWait(command, verbose=True)
-
-  if result != 0:
-    logger.error('zip command %s failed %d', str(command), result)
-    return result
-
-  return 0
+  common.RunAndWait(command, verbose=True)
 
 
 def merge_target_files_with_temp_dir(
@@ -599,9 +541,6 @@
     package created by merging system and other.
 
     keep_tmp: Keep the temporary directory after processing is complete.
-
-  Returns:
-    On success, 0. Otherwise, a non-zero exit code.
   """
 
   # Create a temporary directory. This will serve as the parent of directories
@@ -617,7 +556,7 @@
   temp_dir = common.MakeTempDir(prefix='merge_target_files_')
 
   try:
-    return merge_target_files(
+    merge_target_files(
         temp_dir=temp_dir,
         system_target_files=system_target_files,
         other_target_files=other_target_files,
@@ -636,44 +575,46 @@
 
   Process command line arguments, then call merge_target_files_with_temp_dir to
   perform the heavy lifting.
-
-  Returns:
-    On success, 0. Otherwise, a non-zero exit code.
   """
 
   common.InitLogging()
 
-  parser = argparse.ArgumentParser()
+  def option_handler(o, a):
+    if o == '--system-target-files':
+      OPTIONS.system_target_files = a
+    elif o == '--other-target-files':
+      OPTIONS.other_target_files = a
+    elif o == '--output-target-files':
+      OPTIONS.output_target_files = a
+    elif o == '--keep_tmp':
+      OPTIONS.keep_tmp = True
+    else:
+      return False
+    return True
 
-  parser.add_argument(
-      '--system-target-files',
-      required=True,
-      help='The input target files package containing system bits.')
+  args = common.ParseOptions(
+      sys.argv[1:], __doc__,
+      extra_long_opts=[
+          'system-target-files=',
+          'other-target-files=',
+          'output-target-files=',
+          "keep_tmp",
+      ],
+      extra_option_handler=option_handler)
 
-  parser.add_argument(
-      '--other-target-files',
-      required=True,
-      help='The input target files package containing other bits.')
+  if (len(args) != 0 or
+      OPTIONS.system_target_files is None or
+      OPTIONS.other_target_files is None or
+      OPTIONS.output_target_files is None):
+    common.Usage(__doc__)
+    sys.exit(1)
 
-  parser.add_argument(
-      '--output-target-files',
-      required=True,
-      help='The output merged target files package.')
-
-  parser.add_argument(
-      '--keep-tmp',
-      required=False,
-      action='store_true',
-      help='Keep the temporary directories after execution.')
-
-  args = parser.parse_args()
-
-  return merge_target_files_with_temp_dir(
-      system_target_files=args.system_target_files,
-      other_target_files=args.other_target_files,
-      output_target_files=args.output_target_files,
-      keep_tmp=args.keep_tmp)
+  merge_target_files_with_temp_dir(
+      system_target_files=OPTIONS.system_target_files,
+      other_target_files=OPTIONS.other_target_files,
+      output_target_files=OPTIONS.output_target_files,
+      keep_tmp=OPTIONS.keep_tmp)
 
 
 if __name__ == '__main__':
-  sys.exit(main())
+  main()
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 4336cb3..fa9e2e9 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -71,6 +71,13 @@
       partitions but the target build does. For A/B, when this flag is set,
       --skip_postinstall is implied.
 
+  --skip_compatibility_check
+      Skip adding the compatibility package to the generated OTA package.
+
+  --output_metadata_path
+      Write a copy of the metadata to a separate file. Therefore, users can
+      read the post build fingerprint without extracting the OTA package.
+
 Non-A/B OTA specific options
 
   -b  (--binary) <file>
@@ -221,6 +228,8 @@
 OPTIONS.key_passwords = []
 OPTIONS.skip_postinstall = False
 OPTIONS.retrofit_dynamic_partitions = False
+OPTIONS.skip_compatibility_check = False
+OPTIONS.output_metadata_path = None
 
 
 METADATA_NAME = 'META-INF/com/android/metadata'
@@ -750,6 +759,11 @@
   if not HasTrebleEnabled(target_zip, target_info):
     return
 
+  # Skip adding the compatibility package as a workaround for b/114240221. The
+  # compatibility will always fail on devices without qualified kernels.
+  if OPTIONS.skip_compatibility_check:
+    return
+
   # Full OTA carries the info for system/vendor both.
   if source_info is None:
     AddCompatibilityArchive(True, True)
@@ -969,10 +983,22 @@
   FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
 
 
-def WriteMetadata(metadata, output_zip):
+def WriteMetadata(metadata, output):
+  """Writes the metadata to the zip archive or a file.
+
+  Args:
+    metadata: The metadata dict for the package.
+    output: A ZipFile object or a string of the output file path.
+  """
+
   value = "".join(["%s=%s\n" % kv for kv in sorted(metadata.iteritems())])
-  common.ZipWriteStr(output_zip, METADATA_NAME, value,
-                     compress_type=zipfile.ZIP_STORED)
+  if isinstance(output, zipfile.ZipFile):
+    common.ZipWriteStr(output, METADATA_NAME, value,
+                       compress_type=zipfile.ZIP_STORED)
+    return
+
+  with open(output, 'w') as f:
+    f.write(value)
 
 
 def HandleDowngradeMetadata(metadata, target_info, source_info):
@@ -1416,6 +1442,11 @@
     for property_files in needed_property_files:
       property_files.Verify(output_zip, metadata[property_files.name].strip())
 
+  # If requested, dump the metadata to a separate file.
+  output_metadata_path = OPTIONS.output_metadata_path
+  if output_metadata_path:
+    WriteMetadata(metadata, output_metadata_path)
+
 
 def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
   target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
@@ -2032,6 +2063,10 @@
       OPTIONS.skip_postinstall = True
     elif o == "--retrofit_dynamic_partitions":
       OPTIONS.retrofit_dynamic_partitions = True
+    elif o == "--skip_compatibility_check":
+      OPTIONS.skip_compatibility_check = True
+    elif o == "--output_metadata_path":
+      OPTIONS.output_metadata_path = a
     else:
       return False
     return True
@@ -2063,6 +2098,8 @@
                                  "extracted_input_target_files=",
                                  "skip_postinstall",
                                  "retrofit_dynamic_partitions",
+                                 "skip_compatibility_check",
+                                 "output_metadata_path=",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index a6a8876..5f619ec 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -19,11 +19,13 @@
 import os
 import os.path
 import shutil
+import zipfile
 
 import common
 import test_utils
-import verity_utils
-from validate_target_files import ValidateVerifiedBootImages
+from rangelib import RangeSet
+from validate_target_files import (ValidateVerifiedBootImages,
+                                   ValidateFileConsistency)
 from verity_utils import CreateVerityImageBuilder
 
 
@@ -107,7 +109,8 @@
         AssertionError, ValidateVerifiedBootImages, input_tmp, info_dict,
         options)
 
-  def _generate_system_image(self, output_file):
+  def _generate_system_image(self, output_file, system_root=None,
+                             file_map=None):
     prop_dict = {
         'partition_size': str(1024 * 1024),
         'verity': 'true',
@@ -120,9 +123,12 @@
     image_size = verity_image_builder.CalculateMaxImageSize()
 
     # Use an empty root directory.
-    system_root = common.MakeTempDir()
+    if not system_root:
+      system_root = common.MakeTempDir()
     cmd = ['mkuserimg_mke2fs', '-s', system_root, output_file, 'ext4',
            '/system', str(image_size), '-j', '0']
+    if file_map:
+      cmd.extend(['-B', file_map])
     proc = common.Run(cmd)
     stdoutdata, _ = proc.communicate()
     self.assertEqual(
@@ -155,3 +161,56 @@
         'verity_key_mincrypt' : verity_key_mincrypt,
     }
     ValidateVerifiedBootImages(input_tmp, info_dict, options)
+
+  def test_ValidateFileConsistency_incompleteRange(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    system_root = os.path.join(input_tmp, "SYSTEM")
+    os.mkdir(system_root)
+
+    # Write the test file that contain multiple blocks of zeros, and these
+    # zero blocks will be omitted by kernel. And the test files will occupy one
+    # block range each in the final system image.
+    with open(os.path.join(system_root, 'a'), 'w') as f:
+      f.write("aaa")
+      f.write('\0' * 4096 * 3)
+    with open(os.path.join(system_root, 'b'), 'w') as f:
+      f.write("bbb")
+      f.write('\0' * 4096 * 3)
+
+    raw_file_map = os.path.join(input_tmp, 'IMAGES', 'raw_system.map')
+    self._generate_system_image(system_image, system_root, raw_file_map)
+
+    # Parse the generated file map and update the block ranges for each file.
+    file_map_list = {}
+    image_ranges = RangeSet()
+    with open(raw_file_map, 'r') as f:
+      for line in f.readlines():
+        info = line.split()
+        self.assertEqual(2, len(info))
+        image_ranges = image_ranges.union(RangeSet(info[1]))
+        file_map_list[info[0]] = RangeSet(info[1])
+
+    # Add one unoccupied block as the shared block for all test files.
+    mock_shared_block = RangeSet("10-20").subtract(image_ranges).first(1)
+    with open(os.path.join(input_tmp, 'IMAGES', 'system.map'), 'w') as f:
+      for key in sorted(file_map_list.keys()):
+        line = "{} {}\n".format(
+            key, file_map_list[key].union(mock_shared_block))
+        f.write(line)
+
+    # Prepare for the target zip file
+    input_file = common.MakeTempFile()
+    all_entries = ['SYSTEM/', 'SYSTEM/b', 'SYSTEM/a', 'IMAGES/',
+                   'IMAGES/system.map', 'IMAGES/system.img']
+    with zipfile.ZipFile(input_file, 'w') as input_zip:
+      for name in all_entries:
+        input_zip.write(os.path.join(input_tmp, name), arcname=name)
+
+    input_zip = zipfile.ZipFile(input_file, 'r')
+    info_dict = {'extfs_sparse_flag': '-s'}
+
+    # Expect the validation to pass and both files are skipped due to
+    # 'incomplete' block range.
+    ValidateFileConsistency(input_zip, input_tmp, info_dict)
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index eeb802b..275939c 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -84,11 +84,6 @@
       # bytes past the file length, which is expected to be padded with '\0's.
       ranges = image.file_map[entry]
 
-      incomplete = ranges.extra.get('incomplete', False)
-      if incomplete:
-        logging.warning('Skipping %s that has incomplete block list', entry)
-        continue
-
       # Use the original RangeSet if applicable, which includes the shared
       # blocks. And this needs to happen before checking the monotonicity flag.
       if ranges.extra.get('uses_shared_blocks'):
@@ -96,6 +91,11 @@
       else:
         file_ranges = ranges
 
+      incomplete = file_ranges.extra.get('incomplete', False)
+      if incomplete:
+        logging.warning('Skipping %s that has incomplete block list', entry)
+        continue
+
       # TODO(b/79951650): Handle files with non-monotonic ranges.
       if not file_ranges.monotonic:
         logging.warning(