Merge "Add phony target to check all PCF ELF prebuilts"
diff --git a/common/math.mk b/common/math.mk
index 83f2218..ec15f88 100644
--- a/common/math.mk
+++ b/common/math.mk
@@ -181,6 +181,22 @@
 $(call math-expect,(call numbers_less_than,4,0 2 1 3),0 2 1 3)
 $(call math-expect,(call numbers_less_than,3,0 2 1 3 2),0 2 1 2)
 
+# Returns the words in $2 that are numbers and are greater or equal to $1
+define numbers_greater_or_equal_to
+$(strip \
+  $(foreach n,$2, \
+    $(if $(call math_is_number,$(n)), \
+      $(if $(call math_gt_or_eq,$(n),$(1)), \
+        $(n)))))
+endef
+
+$(call math-expect,(call numbers_greater_or_equal_to,4,0 1 2 3),)
+$(call math-expect,(call numbers_greater_or_equal_to,3,0 2 1 3),3)
+$(call math-expect,(call numbers_greater_or_equal_to,2,0 2 1 3),2 3)
+$(call math-expect,(call numbers_greater_or_equal_to,1,0 2 1 3),2 1 3)
+$(call math-expect,(call numbers_greater_or_equal_to,0,0 2 1 3),0 2 1 3)
+$(call math-expect,(call numbers_greater_or_equal_to,1,0 2 1 3 2),2 1 3 2)
+
 _INT_LIMIT_WORDS := $(foreach a,x x,$(foreach b,x x x x x x x x x x x x x x x x,\
   $(foreach c,x x x x x x x x x x x x x x x x,x x x x x x x x x x x x x x x x)))
 
diff --git a/core/Makefile b/core/Makefile
index 23ef48d..30a41d1 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -449,7 +449,7 @@
 	  $(if $(PACKAGES.$(p).APKCERTS_FILE),\
 	    $(call _apkcerts_merge,$(PACKAGES.$(p).APKCERTS_FILE), $@),\
 	    $(if $(PACKAGES.$(p).EXTERNAL_KEY),\
-	      $(call _apkcerts_write_line,$(PACKAGES.$(p).STEM),"EXTERNAL","",$(PACKAGES.$(p).COMPRESSED),$(PACKAGES.$(p).PARTITION),$@),\
+	      $(call _apkcerts_write_line,$(PACKAGES.$(p).STEM),EXTERNAL,,$(PACKAGES.$(p).COMPRESSED),$(PACKAGES.$(p).PARTITION),$@),\
 	      $(call _apkcerts_write_line,$(PACKAGES.$(p).STEM),$(PACKAGES.$(p).CERTIFICATE),$(PACKAGES.$(p).PRIVATE_KEY),$(PACKAGES.$(p).COMPRESSED),$(PACKAGES.$(p).PARTITION),$@))))
 	# In case value of PACKAGES is empty.
 	$(hide) touch $@
@@ -715,6 +715,26 @@
   BUILT_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
 endif
 
+INTERNAL_PREBUILT_BOOTIMAGE :=
+
+my_installed_prebuilt_gki_apex := $(strip $(foreach package,$(PRODUCT_PACKAGES),$(if $(ALL_MODULES.$(package).EXTRACTED_BOOT_IMAGE),$(package))))
+ifdef my_installed_prebuilt_gki_apex
+  ifneq (1,$(words $(my_installed_prebuilt_gki_apex))) # len(my_installed_prebuilt_gki_apex) > 1
+    $(error More than one prebuilt GKI APEXes are installed: $(my_installed_prebuilt_gki_apex))
+  endif # len(my_installed_prebuilt_gki_apex) > 1
+
+  ifdef BOARD_PREBUILT_BOOTIMAGE
+    $(error Must not define BOARD_PREBUILT_BOOTIMAGE because a prebuilt GKI APEX is installed: $(my_installed_prebuilt_gki_apex))
+  endif # BOARD_PREBUILT_BOOTIMAGE defined
+
+  my_apex_extracted_boot_image := $(ALL_MODULES.$(my_installed_prebuilt_gki_apex).EXTRACTED_BOOT_IMAGE)
+  INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
+  $(eval $(call copy-one-file,$(my_apex_extracted_boot_image),$(INSTALLED_BOOTIMAGE_TARGET)))
+
+  INTERNAL_PREBUILT_BOOTIMAGE := $(my_apex_extracted_boot_image)
+
+else # my_installed_prebuilt_gki_apex not defined
+
 # $1: boot image target
 # returns the kernel used to make the bootimage
 define bootimage-to-kernel
@@ -758,30 +778,27 @@
 
 INTERNAL_KERNEL_CMDLINE := $(strip $(INTERNAL_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
 
-boot_uses_generic_kernel_image :=
-ifdef BUILDING_VENDOR_BOOT_IMAGE
-  # building vendor boot image, dtb/base/pagesize go there
-  boot_uses_generic_kernel_image := true
-else ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
-  boot_uses_generic_kernel_image := true
-endif
-
-ifeq (true,$(boot_uses_generic_kernel_image))
+# kernel cmdline/base/pagesize in boot.
+# - If using GKI, use GENERIC_KERNEL_CMDLINE. Remove kernel base and pagesize because they are
+#   device-specific.
+# - If not using GKI:
+#   - If building vendor_boot, INTERNAL_KERNEL_CMDLINE, base and pagesize goes in vendor_boot.
+#   - Otherwise, put them in boot.
+ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
   ifdef GENERIC_KERNEL_CMDLINE
     INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
   endif
-else # boot_uses_generic_kernel_image != true
-ifdef BOARD_KERNEL_BASE
-  INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
-endif
-ifdef BOARD_KERNEL_PAGESIZE
-  INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
-endif
-ifdef INTERNAL_KERNEL_CMDLINE
-  INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
-endif
-endif # boot_uses_generic_kernel_image == true
-boot_uses_generic_kernel_image :=
+else ifndef BUILDING_VENDOR_BOOT_IMAGE # && BOARD_USES_GENERIC_KERNEL_IMAGE != true
+  ifdef INTERNAL_KERNEL_CMDLINE
+    INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
+  endif
+  ifdef BOARD_KERNEL_BASE
+    INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
+  endif
+  ifdef BOARD_KERNEL_PAGESIZE
+    INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
+  endif
+endif # BUILDING_VENDOR_BOOT_IMAGE == "" && BOARD_USES_GENERIC_KERNEL_IMAGE != true
 
 INTERNAL_MKBOOTIMG_VERSION_ARGS := \
     --os_version $(PLATFORM_VERSION_LAST_STABLE) \
@@ -881,12 +898,17 @@
 # Remove when b/63676296 is resolved.
 $(error Prebuilt bootimage is only supported for AB targets)
 endif
+INTERNAL_PREBUILT_BOOTIMAGE := $(BOARD_PREBUILT_BOOTIMAGE)
 INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
-$(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
+$(eval $(call copy-one-file,$(INTERNAL_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
 else # BOARD_PREBUILT_BOOTIMAGE not defined
 INSTALLED_BOOTIMAGE_TARGET :=
 endif # BOARD_PREBUILT_BOOTIMAGE
 endif # TARGET_NO_KERNEL
+endif # my_installed_prebuilt_gki_apex not defined
+
+my_apex_extracted_boot_image :=
+my_installed_prebuilt_gki_apex :=
 
 # -----------------------------------------------------------------
 # declare recovery ramdisk files
@@ -916,6 +938,17 @@
 $(INTERNAL_VENDOR_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
 	$(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) $(PRIVATE_ADDITIONAL_DIR) | $(COMPRESSION_COMMAND) > $@
 
+INSTALLED_FILES_FILE_VENDOR_RAMDISK := $(PRODUCT_OUT)/installed-files-vendor-ramdisk.txt
+INSTALLED_FILES_JSON_VENDOR_RAMDISK := $(INSTALLED_FILES_FILE_VENDOR_RAMDISK:.txt=.json)
+$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_VENDOR_RAMDISK)
+$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): $(INTERNAL_VENDOR_RAMDISK_TARGET)
+$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): $(INTERNAL_VENDOR_RAMDISK_FILES) $(FILESLIST) $(FILESLIST_UTIL)
+	echo Installed file list: $@
+	mkdir -p $(dir $@)
+	rm -f $@
+	$(hide) $(FILESLIST) $(TARGET_VENDOR_RAMDISK_OUT) > $(@:.txt=.json)
+	$(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+
 ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
   INTERNAL_VENDOR_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
 endif
@@ -1279,6 +1312,9 @@
 ifneq (true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED))
   INTERNAL_USERIMAGES_SPARSE_EXT_FLAG := -s
 endif
+ifneq (true,$(TARGET_USERIMAGES_SPARSE_EROFS_DISABLED))
+  INTERNAL_USERIMAGES_SPARSE_EROFS_FLAG := -s
+endif
 ifneq (true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED))
   INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG := -s
 endif
@@ -1303,6 +1339,18 @@
     $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE) \
     $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE) \
     $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE) \
+  ,erofs),)
+INTERNAL_USERIMAGES_DEPS += $(MKEROFSUSERIMG)
+endif
+
+ifneq ($(filter \
+    $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE) \
+    $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE) \
+    $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE) \
+    $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) \
+    $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE) \
+    $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE) \
+    $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE) \
   ,squashfs),)
 INTERNAL_USERIMAGES_DEPS += $(MKSQUASHFSUSERIMG)
 endif
@@ -1475,6 +1523,7 @@
 
 $(if $(INTERNAL_USERIMAGES_EXT_VARIANT),$(hide) echo "fs_type=$(INTERNAL_USERIMAGES_EXT_VARIANT)" >> $(1))
 $(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1))
+$(if $(INTERNAL_USERIMAGES_SPARSE_EROFS_FLAG),$(hide) echo "erofs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EROFS_FLAG)" >> $(1))
 $(if $(INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG),$(hide) echo "squashfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG)" >> $(1))
 $(if $(INTERNAL_USERIMAGES_SPARSE_F2FS_FLAG),$(hide) echo "f2fs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_F2FS_FLAG)" >> $(1))
 $(if $(BOARD_EXT4_SHARE_DUP_BLOCKS),$(hide) echo "ext4_share_dup_blocks=$(BOARD_EXT4_SHARE_DUP_BLOCKS)" >> $(1))
@@ -1621,16 +1670,15 @@
 INSTALLED_FILES_FILE_RECOVERY := $(PRODUCT_OUT)/installed-files-recovery.txt
 INSTALLED_FILES_JSON_RECOVERY := $(INSTALLED_FILES_FILE_RECOVERY:.txt=.json)
 
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+INSTALLED_BOOTIMAGE_TARGET := $(BUILT_BOOTIMAGE_TARGET)
+endif
+
 # TODO(b/30414428): Can't depend on INTERNAL_RECOVERYIMAGE_FILES alone like other
 # INSTALLED_FILES_FILE_* rules. Because currently there're cp/rsync/rm commands in
 # build-recoveryimage-target, which would touch the files under TARGET_RECOVERY_OUT and race with
 # the call to FILELIST.
-ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
-INSTALLED_BOOTIMAGE_TARGET := $(BUILT_BOOTIMAGE_TARGET)
-$(INSTALLED_FILES_FILE_RECOVERY): $(INSTALLED_BOOTIMAGE_TARGET)
-else
-$(INSTALLED_FILES_FILE_RECOVERY): $(INSTALLED_RECOVERYIMAGE_TARGET)
-endif
+$(INSTALLED_FILES_FILE_RECOVERY): $(INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP)
 
 $(INSTALLED_FILES_FILE_RECOVERY): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_RECOVERY)
 $(INSTALLED_FILES_FILE_RECOVERY): $(INTERNAL_RECOVERYIMAGE_FILES) $(FILESLIST) $(FILESLIST_UTIL)
@@ -1897,19 +1945,10 @@
 	$(copy-file-to-target)
 endif
 
-ifeq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(AB_OTA_UPDATER)))
-  INTERNAL_RECOVERYIMAGE_ARGS := --ramdisk $(recovery_ramdisk)
+INTERNAL_RECOVERYIMAGE_ARGS := --ramdisk $(recovery_ramdisk)
 
-ifneq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
-ifdef GENERIC_KERNEL_CMDLINE
-  INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
-endif # GENERIC_KERNEL_CMDLINE != ""
-endif # BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE != true
-
-else # not (BUILDING_VENDOR_BOOT_IMAGE and AB_OTA_UPDATER)
-  INTERNAL_RECOVERYIMAGE_ARGS := \
-      $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
-      --ramdisk $(recovery_ramdisk)
+ifneq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(BOARD_USES_RECOVERY_AS_BOOT)))
+INTERNAL_RECOVERYIMAGE_ARGS += $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET))
 # Assumes this has already been stripped
 ifneq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
 ifdef INTERNAL_KERNEL_CMDLINE
@@ -1935,7 +1974,7 @@
 ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
   INTERNAL_RECOVERYIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
 endif
-endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined
+endif # (BUILDING_VENDOR_BOOT_IMAGE and BOARD_USES_RECOVERY_AS_BOOT)
 ifndef BOARD_RECOVERY_MKBOOTIMG_ARGS
   BOARD_RECOVERY_MKBOOTIMG_ARGS := $(BOARD_MKBOOTIMG_ARGS)
 endif
@@ -2431,6 +2470,15 @@
 # -----------------------------------------------------------------
 ifdef BUILDING_SYSTEM_IMAGE
 
+# Install system linker configuration
+# Collect all available stub libraries installed in system and install with predefined linker configuration
+SYSTEM_LINKER_CONFIG := $(TARGET_OUT)/etc/linker.config.pb
+$(SYSTEM_LINKER_CONFIG) : $(INTERNAL_SYSTEMIMAGE_FILES) $(LINKER_CONFIG_PATH_system_linker_config) | conv_linker_config
+	$(HOST_OUT_EXECUTABLES)/conv_linker_config systemprovide --source $(LINKER_CONFIG_PATH_system_linker_config)\
+	  --output $@ --value "$(STUB_LIBRARIES)" --system "$(TARGET_OUT)"
+
+FULL_SYSTEMIMAGE_DEPS += $(SYSTEM_LINKER_CONFIG)
+
 # installed file list
 # Depending on anything that $(BUILT_SYSTEMIMAGE) depends on.
 # We put installed-files.txt ahead of image itself in the dependency graph
@@ -3721,7 +3769,7 @@
 $(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(firstword $(INSTALLED_KERNEL_TARGET))
 	$< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(firstword $(INSTALLED_KERNEL_TARGET)) \
 	  --output-configs $@ \
-	  --output-version $(BUILT_KERNEL_VERSION_FILE)
+	  --output-release $(BUILT_KERNEL_VERSION_FILE)
 
 my_decompress_tools :=
 
@@ -3730,7 +3778,7 @@
 
 endif # INSTALLED_KERNEL_TARGET
 
-check_vintf_compatible_args += --kernel $$(cat $(BUILT_KERNEL_VERSION_FILE)):$(BUILT_KERNEL_CONFIGS_FILE)
+check_vintf_compatible_args += --kernel $(BUILT_KERNEL_VERSION_FILE):$(BUILT_KERNEL_CONFIGS_FILE)
 check_vintf_compatible_deps += $(BUILT_KERNEL_CONFIGS_FILE) $(BUILT_KERNEL_VERSION_FILE)
 
 endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
@@ -3915,6 +3963,7 @@
   fec \
   fs_config \
   generate_verity_key \
+  host_init_verifier \
   img2simg \
   img_from_target_files \
   imgdiff \
@@ -3931,6 +3980,8 @@
   mkbootimg \
   mke2fs \
   mke2fs.conf \
+  mkfs.erofs \
+  mkerofsimage.sh \
   mkf2fsuserimg.sh \
   mksquashfs \
   mksquashfsimage.sh \
@@ -4113,6 +4164,9 @@
 	$(hide) echo "board_uses_vendorimage=true" >> $@
 endif
 ifeq ($(BOARD_AVB_ENABLE),true)
+ifeq ($(BUILDING_VBMETA_IMAGE),true)
+	$(hide) echo "avb_building_vbmeta_image=true" >> $@
+endif # BUILDING_VBMETA_IMAGE
 	$(hide) echo "avb_enable=true" >> $@
 	$(hide) echo "avb_vbmeta_key_path=$(BOARD_AVB_KEY_PATH)" >> $@
 	$(hide) echo "avb_vbmeta_algorithm=$(BOARD_AVB_ALGORITHM)" >> $@
@@ -4212,6 +4266,9 @@
 ifeq ($(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE),true)
 	$(hide) echo "exclude_kernel_from_recovery_image=true" >> $@
 endif
+ifneq ($(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST),)
+	$(hide) echo "partial_ota_update_partitions_list=$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)" >> $@
+endif
 
 .PHONY: misc_info
 misc_info: $(INSTALLED_MISC_INFO_TARGET)
@@ -4415,7 +4472,8 @@
 
 ifdef BUILDING_BOOT_IMAGE
   $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_RAMDISK_FILES)
-else ifdef BOARD_PREBUILT_BOOTIMAGE
+endif
+ifneq (,$(INTERNAL_PREBUILT_BOOTIMAGE) $(filter true,$(BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES)))
   $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_BOOTIMAGE_TARGET)
 endif
 
@@ -4497,11 +4555,7 @@
 	cp $(firstword $(INSTALLED_KERNEL_TARGET)) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/kernel
 endif
 endif
-ifeq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(AB_OTA_UPDATER)))
-ifneq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
-	echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
-endif # BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE != true
-else # not (BUILDING_VENDOR_BOOT_IMAGE and AB_OTA_UPDATER)
+ifneq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(BOARD_USES_RECOVERY_AS_BOOT)))
 ifdef INSTALLED_2NDBOOTLOADER_TARGET
 	cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
 endif
@@ -4529,7 +4583,7 @@
 ifdef BOARD_KERNEL_PAGESIZE
 	echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/pagesize
 endif
-endif # not (BUILDING_VENDOR_BOOT_IMAGE and AB_OTA_UPDATER)
+endif # not (BUILDING_VENDOR_BOOT_IMAGE and BOARD_USES_RECOVERY_AS_BOOT)
 endif # INSTALLED_RECOVERYIMAGE_TARGET defined or BOARD_USES_RECOVERY_AS_BOOT is true
 	@# Components of the boot image
 	$(hide) mkdir -p $(zip_root)/BOOT
@@ -4545,11 +4599,9 @@
 ifdef INSTALLED_KERNEL_TARGET
 	$(hide) cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/
 endif
-ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
+ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
 	echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
-else ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
-	echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
-else # INSTALLED_VENDOR_BOOTIMAGE_TARGET == "" && BOARD_USES_GENERIC_KERNEL_IMAGE != true
+else ifndef INSTALLED_VENDOR_BOOTIMAGE_TARGET # && BOARD_USES_GENERIC_KERNEL_IMAGE != true
 	echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
 ifdef INSTALLED_2NDBOOTLOADER_TARGET
 	cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
@@ -4720,10 +4772,12 @@
 	$(hide) mkdir -p $(zip_root)/IMAGES
 	$(hide) cp $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) $(zip_root)/IMAGES/
 endif
-ifdef BOARD_PREBUILT_BOOTIMAGE
+ifneq (,$(INTERNAL_PREBUILT_BOOTIMAGE) $(filter true,$(BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES)))
+ifdef INSTALLED_BOOTIMAGE_TARGET
 	$(hide) mkdir -p $(zip_root)/IMAGES
 	$(hide) cp $(INSTALLED_BOOTIMAGE_TARGET) $(zip_root)/IMAGES/
-endif
+endif # INSTALLED_BOOTIMAGE_TARGET
+endif # INTERNAL_PREBUILT_BOOTIMAGE != "" || BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES == true
 ifdef BOARD_PREBUILT_ODMIMAGE
 	$(hide) mkdir -p $(zip_root)/IMAGES
 	$(hide) cp $(INSTALLED_ODMIMAGE_TARGET) $(zip_root)/IMAGES/
diff --git a/core/base_rules.mk b/core/base_rules.mk
index adf61f1..dbd8930 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -274,6 +274,12 @@
   endif
 endif
 
+ifeq ($(LOCAL_IS_UNIT_TEST),true)
+  ifeq ($(LOCAL_IS_HOST_MODULE),true)
+    LOCAL_COMPATIBILITY_SUITE += host-unit-tests
+  endif
+endif
+
 ifeq ($(my_module_path),)
   install_path_var := $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS)
   ifeq (true,$(LOCAL_PRIVILEGED_MODULE))
diff --git a/core/board_config.mk b/core/board_config.mk
index 457b3bf..d674d1a 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -107,11 +107,14 @@
 #   recovery resources are built to vendor_boot.
 # - BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT controls whether GSI AVB keys are
 #   built to vendor_boot.
+# - BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES controls whether boot images in $OUT are added
+#   to target files package directly.
 _board_strip_readonly_list += \
   BOARD_USES_GENERIC_KERNEL_IMAGE \
   BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE \
   BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT \
   BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT \
+  BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES \
 
 _build_broken_var_list := \
   BUILD_BROKEN_DUP_RULES \
@@ -787,3 +790,10 @@
       Use BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT instead)
   endif
 endif
+
+ifeq (true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT))
+  ifeq (true,$(BOARD_USES_RECOVERY_AS_BOOT))
+    $(error BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT and BOARD_USES_RECOVERY_AS_BOOT cannot be \
+      both true. Recovery resources should be installed to either boot or vendor_boot, but not both)
+  endif
+endif
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 6e1cb68..6909275 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -130,6 +130,7 @@
 LOCAL_IS_FUZZ_TARGET:=
 LOCAL_IS_HOST_MODULE:=
 LOCAL_IS_RUNTIME_RESOURCE_OVERLAY:=
+LOCAL_IS_UNIT_TEST:=
 LOCAL_JACK_CLASSPATH:=
 LOCAL_JACK_COVERAGE_EXCLUDE_FILTER:=
 LOCAL_JACK_COVERAGE_INCLUDE_FILTER:=
diff --git a/core/config.mk b/core/config.mk
index e975214..f860c43 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -555,6 +555,7 @@
 FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
 MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs
 MKE2FS_CONF := system/extras/ext4_utils/mke2fs.conf
+MKEROFSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkerofsimage.sh
 MKSQUASHFSUSERIMG := $(HOST_OUT_EXECUTABLES)/mksquashfsimage.sh
 MKF2FSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh
 SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)
diff --git a/core/definitions.mk b/core/definitions.mk
index d560644..0230340 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -107,7 +107,7 @@
 # All tests that should be skipped in presubmit check.
 ALL_DISABLED_PRESUBMIT_TESTS :=
 
-# All compatibility suites mentioned in LOCAL_COMPATIBILITY_SUITES
+# All compatibility suites mentioned in LOCAL_COMPATIBILITY_SUITE
 ALL_COMPATIBILITY_SUITES :=
 
 # All compatibility suite files to dist.
@@ -2404,6 +2404,7 @@
 	$(1) \
 	$(HOST_INIT_VERIFIER) \
 	$(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+	$(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
 	$(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
 	$(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
 	$(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
@@ -2414,6 +2415,7 @@
 	$(call intermediates-dir-for,ETC,odm_property_contexts)/odm_property_contexts
 	$(hide) $(HOST_INIT_VERIFIER) \
 	  -p $(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+	  -p $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
 	  -p $(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
 	  -p $(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
 	  -p $(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 799b623..c31d4e8 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -189,20 +189,42 @@
   my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \
     $(LOCAL_OPTIONAL_USES_LIBRARIES))
 
-  # dexpreopt needs the paths to the dex jars of these libraries in order to
-  # construct class loader context for dex2oat.
-  my_extra_dexpreopt_libs := \
-    org.apache.http.legacy \
+  # compatibility libraries are added to class loader context of an app only if
+  # targetSdkVersion in the app's manifest is lower than the given SDK version
+
+  my_dexpreopt_libs_compat_28 := \
+    org.apache.http.legacy
+
+  my_dexpreopt_libs_compat_29 := \
     android.hidl.base-V1.0-java \
-    android.hidl.manager-V1.0-java \
+    android.hidl.manager-V1.0-java
+
+  my_dexpreopt_libs_compat_30 := \
     android.test.base \
+    android.test.mock
+
+  my_dexpreopt_libs_compat := \
+    $(my_dexpreopt_libs_compat_28) \
+    $(my_dexpreopt_libs_compat_29) \
+    $(my_dexpreopt_libs_compat_30)
 
   my_dexpreopt_libs := $(sort \
     $(LOCAL_USES_LIBRARIES) \
     $(my_filtered_optional_uses_libraries) \
-    $(my_extra_dexpreopt_libs) \
   )
 
+  # 1: SDK version
+  # 2: list of libraries
+  add_json_class_loader_context = \
+    $(call add_json_map, $(1)) \
+    $(foreach lib, $(2),\
+      $(call add_json_map, $(lib)) \
+      $(eval file := $(filter %/$(lib).jar, $(call module-installed-files,$(lib)))) \
+      $(call add_json_str, Host,       $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \
+      $(call add_json_str, Device,     $(call install-path-to-on-device-path,$(file))) \
+      $(call end_json_map)) \
+    $(call end_json_map)
+
   # Record dex-preopt config.
   DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT)
   DEXPREOPT.$(LOCAL_MODULE).MULTILIB := $(LOCAL_MULTILIB)
@@ -230,15 +252,11 @@
   $(call add_json_str,  ProfileClassListing,            $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE)))
   $(call add_json_bool, ProfileIsTextListing,           $(my_profile_is_text_listing))
   $(call add_json_bool, EnforceUsesLibraries,           $(LOCAL_ENFORCE_USES_LIBRARIES))
-  $(call add_json_list, OptionalUsesLibraries,          $(my_filtered_optional_uses_libraries))
-  $(call add_json_list, UsesLibraries,                  $(LOCAL_USES_LIBRARIES))
-  $(call add_json_map,  LibraryPaths)
-  $(foreach lib,$(my_dexpreopt_libs),\
-    $(call add_json_map, $(lib)) \
-    $(eval file := $(filter %/$(lib).jar, $(call module-installed-files,$(lib)))) \
-    $(call add_json_str, Host,   $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \
-    $(call add_json_str, Device, $(call install-path-to-on-device-path,$(file))) \
-    $(call end_json_map))
+  $(call add_json_map,  ClassLoaderContexts)
+  $(call add_json_class_loader_context, any, $(my_dexpreopt_libs))
+  $(call add_json_class_loader_context,  28, $(my_dexpreopt_libs_compat_28))
+  $(call add_json_class_loader_context,  29, $(my_dexpreopt_libs_compat_29))
+  $(call add_json_class_loader_context,  30, $(my_dexpreopt_libs_compat_30))
   $(call end_json_map)
   $(call add_json_list, Archs,                          $(my_dexpreopt_archs))
   $(call add_json_list, DexPreoptImages,                $(my_dexpreopt_images))
@@ -280,7 +298,7 @@
   my_dexpreopt_deps := $(my_dex_jar)
   my_dexpreopt_deps += $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE))
   my_dexpreopt_deps += \
-    $(foreach lib, $(my_dexpreopt_libs), \
+    $(foreach lib, $(my_dexpreopt_libs) $(my_dexpreopt_libs_compat), \
       $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar)
   my_dexpreopt_deps += $(my_dexpreopt_images_deps)
   my_dexpreopt_deps += $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
diff --git a/core/dumpvar.mk b/core/dumpvar.mk
index b2ee8fd..6b5c030 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -24,9 +24,14 @@
 # Input variables:
 #   DUMP_MANY_VARS: the list of variable names.
 #   DUMP_VAR_PREFIX: an optional prefix of the variable name added to the output.
+# The value is printed in parts because large variables like PRODUCT_PACKAGES
+# can exceed the maximum linux command line size
 .PHONY: dump-many-vars
 dump-many-vars :
 	@$(foreach v, $(DUMP_MANY_VARS),\
-	  printf "%s='%s'\n" '$(DUMP_VAR_PREFIX)$(v)' '$($(v))';)
+	  printf "%s='%s" '$(DUMP_VAR_PREFIX)$(v)' '$(firstword $($(v)))'; \
+	  $(foreach part, $(wordlist 2, $(words $($(v))), $($(v))),\
+	    printf " %s" '$(part)'$(newline))\
+	  printf "'\n";)
 
 endif # CALLED_FROM_SETUP
diff --git a/core/java_host_unit_test_config_template.xml b/core/java_host_unit_test_config_template.xml
new file mode 100644
index 0000000..ff300da
--- /dev/null
+++ b/core/java_host_unit_test_config_template.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {MODULE}">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-unit-tests" />
+
+    {EXTRA_CONFIGS}
+
+    <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+        <option name="jar" value="{MODULE}.jar" />
+    </test>
+</configuration>
diff --git a/core/main.mk b/core/main.mk
index 9ba43f6..d8a0443 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -748,7 +748,7 @@
     $(eval r := $(call module-installed-files,$(r))) \
     $(eval h_m := $(filter $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
     $(eval h_r := $(filter $(HOST_OUT)/%, $(r))) \
-    $(eval h_m := $(filter-out $(h_r), $(h_m))) \
+    $(eval h_r := $(filter-out $(h_m), $(h_r))) \
     $(if $(h_m), $(eval $(call add-required-deps, $(h_m),$(h_r)))) \
   ) \
 )
@@ -764,7 +764,7 @@
     $(eval r := $(call module-installed-files,$(r))) \
     $(eval hc_m := $(filter $(HOST_CROSS_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
     $(eval hc_r := $(filter $(HOST_CROSS_OUT)/%, $(r))) \
-    $(eval hc_m := $(filter-out $(hc_r), $(hc_m))) \
+    $(eval hc_r := $(filter-out $(hc_m), $(hc_r))) \
     $(if $(hc_m), $(eval $(call add-required-deps, $(hc_m),$(hc_r)))) \
   ) \
 )
@@ -780,7 +780,7 @@
     $(eval r := $(call module-installed-files,$(r))) \
     $(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
     $(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \
-    $(eval t_m := $(filter-out $(t_r), $(t_m))) \
+    $(eval t_r := $(filter-out $(t_m), $(t_r))) \
     $(if $(t_m), $(eval $(call add-required-deps, $(t_m),$(t_r)))) \
   ) \
 )
@@ -807,7 +807,6 @@
     )\
     $(eval req_files := $(strip $(req_files)))\
     $(eval mod_files := $(filter $(HOST_OUT)/%, $(call module-installed-files,$(m)))) \
-    $(eval mod_files := $(filter-out $(req_files),$(mod_files)))\
     $(if $(mod_files),\
       $(eval $(call add-required-deps, $(mod_files),$(req_files))) \
     )\
@@ -836,7 +835,6 @@
     )\
     $(eval req_files := $(strip $(req_files)))\
     $(eval mod_files := $(filter $(TARGET_OUT_ROOT)/%, $(call module-installed-files,$(m))))\
-    $(eval mod_files := $(filter-out $(req_files),$(mod_files)))\
     $(if $(mod_files),\
       $(eval $(call add-required-deps, $(mod_files),$(req_files))) \
     )\
@@ -895,7 +893,7 @@
 # Scan all modules in general-tests, device-tests and other selected suites and
 # flatten the shared library dependencies.
 define update-host-shared-libs-deps-for-suites
-$(foreach suite,general-tests device-tests vts art-host-tests,\
+$(foreach suite,general-tests device-tests vts art-host-tests host-unit-tests,\
   $(foreach m,$(COMPATIBILITY.$(suite).MODULES),\
     $(eval my_deps := $(call get-all-shared-libs-deps,$(m)))\
     $(foreach dep,$(my_deps),\
@@ -1627,6 +1625,8 @@
     $(INSTALLED_FILES_JSON_RAMDISK) \
     $(INSTALLED_FILES_FILE_DEBUG_RAMDISK) \
     $(INSTALLED_FILES_JSON_DEBUG_RAMDISK) \
+    $(INSTALLED_FILES_FILE_VENDOR_RAMDISK) \
+    $(INSTALLED_FILES_JSON_VENDOR_RAMDISK) \
     $(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK) \
     $(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
     $(INSTALLED_FILES_FILE_ROOT) \
@@ -1641,6 +1641,7 @@
 
 ifeq ($(SOONG_COLLECT_JAVA_DEPS), true)
   $(call dist-for-goals, dist_files, $(SOONG_OUT_DIR)/module_bp_java_deps.json)
+  $(call dist-for-goals, dist_files, $(PRODUCT_OUT)/module-info.json)
 endif
 
 .PHONY: apps_only
@@ -1775,6 +1776,8 @@
       $(INSTALLED_FILES_JSON_RAMDISK) \
       $(INSTALLED_FILES_FILE_DEBUG_RAMDISK) \
       $(INSTALLED_FILES_JSON_DEBUG_RAMDISK) \
+      $(INSTALLED_FILES_FILE_VENDOR_RAMDISK) \
+      $(INSTALLED_FILES_JSON_VENDOR_RAMDISK) \
       $(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK) \
       $(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
       $(INSTALLED_DEBUG_RAMDISK_TARGET) \
@@ -1899,6 +1902,11 @@
 ndk: $(SOONG_OUT_DIR)/ndk.timestamp
 .PHONY: ndk
 
+# Checks that build/soong/apex/allowed_deps.txt remains up to date
+ifneq ($(UNSAFE_DISABLE_APEX_ALLOWED_DEPS_CHECK),true)
+  droidcore: ${APEX_ALLOWED_DEPS_CHECK}
+endif
+
 $(call dist-write-file,$(KATI_PACKAGE_MK_DIR)/dist.mk)
 
 $(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] writing build rules ...)
diff --git a/core/product.mk b/core/product.mk
index 666e390..5f06141 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -120,7 +120,7 @@
 # The resoure configuration options to use for this product.
 _product_list_vars += PRODUCT_LOCALES
 _product_list_vars += PRODUCT_AAPT_CONFIG
-_product_list_vars += PRODUCT_AAPT_PREF_CONFIG
+_product_single_value_vars += PRODUCT_AAPT_PREF_CONFIG
 _product_list_vars += PRODUCT_AAPT_PREBUILT_DPI
 _product_list_vars += PRODUCT_HOST_PACKAGES
 _product_list_vars += PRODUCT_PACKAGES
@@ -209,7 +209,7 @@
 _product_list_vars += PRODUCT_SOONG_NAMESPACES
 
 _product_list_vars += PRODUCT_DEFAULT_WIFI_CHANNELS
-_product_list_vars += PRODUCT_DEFAULT_DEV_CERTIFICATE
+_product_single_value_vars += PRODUCT_DEFAULT_DEV_CERTIFICATE
 _product_list_vars += PRODUCT_MAINLINE_SEPOLICY_DEV_CERTIFICATES
 _product_list_vars += PRODUCT_RESTRICT_VENDOR_FILES
 
@@ -233,7 +233,7 @@
 # List of system_server jars delivered via apex. Format = <apex name>:<jar name>.
 _product_list_vars += PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS
 # If true, then suboptimal order of system server jars does not cause an error.
-_product_list_vars += PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS
+_product_single_value_vars += PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS
 
 # Additional system server jars to be appended at the end of the common list.
 # This is necessary to avoid jars reordering due to makefile inheritance order.
@@ -258,13 +258,13 @@
 
 # Per-module dex-preopt configs.
 _product_list_vars += PRODUCT_DEX_PREOPT_MODULE_CONFIGS
-_product_list_vars += PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
+_product_single_value_vars += PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
 _product_list_vars += PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
-_product_list_vars += PRODUCT_DEX_PREOPT_BOOT_FLAGS
-_product_list_vars += PRODUCT_DEX_PREOPT_PROFILE_DIR
-_product_list_vars += PRODUCT_DEX_PREOPT_GENERATE_DM_FILES
-_product_list_vars += PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING
-_product_list_vars += PRODUCT_DEX_PREOPT_RESOLVE_STARTUP_STRINGS
+_product_single_value_vars += PRODUCT_DEX_PREOPT_BOOT_FLAGS
+_product_single_value_vars += PRODUCT_DEX_PREOPT_PROFILE_DIR
+_product_single_value_vars += PRODUCT_DEX_PREOPT_GENERATE_DM_FILES
+_product_single_value_vars += PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING
+_product_single_value_vars += PRODUCT_DEX_PREOPT_RESOLVE_STARTUP_STRINGS
 
 # Boot image options.
 _product_single_value_vars += \
@@ -272,7 +272,7 @@
     PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION \
     PRODUCT_USES_DEFAULT_ART_CONFIG \
 
-_product_list_vars += PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
+_product_single_value_vars += PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
 # Per-module sanitizer configs
 _product_list_vars += PRODUCT_SANITIZER_MODULE_CONFIGS
 _product_single_value_vars += PRODUCT_SYSTEM_BASE_FS_PATH
diff --git a/core/robolectric_test_config_template.xml b/core/robolectric_test_config_template.xml
index e79abd5..e62175f 100644
--- a/core/robolectric_test_config_template.xml
+++ b/core/robolectric_test_config_template.xml
@@ -15,8 +15,8 @@
 -->
 <!-- This test config file is auto-generated. -->
 <configuration description="Runs {MODULE}">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-junit" />
+    <option name="test-suite-tag" value="robolectric" />
+    <option name="test-suite-tag" value="robolectric-tests" />
 
     <option name="java-folder" value="prebuilts/jdk/jdk9/linux-x86/" />
     <option name="exclude-paths" value="java" />
diff --git a/core/soong_config.mk b/core/soong_config.mk
index c221c55..250efb2 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -1,7 +1,3 @@
-SOONG := $(SOONG_OUT_DIR)/soong
-SOONG_BOOTSTRAP := $(SOONG_OUT_DIR)/.soong.bootstrap
-SOONG_BUILD_NINJA := $(SOONG_OUT_DIR)/build.ninja
-SOONG_IN_MAKE := $(SOONG_OUT_DIR)/.soong.in_make
 SOONG_MAKEVARS_MK := $(SOONG_OUT_DIR)/make_vars-$(TARGET_PRODUCT).mk
 SOONG_VARIABLES := $(SOONG_OUT_DIR)/soong.variables
 SOONG_ANDROID_MK := $(SOONG_OUT_DIR)/Android-$(TARGET_PRODUCT).mk
@@ -42,6 +38,7 @@
 $(call add_json_bool, Unbundled_build,                   $(TARGET_BUILD_UNBUNDLED))
 $(call add_json_bool, Unbundled_build_apps,              $(TARGET_BUILD_APPS))
 $(call add_json_bool, Always_use_prebuilt_sdks,          $(TARGET_BUILD_USE_PREBUILT_SDKS))
+$(call add_json_bool, Skip_boot_jars_check,              $(SKIP_BOOT_JARS_CHECK))
 
 $(call add_json_bool, Debuggable,                        $(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 $(call add_json_bool, Eng,                               $(filter eng,$(TARGET_BUILD_VARIANT)))
@@ -213,6 +210,9 @@
 $(call add_json_bool, EnforceProductPartitionInterface,  $(PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE))
 $(call add_json_str,  DeviceCurrentApiLevelForVendorModules,  $(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES))
 
+$(call add_json_bool, EnforceInterPartitionJavaSdkLibrary, $(PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY))
+$(call add_json_list, InterPartitionJavaLibraryAllowList, $(PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST))
+
 $(call add_json_bool, InstallExtraFlattenedApexes, $(PRODUCT_INSTALL_EXTRA_FLATTENED_APEXES))
 
 $(call add_json_bool, BoardUsesRecoveryAsBoot, $(BOARD_USES_RECOVERY_AS_BOOT))
diff --git a/core/soong_rust_prebuilt.mk b/core/soong_rust_prebuilt.mk
index dea7340..4cfb01f 100644
--- a/core/soong_rust_prebuilt.mk
+++ b/core/soong_rust_prebuilt.mk
@@ -82,8 +82,19 @@
   endif
 endif
 
+create_coverage_zip :=
 
 ifeq ($(NATIVE_COVERAGE),true)
+   create_coverage_zip := true
+endif
+
+# Until Rust supports LLVM coverage, Soong assumes GCOV coverage in both cases.
+# Therefore we should create the coverage zip with the gcno files in this case as well.
+ifeq ($(CLANG_COVERAGE),true)
+   create_coverage_zip := true
+endif
+
+ifdef create_coverage_zip
   ifneq (,$(strip $(LOCAL_PREBUILT_COVERAGE_ARCHIVE)))
     $(eval $(call copy-one-file,$(LOCAL_PREBUILT_COVERAGE_ARCHIVE),$(intermediates)/$(LOCAL_MODULE).zip))
     ifneq ($(LOCAL_UNINSTALLABLE_MODULE),true)
diff --git a/core/sysprop.mk b/core/sysprop.mk
index fdefced..1c66281 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -68,7 +68,9 @@
 #       emitted to the output
 # $(4): list of variable names each of which contains name=value pairs
 # $(5): optional list of prop names to force remove from the output. Properties from both
-#       $(3) and (4) are affected.
+#       $(3) and (4) are affected
+# $(6): optional list of files to append at the end. The content of each file is emitted
+#       to the output
 define build-properties
 ALL_DEFAULT_INSTALLED_MODULES += $(2)
 
@@ -90,7 +92,7 @@
     $(eval _option := --allow-dup)\
 )
 
-$(2): $(POST_PROCESS_PROPS) $(INTERNAL_BUILD_ID_MAKEFILE) $(API_FINGERPRINT) $(3)
+$(2): $(POST_PROCESS_PROPS) $(INTERNAL_BUILD_ID_MAKEFILE) $(API_FINGERPRINT) $(3) $(6)
 	$(hide) echo Building $$@
 	$(hide) mkdir -p $$(dir $$@)
 	$(hide) rm -f $$@ && touch $$@
@@ -113,6 +115,10 @@
 	    )\
 	)
 	$(hide) $(POST_PROCESS_PROPS) $$(_option) $$@ $(5)
+	$(hide) $(foreach file,$(strip $(6)),\
+	    if [ -f "$(file)" ]; then\
+	        cat $(file) >> $$@;\
+	    fi;)
 	$(hide) echo "# end of file" >> $$@
 endef
 
@@ -265,19 +271,6 @@
 	        TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
 	        bash $(BUILDINFO_SH) > $@
 
-ifneq ($(PRODUCT_OEM_PROPERTIES),)
-import_oem_prop := $(call intermediates-dir-for,ETC,system_build_prop)/oem.prop
-
-$(import_oem_prop):
-	$(hide) echo "#" >> $@; \
-	        echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
-	        echo "#" >> $@;
-	$(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \
-	    echo "import /oem/oem.prop $(prop)" >> $@;)
-else
-import_oem_prop :=
-endif
-
 ifdef TARGET_SYSTEM_PROP
 system_prop_file := $(TARGET_SYSTEM_PROP)
 else
@@ -285,7 +278,6 @@
 endif
 
 _prop_files_ := \
-  $(import_oem_prop) \
   $(gen_from_buildinfo_sh) \
   $(system_prop_file)
 
@@ -311,9 +303,13 @@
 
 INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop
 
-$(eval $(call build-properties,system,$(INSTALLED_BUILD_PROP_TARGET),\
-$(_prop_files_),$(_prop_vars_),\
-$(_blacklist_names_)))
+$(eval $(call build-properties,\
+    system,\
+    $(INSTALLED_BUILD_PROP_TARGET),\
+    $(_prop_files_),\
+    $(_prop_vars_),\
+    $(_blacklist_names_),\
+    $(empty)))
 
 # -----------------------------------------------------------------
 # vendor/build.prop
@@ -349,7 +345,8 @@
     $(INSTALLED_VENDOR_BUILD_PROP_TARGET),\
     $(_prop_files_),\
     $(_prop_vars_),\
-    $(PRODUCT_VENDOR_PROPERTY_BLACKLIST)))
+    $(PRODUCT_VENDOR_PROPERTY_BLACKLIST),\
+    $(empty)))
 
 # -----------------------------------------------------------------
 # product/etc/build.prop
@@ -366,12 +363,29 @@
     PRODUCT_PRODUCT_PROPERTIES
 
 INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/etc/build.prop
+
+ifdef PRODUCT_OEM_PROPERTIES
+import_oem_prop := $(call intermediates-dir-for,ETC,import_oem_prop)/oem.prop
+
+$(import_oem_prop):
+	$(hide) echo "####################################" >> $@; \
+	        echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
+	        echo "####################################" >> $@;
+	$(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \
+	    echo "import /oem/oem.prop $(prop)" >> $@;)
+
+_footers_ := $(import_oem_prop)
+else
+_footers_ :=
+endif
+
 $(eval $(call build-properties,\
     product,\
     $(INSTALLED_PRODUCT_BUILD_PROP_TARGET),\
     $(_prop_files_),\
     $(_prop_vars_),\
-    $(empty)))
+    $(empty),\
+    $(_footers_)))
 
 # ----------------------------------------------------------------
 # odm/etc/build.prop
@@ -392,6 +406,7 @@
     $(INSTALLED_ODM_BUILD_PROP_TARGET),\
     $(_prop_files),\
     $(_prop_vars_),\
+    $(empty),\
     $(empty)))
 
 # ----------------------------------------------------------------
@@ -401,7 +416,11 @@
 INSTALLED_VENDOR_DLKM_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR_DLKM)/etc/build.prop
 $(eval $(call build-properties,\
     vendor_dlkm,\
-    $(INSTALLED_VENDOR_DLKM_BUILD_PROP_TARGET)))
+    $(INSTALLED_VENDOR_DLKM_BUILD_PROP_TARGET),\
+    $(empty),\
+    $(empty),\
+    $(empty),\
+    $(empty)))
 
 # ----------------------------------------------------------------
 # odm_dlkm/etc/build.prop
@@ -410,7 +429,11 @@
 INSTALLED_ODM_DLKM_BUILD_PROP_TARGET := $(TARGET_OUT_ODM_DLKM)/etc/build.prop
 $(eval $(call build-properties,\
     odm_dlkm,\
-    $(INSTALLED_ODM_DLKM_BUILD_PROP_TARGET)))
+    $(INSTALLED_ODM_DLKM_BUILD_PROP_TARGET),\
+    $(empty),\
+    $(empty),\
+    $(empty),\
+    $(empty)))
 
 # -----------------------------------------------------------------
 # system_ext/etc/build.prop
@@ -429,6 +452,7 @@
     $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET),\
     $(_prop_files_),\
     $(_prop_vars_),\
+    $(empty),\
     $(empty)))
 
 # ----------------------------------------------------------------
@@ -439,4 +463,8 @@
 INSTALLED_RAMDISK_BUILD_PROP_TARGET := $(TARGET_RAMDISK_OUT)/$(RAMDISK_BUILD_PROP_REL_PATH)
 $(eval $(call build-properties,\
     bootimage,\
-    $(INSTALLED_RAMDISK_BUILD_PROP_TARGET)))
+    $(INSTALLED_RAMDISK_BUILD_PROP_TARGET),\
+    $(empty),\
+    $(empty),\
+    $(empty),\
+    $(empty)))
diff --git a/core/tasks/boot_jars_package_check.mk b/core/tasks/boot_jars_package_check.mk
deleted file mode 100644
index baa378a..0000000
--- a/core/tasks/boot_jars_package_check.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright (C) 2014 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.
-
-#
-# Rules to check if classes in the boot jars are from the list of allowed packages.
-#
-
-ifneq ($(SKIP_BOOT_JARS_CHECK),true)
-ifdef PRODUCT_BOOT_JARS
-
-intermediates := $(call intermediates-dir-for, PACKAGING, boot-jars-package-check,,COMMON)
-stamp := $(intermediates)/stamp
-
-# Convert the colon-separated components <apex>:<jar> to <jar>.<apex> names
-# (e.g. com.android.media:updatable-media -> updatable-media.com.android.media).
-# Special cases:
-#   - for the "platform" or "system_ext" apex drop the .<apex> suffix
-boot_jars := $(foreach pair,$(PRODUCT_BOOT_JARS) $(PRODUCT_UPDATABLE_BOOT_JARS), \
-  $(eval apex := $(call word-colon,1,$(pair))) \
-  $(eval jar := $(call word-colon,2,$(pair))) \
-  $(eval q := :) \
-  $(eval sfx := $(q).$(apex)$(q)) \
-  $(eval sfx := $(subst $(q).platform$(q),$(q)$(q),$(sfx))) \
-  $(eval sfx := $(subst $(q).system_ext$(q),$(q)$(q),$(sfx))) \
-  $(eval sfx := $(patsubst $(q)%$(q),%,$(sfx))) \
-  $(jar)$(sfx))
-
-# Convert boot jar names to build paths.
-built_boot_jars := $(foreach j, $(boot_jars), \
-  $(call intermediates-dir-for, JAVA_LIBRARIES, $(j),,COMMON)/classes.jar)
-
-script := build/make/core/tasks/check_boot_jars/check_boot_jars.py
-allowed_file := build/make/core/tasks/check_boot_jars/package_allowed_list.txt
-
-$(stamp): PRIVATE_BOOT_JARS := $(built_boot_jars)
-$(stamp): PRIVATE_SCRIPT := $(script)
-$(stamp): PRIVATE_ALLOWED := $(allowed_file)
-$(stamp) : $(built_boot_jars) $(script) $(allowed_file)
-	@echo "Check package name for $(PRIVATE_BOOT_JARS)"
-	$(hide) $(PRIVATE_SCRIPT) $(PRIVATE_ALLOWED) $(PRIVATE_BOOT_JARS)
-	$(hide) mkdir -p $(dir $@) && touch $@
-
-.PHONY: check-boot-jars
-check-boot-jars : $(stamp)
-
-# Run check-boot-jars by default
-droidcore : check-boot-jars
-
-endif  # PRODUCT_BOOT_JARS
-endif  # SKIP_BOOT_JARS_CHECK not true
diff --git a/core/tasks/check_boot_jars/check_boot_jars.py b/core/tasks/check_boot_jars/check_boot_jars.py
deleted file mode 100755
index cf4ef27..0000000
--- a/core/tasks/check_boot_jars/check_boot_jars.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-
-"""
-Check boot jars.
-
-Usage: check_boot_jars.py <package_allow_list_file> <jar1> <jar2> ...
-"""
-import logging
-import os.path
-import re
-import subprocess
-import sys
-
-
-# The compiled allow list RE.
-allow_list_re = None
-
-
-def LoadAllowList(filename):
-  """ Load and compile allow list regular expressions from filename.
-  """
-  lines = []
-  with open(filename, 'r') as f:
-    for line in f:
-      line = line.strip()
-      if not line or line.startswith('#'):
-        continue
-      lines.append(line)
-  combined_re = r'^(%s)$' % '|'.join(lines)
-  global allow_list_re
-  try:
-    allow_list_re = re.compile(combined_re)
-  except re.error:
-    logging.exception(
-        'Cannot compile package allow list regular expression: %r',
-        combined_re)
-    allow_list_re = None
-    return False
-  return True
-
-
-def CheckJar(allow_list_path, jar):
-  """Check a jar file.
-  """
-  # Get the list of files inside the jar file.
-  p = subprocess.Popen(args='jar tf %s' % jar,
-      stdout=subprocess.PIPE, shell=True)
-  stdout, _ = p.communicate()
-  if p.returncode != 0:
-    return False
-  items = stdout.split()
-  classes = 0
-  for f in items:
-    if f.endswith('.class'):
-      classes += 1
-      package_name = os.path.dirname(f)
-      package_name = package_name.replace('/', '.')
-      if not package_name or not allow_list_re.match(package_name):
-        print >> sys.stderr, ('Error: %s contains class file %s, whose package name %s is empty or'
-                              ' not in the allow list %s of packages allowed on the bootclasspath.'
-                              % (jar, f, package_name, allow_list_path))
-        return False
-  if classes == 0:
-    print >> sys.stderr, ('Error: %s does not contain any class files.' % jar)
-    return False
-  return True
-
-
-def main(argv):
-  if len(argv) < 2:
-    print __doc__
-    return 1
-  allow_list_path = argv[0]
-
-  if not LoadAllowList(allow_list_path):
-    return 1
-
-  passed = True
-  for jar in argv[1:]:
-    if not CheckJar(allow_list_path, jar):
-      passed = False
-  if not passed:
-    return 1
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
diff --git a/core/tasks/check_boot_jars/package_allowed_list.txt b/core/tasks/check_boot_jars/package_allowed_list.txt
deleted file mode 100644
index 18ab427..0000000
--- a/core/tasks/check_boot_jars/package_allowed_list.txt
+++ /dev/null
@@ -1,248 +0,0 @@
-# Boot jar package name allowed list.
-# Each line is interpreted as a regular expression.
-
-###################################################
-# core-libart.jar & core-oj.jar
-java\.awt\.font
-java\.beans
-java\.io
-java\.lang
-java\.lang\.annotation
-java\.lang\.invoke
-java\.lang\.ref
-java\.lang\.reflect
-java\.math
-java\.net
-java\.nio
-java\.nio\.file
-java\.nio\.file\.spi
-java\.nio\.file\.attribute
-java\.nio\.channels
-java\.nio\.channels\.spi
-java\.nio\.charset
-java\.nio\.charset\.spi
-java\.security
-java\.security\.acl
-java\.security\.cert
-java\.security\.interfaces
-java\.security\.spec
-java\.sql
-java\.text
-java\.text\.spi
-java\.time
-java\.time\.chrono
-java\.time\.format
-java\.time\.temporal
-java\.time\.zone
-java\.util
-java\.util\.concurrent
-java\.util\.concurrent\.atomic
-java\.util\.concurrent\.locks
-java\.util\.function
-java\.util\.jar
-java\.util\.logging
-java\.util\.prefs
-java\.util\.regex
-java\.util\.spi
-java\.util\.stream
-java\.util\.zip
-# TODO: Remove javax.annotation.processing if possible, see http://b/132338110:
-javax\.annotation\.processing
-javax\.crypto
-javax\.crypto\.interfaces
-javax\.crypto\.spec
-javax\.net
-javax\.net\.ssl
-javax\.security\.auth
-javax\.security\.auth\.callback
-javax\.security\.auth\.login
-javax\.security\.auth\.x500
-javax\.security\.cert
-javax\.sql
-javax\.xml
-javax\.xml\.datatype
-javax\.xml\.namespace
-javax\.xml\.parsers
-javax\.xml\.transform
-javax\.xml\.transform\.dom
-javax\.xml\.transform\.sax
-javax\.xml\.transform\.stream
-javax\.xml\.validation
-javax\.xml\.xpath
-jdk\.internal\.util
-jdk\.internal\.vm\.annotation
-jdk\.net
-org\.w3c\.dom
-org\.w3c\.dom\.ls
-org\.w3c\.dom\.traversal
-# OpenJdk internal implementation.
-sun\.invoke\.util
-sun\.invoke\.empty
-sun\.misc
-sun\.util.*
-sun\.text.*
-sun\.security.*
-sun\.reflect.*
-sun\.nio.*
-sun\.net.*
-com\.sun\..*
-
-# TODO: Move these internal org.apache.harmony classes to libcore.*
-org\.apache\.harmony\.crypto\.internal
-org\.apache\.harmony\.dalvik
-org\.apache\.harmony\.dalvik\.ddmc
-org\.apache\.harmony\.luni\.internal\.util
-org\.apache\.harmony\.security
-org\.apache\.harmony\.security\.asn1
-org\.apache\.harmony\.security\.fortress
-org\.apache\.harmony\.security\.pkcs10
-org\.apache\.harmony\.security\.pkcs7
-org\.apache\.harmony\.security\.pkcs8
-org\.apache\.harmony\.security\.provider\.crypto
-org\.apache\.harmony\.security\.utils
-org\.apache\.harmony\.security\.x501
-org\.apache\.harmony\.security\.x509
-org\.apache\.harmony\.security\.x509\.tsp
-org\.apache\.harmony\.xml
-org\.apache\.harmony\.xml\.dom
-org\.apache\.harmony\.xml\.parsers
-
-org\.json
-org\.xmlpull\.v1
-org\.xmlpull\.v1\.sax2
-
-# TODO:  jarjar org.kxml2.io to com.android org\.kxml2\.io
-org\.kxml2\.io
-org\.xml
-org\.xml\.sax
-org\.xml\.sax\.ext
-org\.xml\.sax\.helpers
-
-dalvik\..*
-libcore\..*
-android\..*
-com\.android\..*
-###################################################
-# android.test.base.jar
-junit\.extensions
-junit\.framework
-android\.test
-android\.test\.suitebuilder\.annotation
-
-
-###################################################
-# ext.jar
-# TODO: jarjar javax.sip to com.android
-javax\.sip
-javax\.sip\.address
-javax\.sip\.header
-javax\.sip\.message
-
-# TODO: jarjar org.apache.commons to com.android
-org\.apache\.commons\.codec
-org\.apache\.commons\.codec\.binary
-org\.apache\.commons\.codec\.language
-org\.apache\.commons\.codec\.net
-org\.apache\.commons\.logging
-org\.apache\.commons\.logging\.impl
-org\.apache\.http
-org\.apache\.http\.auth
-org\.apache\.http\.auth\.params
-org\.apache\.http\.client
-org\.apache\.http\.client\.entity
-org\.apache\.http\.client\.methods
-org\.apache\.http\.client\.params
-org\.apache\.http\.client\.protocol
-org\.apache\.http\.client\.utils
-org\.apache\.http\.conn
-org\.apache\.http\.conn\.params
-org\.apache\.http\.conn\.routing
-org\.apache\.http\.conn\.scheme
-org\.apache\.http\.conn\.ssl
-org\.apache\.http\.conn\.util
-org\.apache\.http\.cookie
-org\.apache\.http\.cookie\.params
-org\.apache\.http\.entity
-org\.apache\.http\.impl
-org\.apache\.http\.impl\.auth
-org\.apache\.http\.impl\.client
-org\.apache\.http\.impl\.client
-org\.apache\.http\.impl\.conn
-org\.apache\.http\.impl\.conn\.tsccm
-org\.apache\.http\.impl\.cookie
-org\.apache\.http\.impl\.entity
-org\.apache\.http\.impl\.io
-org\.apache\.http\.impl\.io
-org\.apache\.http\.io
-org\.apache\.http\.message
-org\.apache\.http\.params
-org\.apache\.http\.protocol
-org\.apache\.http\.util
-
-# TODO: jarjar gov.nist to com.android
-gov\.nist\.core
-gov\.nist\.core\.net
-gov\.nist\.javax\.sip
-gov\.nist\.javax\.sip\.address
-gov\.nist\.javax\.sip\.clientauthutils
-gov\.nist\.javax\.sip\.header
-gov\.nist\.javax\.sip\.header\.extensions
-gov\.nist\.javax\.sip\.header\.ims
-gov\.nist\.javax\.sip\.message
-gov\.nist\.javax\.sip\.parser
-gov\.nist\.javax\.sip\.parser\.extensions
-gov\.nist\.javax\.sip\.parser\.ims
-gov\.nist\.javax\.sip\.stack
-
-org\.ccil\.cowan\.tagsoup
-org\.ccil\.cowan\.tagsoup\.jaxp
-
-###################################################
-# framework.jar
-javax\.microedition\.khronos\.opengles
-javax\.microedition\.khronos\.egl
-
-android
-
-###################################################
-# apache-xml.jar
-org\.apache\.xml\.res
-org\.apache\.xml\.utils
-org\.apache\.xml\.utils\.res
-org\.apache\.xml\.dtm
-org\.apache\.xml\.dtm\.ref
-org\.apache\.xml\.dtm\.ref\.dom2dtm
-org\.apache\.xml\.dtm\.ref\.sax2dtm
-org\.apache\.xml\.serializer
-org\.apache\.xml\.serializer\.utils
-org\.apache\.xml\.serializer\.dom3
-org\.apache\.xpath
-org\.apache\.xpath\.operations
-org\.apache\.xpath\.domapi
-org\.apache\.xpath\.functions
-org\.apache\.xpath\.res
-org\.apache\.xpath\.axes
-org\.apache\.xpath\.objects
-org\.apache\.xpath\.patterns
-org\.apache\.xpath\.jaxp
-org\.apache\.xpath\.compiler
-org\.apache\.xalan
-org\.apache\.xalan\.res
-org\.apache\.xalan\.templates
-org\.apache\.xalan\.serialize
-org\.apache\.xalan\.extensions
-org\.apache\.xalan\.processor
-org\.apache\.xalan\.transformer
-org\.apache\.xalan\.xslt
-
-###################################################
-# Packages in the google namespace across all bootclasspath jars.
-com\.google\.android\..*
-com\.google\.vr\.platform.*
-com\.google\.i18n\.phonenumbers\..*
-com\.google\.i18n\.phonenumbers
-
-###################################################
-# Packages used for Android in Chrome OS
-org\.chromium\.arc
-org\.chromium\.arc\..*
diff --git a/core/tasks/find-shareduid-violation.mk b/core/tasks/find-shareduid-violation.mk
index 972b1ec..d6885eb 100644
--- a/core/tasks/find-shareduid-violation.mk
+++ b/core/tasks/find-shareduid-violation.mk
@@ -16,8 +16,6 @@
 
 shareduid_violation_modules_filename := $(PRODUCT_OUT)/shareduid_violation_modules.json
 
-find_shareduid_script := $(BUILD_SYSTEM)/tasks/find-shareduid-violation.py
-
 $(shareduid_violation_modules_filename): $(INSTALLED_SYSTEMIMAGE_TARGET) \
     $(INSTALLED_RAMDISK_TARGET) \
     $(INSTALLED_BOOTIMAGE_TARGET) \
@@ -26,9 +24,9 @@
     $(INSTALLED_PRODUCTIMAGE_TARGET) \
     $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
 
-$(shareduid_violation_modules_filename): $(find_shareduid_script)
+$(shareduid_violation_modules_filename): $(HOST_OUT_EXECUTABLES)/find_shareduid_violation
 $(shareduid_violation_modules_filename): $(AAPT2)
-	$(find_shareduid_script) \
+	$(HOST_OUT_EXECUTABLES)/find_shareduid_violation \
 		--product_out $(PRODUCT_OUT) \
 		--aapt $(AAPT2) \
 		--copy_out_system $(TARGET_COPY_OUT_SYSTEM) \
diff --git a/core/tasks/find-shareduid-violation.py b/core/tasks/find-shareduid-violation.py
deleted file mode 100755
index 8dba5a1..0000000
--- a/core/tasks/find-shareduid-violation.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import argparse
-import json
-import os
-import subprocess
-import sys
-
-from collections import defaultdict
-from glob import glob
-
-def parse_args():
-    """Parse commandline arguments."""
-    parser = argparse.ArgumentParser(description='Find sharedUserId violators')
-    parser.add_argument('--product_out', help='PRODUCT_OUT directory',
-                        default=os.environ.get("PRODUCT_OUT"))
-    parser.add_argument('--aapt', help='Path to aapt or aapt2',
-                        default="aapt2")
-    parser.add_argument('--copy_out_system', help='TARGET_COPY_OUT_SYSTEM',
-                        default="system")
-    parser.add_argument('--copy_out_vendor', help='TARGET_COPY_OUT_VENDOR',
-                        default="vendor")
-    parser.add_argument('--copy_out_product', help='TARGET_COPY_OUT_PRODUCT',
-                        default="product")
-    parser.add_argument('--copy_out_system_ext', help='TARGET_COPY_OUT_SYSTEM_EXT',
-                        default="system_ext")
-    return parser.parse_args()
-
-def execute(cmd):
-    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    out, err = map(lambda b: b.decode('utf-8'), p.communicate())
-    return p.returncode == 0, out, err
-
-def make_aapt_cmds(file):
-    return [aapt + ' dump ' + file + ' --file AndroidManifest.xml',
-            aapt + ' dump xmltree ' + file + ' --file AndroidManifest.xml']
-
-def extract_shared_uid(file):
-    for cmd in make_aapt_cmds(file):
-        success, manifest, error_msg = execute(cmd)
-        if success:
-            break
-    else:
-        print(error_msg, file=sys.stderr)
-        sys.exit()
-
-    for l in manifest.split('\n'):
-        if "sharedUserId" in l:
-            return l.split('"')[-2]
-    return None
-
-
-args = parse_args()
-
-product_out = args.product_out
-aapt = args.aapt
-
-partitions = (
-        ("system", args.copy_out_system),
-        ("vendor", args.copy_out_vendor),
-        ("product", args.copy_out_product),
-        ("system_ext", args.copy_out_system_ext),
-)
-
-shareduid_app_dict = defaultdict(list)
-
-for part, location in partitions:
-    for f in glob(os.path.join(product_out, location, "*", "*", "*.apk")):
-        apk_file = os.path.basename(f)
-        shared_uid = extract_shared_uid(f)
-
-        if shared_uid is None:
-            continue
-        shareduid_app_dict[shared_uid].append((part, apk_file))
-
-
-output = defaultdict(lambda: defaultdict(list))
-
-for uid, app_infos in shareduid_app_dict.items():
-    partitions = {p for p, _ in app_infos}
-    if len(partitions) > 1:
-        for part in partitions:
-            output[uid][part].extend([a for p, a in app_infos if p == part])
-
-print(json.dumps(output, indent=2, sort_keys=True))
diff --git a/core/tasks/host-unit-tests.mk b/core/tasks/host-unit-tests.mk
new file mode 100644
index 0000000..755b589
--- /dev/null
+++ b/core/tasks/host-unit-tests.mk
@@ -0,0 +1,50 @@
+# 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.
+
+# `host-unit-tests` shall only include hostside unittest that don't require a device to run. Tests
+# included will be run as part of presubmit check.
+# To add tests to the suite, do one of the following:
+# * For test modules configured with Android.bp, set attribute `test_options: { unit_test: true }`
+# * For test modules configured with mk, set `LOCAL_IS_UNIT_TEST := true`
+.PHONY: host-unit-tests
+
+intermediates_dir := $(call intermediates-dir-for,PACKAGING,host-unit-tests)
+host_unit_tests_zip := $(PRODUCT_OUT)/host-unit-tests.zip
+# Get the hostside libraries to be packaged in the test zip. Unlike
+# device-tests.mk or general-tests.mk, the files are not copied to the
+# testcases directory.
+my_host_shared_lib_for_host_unit_tests := $(foreach f,$(COMPATIBILITY.host-unit-tests.HOST_SHARED_LIBRARY.FILES),$(strip \
+    $(eval _cmf_tuple := $(subst :, ,$(f))) \
+    $(eval _cmf_src := $(word 1,$(_cmf_tuple))) \
+    $(_cmf_src)))
+
+$(host_unit_tests_zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_host_unit_tests)
+
+$(host_unit_tests_zip) : $(COMPATIBILITY.host-unit-tests.FILES) $(my_host_shared_lib_for_host_unit_tests) $(SOONG_ZIP)
+	echo $(sort $(COMPATIBILITY.host-unit-tests.FILES)) | tr " " "\n" > $@.list
+	grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
+	echo "" >> $@-host-libs.list
+	$(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
+	  echo $$shared_lib >> $@-host-libs.list; \
+	done
+	grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
+	$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list \
+	  -P target -C $(PRODUCT_OUT) -l $@-target.list \
+	  -P host/testcases -C $(HOST_OUT) -l $@-host-libs.list
+	rm -f $@.list $@-host.list $@-target.list $@-host-libs.list
+
+host-unit-tests: $(host_unit_tests_zip)
+$(call dist-for-goals, host-unit-tests, $(host_unit_tests_zip))
+
+tests: host-unit-tests
diff --git a/core/tasks/host_init_verifier.mk b/core/tasks/host_init_verifier.mk
new file mode 100644
index 0000000..bdf996c
--- /dev/null
+++ b/core/tasks/host_init_verifier.mk
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+
+host_init_verifier_output := $(PRODUCT_OUT)/host_init_verifier_output.txt
+
+$(host_init_verifier_output): \
+    $(INSTALLED_SYSTEMIMAGE_TARGET) \
+    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
+    $(INSTALLED_VENDORIMAGE_TARGET) \
+    $(INSTALLED_ODMIMAGE_TARGET) \
+    $(INSTALLED_PRODUCTIMAGE_TARGET) \
+    $(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+    $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
+    $(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
+    $(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
+    $(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
+    $(call intermediates-dir-for,ETC,plat_property_contexts)/plat_property_contexts \
+    $(call intermediates-dir-for,ETC,system_ext_property_contexts)/system_ext_property_contexts \
+    $(call intermediates-dir-for,ETC,product_property_contexts)/product_property_contexts \
+    $(call intermediates-dir-for,ETC,vendor_property_contexts)/vendor_property_contexts \
+    $(call intermediates-dir-for,ETC,odm_property_contexts)/odm_property_contexts
+
+# Run host_init_verifier on the partition staging directories.
+$(host_init_verifier_output): $(HOST_INIT_VERIFIER)
+	$(HOST_INIT_VERIFIER) \
+		-p $(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+		-p $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
+		-p $(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
+		-p $(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
+		-p $(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
+		--property-contexts=$(call intermediates-dir-for,ETC,plat_property_contexts)/plat_property_contexts \
+		--property-contexts=$(call intermediates-dir-for,ETC,system_ext_property_contexts)/system_ext_property_contexts \
+		--property-contexts=$(call intermediates-dir-for,ETC,product_property_contexts)/product_property_contexts \
+		--property-contexts=$(call intermediates-dir-for,ETC,vendor_property_contexts)/vendor_property_contexts \
+		--property-contexts=$(call intermediates-dir-for,ETC,odm_property_contexts)/odm_property_contexts \
+		--out_system $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM) \
+		--out_system_ext $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_EXT) \
+		--out_vendor $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR) \
+		--out_odm $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ODM) \
+		--out_product $(PRODUCT_OUT)/$(TARGET_COPY_OUT_PRODUCT) \
+		> $@
+
+$(call dist-for-goals,droidcore,$(host_init_verifier_output))
diff --git a/core/tasks/mts.mk b/core/tasks/mts.mk
index e800505..e084856 100644
--- a/core/tasks/mts.mk
+++ b/core/tasks/mts.mk
@@ -13,13 +13,20 @@
 # limitations under the License.
 
 ifneq ($(wildcard test/mts/README.md),)
-test_suite_name := mts
-test_suite_tradefed := mts-tradefed
-test_suite_readme := test/mts/README.md
 
-include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
+mts_test_suites :=
+mts_test_suites += mts
 
-.PHONY: mts
-mts: $(compatibility_zip)
-$(call dist-for-goals, mts, $(compatibility_zip))
+$(foreach module, $(mts_modules), $(eval mts_test_suites += mts-$(module)))
+
+$(foreach suite, $(mts_test_suites), \
+	$(eval test_suite_name := $(suite)) \
+	$(eval test_suite_tradefed := mts-tradefed) \
+	$(eval test_suite_readme := test/mts/README.md) \
+	$(eval include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk) \
+	$(eval .PHONY: $(suite)) \
+	$(eval $(suite): $(compatibility_zip)) \
+	$(eval $(call dist-for-goals, $(suite), $(compatibility_zip))) \
+)
+
 endif
diff --git a/core/tasks/platform_availability_check.mk b/core/tasks/platform_availability_check.mk
index 7ce6b40..1524758 100644
--- a/core/tasks/platform_availability_check.mk
+++ b/core/tasks/platform_availability_check.mk
@@ -17,6 +17,9 @@
 # Check whether there is any module that isn't available for platform
 # is installed to the platform.
 
+# Skip for unbundled builds that don't produce a platform image.
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+
 # Filter FAKE and NON_INSTALLABLE modules out and then collect those are not
 # available for platform
 _modules_not_available_for_platform := \
@@ -41,7 +44,7 @@
 # Don't error out immediately when ALLOW_MISSING_DEPENDENCIES is set.
 # Instead, add a dependency on a rule that prints the error message.
   define not_available_for_platform_rule
-    not_installable_file := $(patsubst $(OUT_DIR)/%,$(OUT_DIR)/NOT_AVAILABLE_FOR_PLATFORM/%,$(1)))
+    not_installable_file := $(patsubst $(OUT_DIR)/%,$(OUT_DIR)/NOT_AVAILABLE_FOR_PLATFORM/%,$(1))
     $(1): $$(not_installable_file)
     $$(not_installable_file):
 	$(call echo-error,$(2),Module is requested to be installed but is not \
@@ -54,3 +57,5 @@
     $(foreach i,$(filter-out $(HOST_OUT)/%,$(ALL_MODULES.$(m).INSTALLED)),\
       $(eval $(call not_available_for_platform_rule,$(i),$(m)))))
 endif
+
+endif
diff --git a/core/tasks/recovery_snapshot.mk b/core/tasks/recovery_snapshot.mk
new file mode 100644
index 0000000..fea0bb9
--- /dev/null
+++ b/core/tasks/recovery_snapshot.mk
@@ -0,0 +1,34 @@
+# 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.
+
+current_makefile := $(lastword $(MAKEFILE_LIST))
+
+# BOARD_VNDK_VERSION must be set to 'current' in order to generate a recovery snapshot.
+ifeq ($(BOARD_VNDK_VERSION),current)
+
+.PHONY: recovery-snapshot
+recovery-snapshot: $(SOONG_RECOVERY_SNAPSHOT_ZIP)
+
+$(call dist-for-goals, recovery-snapshot, $(SOONG_RECOVERY_SNAPSHOT_ZIP))
+
+else # BOARD_VNDK_VERSION is NOT set to 'current'
+
+.PHONY: recovery-snapshot
+recovery-snapshot: PRIVATE_MAKEFILE := $(current_makefile)
+recovery-snapshot:
+	$(call echo-error,$(PRIVATE_MAKEFILE),\
+		"CANNOT generate Recovery snapshot. BOARD_VNDK_VERSION must be set to 'current'.")
+	exit 1
+
+endif # BOARD_VNDK_VERSION
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 41696e8..7362275 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -240,7 +240,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 := 2020-10-05
+      PLATFORM_SECURITY_PATCH := 2020-11-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
diff --git a/envsetup.sh b/envsetup.sh
index 82c4565..a2d5d1d 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -307,6 +307,9 @@
     unset ANDROID_HOST_OUT
     export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
 
+    unset ANDROID_SOONG_HOST_OUT
+    export ANDROID_SOONG_HOST_OUT=$(get_abs_build_var SOONG_HOST_OUT)
+
     unset ANDROID_HOST_OUT_TESTCASES
     export ANDROID_HOST_OUT_TESTCASES=$(get_abs_build_var HOST_OUT_TESTCASES)
 
@@ -318,7 +321,7 @@
     #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
 }
 
-function abazel()
+function bazel()
 {
     local T="$(gettop)"
     if [ ! "$T" ]; then
@@ -326,49 +329,12 @@
         return
     fi
 
-    case $(uname -s) in
-        Darwin)
-            ANDROID_BAZEL_PATH="${T}/prebuilts/bazel/darwin-x86_64/bazel"
-            ANDROID_BAZELRC_PATH="${T}/build/bazel/darwin.bazelrc"
-            ANDROID_BAZEL_JDK_PATH="${T}/prebuilts/jdk/jdk11/darwin-x86"
-            ;;
-        Linux)
-            ANDROID_BAZEL_PATH="${T}/prebuilts/bazel/linux-x86_64/bazel"
-            ANDROID_BAZELRC_PATH="${T}/build/bazel/linux.bazelrc"
-            ANDROID_BAZEL_JDK_PATH="${T}/prebuilts/jdk/jdk11/linux-x86"
-            ;;
-        *)
-            ANDROID_BAZEL_PATH=
-            ANDROID_BAZELRC_PATH=
-            ANDROID_BAZEL_JDK_PATH=
-            ;;
-    esac
-
-    if [ -n "$ANDROID_BAZEL_PATH" -a -f "$ANDROID_BAZEL_PATH" ]; then
-        export ANDROID_BAZEL_PATH
-    else
-        echo "Couldn't locate Bazel binary"
-        return
+    if which bazel &>/dev/null; then
+        echo "NOTE: bazel() function sourced from envsetup.sh is being used instead of $(which bazel)"
+        echo
     fi
 
-    if [ -n "$ANDROID_BAZELRC_PATH" -a -f "$ANDROID_BAZELRC_PATH" ]; then
-        export ANDROID_BAZELRC_PATH
-    else
-        echo "Couldn't locate bazelrc file for Bazel"
-        return
-    fi
-
-    if [ -n "$ANDROID_BAZEL_JDK_PATH" -a -d "$ANDROID_BAZEL_JDK_PATH" ]; then
-        export ANDROID_BAZEL_JDK_PATH
-    else
-        echo "Couldn't locate JDK to use for Bazel"
-        return
-    fi
-
-    echo "WARNING: Bazel support for the Android Platform is experimental and is undergoing development."
-    echo "WARNING: Currently, build stability is not guaranteed. Thank you."
-    echo
-    "${ANDROID_BAZEL_PATH}" --server_javabase="${ANDROID_BAZEL_JDK_PATH}" --bazelrc="${ANDROID_BAZELRC_PATH}" "$@"
+    "$T/tools/bazel" "$@"
 }
 
 function printconfig()
@@ -1408,7 +1374,7 @@
     mkdir -p $ANDROID_PRODUCT_OUT || return 1
 
     # Note, can't use absolute path because of the way make works.
-    m out/target/product/$(get_build_var TARGET_DEVICE)/module-info.json \
+    m $(get_build_var PRODUCT_OUT)/module-info.json \
         > $ANDROID_PRODUCT_OUT/module-info.json.build.log 2>&1
 }
 
diff --git a/rbesetup.sh b/rbesetup.sh
index 0182bfd..ec39e6e 100644
--- a/rbesetup.sh
+++ b/rbesetup.sh
@@ -65,7 +65,11 @@
 function _set_rbe_vars() {
   unset USE_GOMA
   export USE_RBE="true"
-  export RBE_CXX_EXEC_STRATEGY="remote_local_fallback"
+  export RBE_CXX_EXEC_STRATEGY="racing"
+  export RBE_JAVAC_EXEC_STRATEGY="racing"
+  export RBE_R8_EXEC_STRATEGY="racing"
+  export RBE_D8_EXEC_STRATEGY="racing"
+  export RBE_use_unified_cas_ops="true"
   export RBE_JAVAC=1
   export RBE_R8=1
   export RBE_D8=1
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index 07b07ce..6b2291f 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -77,6 +77,7 @@
 BOARD_BOOT_HEADER_VERSION := 3
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
 BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 0x06000000
+BOARD_RAMDISK_USE_LZ4 := true
 
 # Enable chain partition for system.
 BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 42660e5..414e032 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -54,9 +54,6 @@
 
 include build/make/target/board/BoardConfigGsiCommon.mk
 
-TARGET_NO_KERNEL := false
-BOARD_USES_RECOVERY_AS_BOOT := true
-
 BOARD_KERNEL-4.19-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
 BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
 BOARD_KERNEL-5.4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
@@ -79,7 +76,21 @@
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 BOARD_KERNEL_BINARIES += kernel-5.4-allsyms kernel-5.4-gz-allsyms kernel-5.4-lz4-allsyms
 endif
+
+# Boot image
+BOARD_USES_RECOVERY_AS_BOOT :=
+TARGET_NO_KERNEL := false
+BOARD_USES_GENERIC_KERNEL_IMAGE := true
 BOARD_KERNEL_MODULE_INTERFACE_VERSIONS := 5.4-android12-0
+# Copy boot image in $OUT to target files. This is defined for targets where
+# the installed GKI APEXes are built from source.
+BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES := true
+
+# No vendor_boot
+BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
+
+# No recovery
+BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
 
 # Some vendors still haven't cleaned up all device specific directories under
 # root!
diff --git a/target/board/generic_arm64/README.txt b/target/board/generic_arm64/README.txt
index 21c71d7..8711a14 100644
--- a/target/board/generic_arm64/README.txt
+++ b/target/board/generic_arm64/README.txt
@@ -1,5 +1,7 @@
 The "generic_arm64" product defines a non-hardware-specific arm64 target
-without a kernel or bootloader.
+without a bootloader.
+
+It is also the target to build the generic kernel image (GKI).
 
 It is not a product "base class"; no other products inherit
 from it or use it in any way.
diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk
index 866d7c7..7b16aea 100644
--- a/target/board/generic_arm64/device.mk
+++ b/target/board/generic_arm64/device.mk
@@ -30,4 +30,7 @@
     kernel/prebuilts/5.4/arm64/kernel-5.4-lz4:kernel-5.4-lz4-allsyms
 endif
 
+PRODUCT_PACKAGES += e2fsck_ramdisk
+
 PRODUCT_BUILD_VENDOR_BOOT_IMAGE := false
+PRODUCT_BUILD_RECOVERY_IMAGE := false
diff --git a/target/board/generic_arm64/sepolicy/OWNERS b/target/board/generic_arm64/sepolicy/OWNERS
index ff29677..6dc2b86 100644
--- a/target/board/generic_arm64/sepolicy/OWNERS
+++ b/target/board/generic_arm64/sepolicy/OWNERS
@@ -1,8 +1 @@
-alanstokes@google.com
-bowgotsai@google.com
-jbires@google.com
-jeffv@google.com
-jgalenson@google.com
-sspatil@google.com
-tomcherry@google.com
-trong@google.com
+include platform/system/sepolicy:/OWNERS
diff --git a/target/board/generic_arm64_ab/BoardConfig.mk b/target/board/generic_arm64_ab/BoardConfig.mk
deleted file mode 100644
index 7c91607..0000000
--- a/target/board/generic_arm64_ab/BoardConfig.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_ABI := arm64-v8a
-TARGET_CPU_ABI2 :=
-TARGET_CPU_VARIANT := generic
-
-TARGET_2ND_ARCH := arm
-TARGET_2ND_ARCH_VARIANT := armv8-a
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_CPU_VARIANT := generic
-
-# TODO(jiyong) These might be SoC specific.
-BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
-
-# TODO(b/36764215): remove this setting when the generic system image
-# no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64/sepolicy
diff --git a/target/board/generic_arm_ab/BoardConfig.mk b/target/board/generic_arm_ab/BoardConfig.mk
deleted file mode 100644
index 21b763c..0000000
--- a/target/board/generic_arm_ab/BoardConfig.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm
-TARGET_ARCH_VARIANT := armv7-a-neon
-TARGET_CPU_ABI := armeabi-v7a
-TARGET_CPU_ABI2 := armeabi
-TARGET_CPU_VARIANT := generic
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
-
-# TODO(jiyong) These might be SoC specific.
-BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
-
-# TODO(b/36764215): remove this setting when the generic system image
-# no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64/sepolicy
diff --git a/target/board/generic_x86_64_ab/BoardConfig.mk b/target/board/generic_x86_64_ab/BoardConfig.mk
deleted file mode 100644
index 1dd5e48..0000000
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_CPU_ABI := x86_64
-TARGET_ARCH := x86_64
-TARGET_ARCH_VARIANT := x86_64
-
-TARGET_2ND_CPU_ABI := x86
-TARGET_2ND_ARCH := x86
-TARGET_2ND_ARCH_VARIANT := x86_64
diff --git a/target/board/generic_x86_ab/BoardConfig.mk b/target/board/generic_x86_ab/BoardConfig.mk
deleted file mode 100644
index 53acffd..0000000
--- a/target/board/generic_x86_ab/BoardConfig.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_CPU_ABI := x86
-TARGET_ARCH := x86
-TARGET_ARCH_VARIANT := x86
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
diff --git a/target/board/mainline_arm64/sepolicy/OWNERS b/target/board/mainline_arm64/sepolicy/OWNERS
index ff29677..6dc2b86 100644
--- a/target/board/mainline_arm64/sepolicy/OWNERS
+++ b/target/board/mainline_arm64/sepolicy/OWNERS
@@ -1,8 +1 @@
-alanstokes@google.com
-bowgotsai@google.com
-jbires@google.com
-jeffv@google.com
-jgalenson@google.com
-sspatil@google.com
-tomcherry@google.com
-trong@google.com
+include platform/system/sepolicy:/OWNERS
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 61a7583..5094149 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -44,13 +44,9 @@
 else
 PRODUCT_MAKEFILES := \
     $(LOCAL_DIR)/aosp_64bitonly_x86_64.mk \
-    $(LOCAL_DIR)/aosp_arm64_ab.mk \
     $(LOCAL_DIR)/aosp_arm64.mk \
-    $(LOCAL_DIR)/aosp_arm_ab.mk \
     $(LOCAL_DIR)/aosp_arm.mk \
-    $(LOCAL_DIR)/aosp_x86_64_ab.mk \
     $(LOCAL_DIR)/aosp_x86_64.mk \
-    $(LOCAL_DIR)/aosp_x86_ab.mk \
     $(LOCAL_DIR)/aosp_x86_arm.mk \
     $(LOCAL_DIR)/aosp_x86.mk \
     $(LOCAL_DIR)/full.mk \
diff --git a/target/product/aosp_arm64_ab.mk b/target/product/aosp_arm64_ab.mk
deleted file mode 100644
index 5510e1b..0000000
--- a/target/product/aosp_arm64_ab.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_arm64_ab-userdebug is a Legacy GSI for the devices with:
-# - ARM 64 bits user space
-# - 64 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (The system image of Legacy GSI is not CSI)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_arm64_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# All components inherited here go to system_ext image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_arm64_ab
-PRODUCT_DEVICE := generic_arm64_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM64
diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk
deleted file mode 100644
index 7e06044..0000000
--- a/target/product/aosp_arm_ab.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_arm_ab-userdebug is a Legacy GSI for the devices with:
-# - ARM 32 bits user space
-# - 32 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (The system image of Legacy GSI is not CSI)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_arm_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# All components inherited here go to system_ext image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_arm_ab
-PRODUCT_DEVICE := generic_arm_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM32
diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk
deleted file mode 100644
index c31545d..0000000
--- a/target/product/aosp_x86_64_ab.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_x86_64_ab-userdebug is a Legacy GSI for the devices with:
-# - x86 64 bits user space
-# - 64 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (The system image of Legacy GSI is not CSI)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_x86_64_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# All components inherited here go to system_ext image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_x86_64_ab
-PRODUCT_DEVICE := generic_x86_64_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86_64
diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk
deleted file mode 100644
index 2f02dd1..0000000
--- a/target/product/aosp_x86_ab.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_x86_ab-userdebug is a Legacy GSI for the devices with:
-# - x86 32 bits user space
-# - 32 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (The system image of Legacy GSI is not CSI)
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_x86_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# All components inherited here go to system_ext image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_x86_ab
-PRODUCT_DEVICE := generic_x86_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 1a28cf0..1b4c8d9 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -117,6 +117,7 @@
     ip-up-vpn \
     javax.obex \
     keystore \
+    keystore2 \
     credstore \
     ld.mc \
     libaaudio \
@@ -248,6 +249,7 @@
     shell_and_utilities_system \
     sm \
     snapshotctl \
+    snapuserd \
     SoundPicker \
     storaged \
     surfaceflinger \
@@ -321,45 +323,12 @@
     tz_version_host \
     tz_version_host_tzdata_apex \
 
-ifeq ($(ART_APEX_JARS),)
-$(error ART_APEX_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
-endif
-
-# The order matters for runtime class lookup performance.
-PRODUCT_BOOT_JARS := \
-    $(ART_APEX_JARS) \
-    framework-minus-apex \
-    ext \
-    com.android.i18n:core-icu4j \
-    telephony-common \
-    voip-common \
-    ims-common
-
-PRODUCT_UPDATABLE_BOOT_JARS := \
-    com.android.conscrypt:conscrypt \
-    com.android.media:updatable-media \
-    com.android.mediaprovider:framework-mediaprovider \
-    com.android.os.statsd:framework-statsd \
-    com.android.permission:framework-permission \
-    com.android.sdkext:framework-sdkextensions \
-    com.android.wifi:framework-wifi \
-    com.android.tethering:framework-tethering
 
 PRODUCT_COPY_FILES += \
     system/core/rootdir/init.usb.rc:system/etc/init/hw/init.usb.rc \
     system/core/rootdir/init.usb.configfs.rc:system/etc/init/hw/init.usb.configfs.rc \
     system/core/rootdir/etc/hosts:system/etc/hosts
 
-# Add the compatibility library that is needed when android.test.base
-# is removed from the bootclasspath.
-# Default to excluding android.test.base from the bootclasspath.
-ifneq ($(REMOVE_ATB_FROM_BCP),false)
-PRODUCT_PACKAGES += framework-atb-backward-compatibility
-PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
-else
-PRODUCT_BOOT_JARS += android.test.base
-endif
-
 PRODUCT_COPY_FILES += system/core/rootdir/init.zygote32.rc:system/etc/init/hw/init.zygote32.rc
 PRODUCT_SYSTEM_PROPERTIES += ro.zygote?=zygote32
 
@@ -372,6 +341,7 @@
 PRODUCT_PACKAGES_DEBUG := \
     adb_keys \
     arping \
+    dmuserd \
     gdbserver \
     idlcli \
     init-debug.rc \
@@ -381,6 +351,8 @@
     logpersist.start \
     logtagd.rc \
     procrank \
+    profcollectd \
+    profcollectctl \
     remount \
     showmap \
     sqlite3 \
@@ -417,4 +389,5 @@
 PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\
     frameworks/base/config/dirty-image-objects:system/etc/dirty-image-objects)
 
+$(call inherit-product, $(SRC_TARGET_DIR)/product/bootclasspath.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
diff --git a/target/product/bootclasspath.mk b/target/product/bootclasspath.mk
new file mode 100644
index 0000000..60dd071
--- /dev/null
+++ b/target/product/bootclasspath.mk
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+ifeq ($(ART_APEX_JARS),)
+  $(error ART_APEX_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
+endif
+
+# The order matters for runtime class lookup performance.
+PRODUCT_BOOT_JARS := \
+    $(ART_APEX_JARS) \
+    framework-minus-apex \
+    ext \
+    com.android.i18n:core-icu4j \
+    telephony-common \
+    voip-common \
+    ims-common
+
+PRODUCT_UPDATABLE_BOOT_JARS := \
+    com.android.conscrypt:conscrypt \
+    com.android.media:updatable-media \
+    com.android.mediaprovider:framework-mediaprovider \
+    com.android.os.statsd:framework-statsd \
+    com.android.permission:framework-permission \
+    com.android.sdkext:framework-sdkextensions \
+    com.android.wifi:framework-wifi \
+    com.android.tethering:framework-tethering
+
+# Add the compatibility library that is needed when android.test.base
+# is removed from the bootclasspath.
+# Default to excluding android.test.base from the bootclasspath.
+ifneq ($(REMOVE_ATB_FROM_BCP),false)
+  PRODUCT_PACKAGES += framework-atb-backward-compatibility
+  PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
+else
+  PRODUCT_BOOT_JARS += android.test.base
+endif
diff --git a/target/product/cfi-common.mk b/target/product/cfi-common.mk
index 42edd92..623a9a8 100644
--- a/target/product/cfi-common.mk
+++ b/target/product/cfi-common.mk
@@ -17,6 +17,7 @@
 # This is a set of common components to enable CFI for (across
 # compatible product configs)
 PRODUCT_CFI_INCLUDE_PATHS :=  \
+    device/generic/goldfish/wifi/wpa_supplicant_8_lib \
     device/google/cuttlefish/guest/libs/wpa_supplicant_8_lib \
     device/google/wahoo/wifi_offload \
     external/tinyxml2 \
@@ -28,7 +29,8 @@
     hardware/broadcom/wlan/bcmdhd/wpa_supplicant_8_lib \
     hardware/interfaces/nfc \
     hardware/qcom/wlan/qcwcn/wpa_supplicant_8_lib \
-    harware/interfaces/keymaster \
+    hardware/interfaces/keymaster \
+    hardware/interfaces/keymint \
     system/bt \
     system/chre \
     system/core/libnetutils \
diff --git a/target/product/generic_x86.mk b/target/product/generic_x86.mk
index 0274b5b..eeb8216 100644
--- a/target/product/generic_x86.mk
+++ b/target/product/generic_x86.mk
@@ -17,7 +17,7 @@
 # This is a generic phone product that isn't specialized for a specific device.
 # It includes the base Android platform.
 
-include $(SRC_TARGET_DIR)/product/generic.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
 
 # Overrides
 PRODUCT_BRAND := generic_x86
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index f057958..9c08e5e 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -43,6 +43,7 @@
 VNDK-SP: libc++.so
 VNDK-SP: libcompiler_rt.so
 VNDK-SP: libcutils.so
+VNDK-SP: libdmabufheap.so
 VNDK-SP: libgralloctypes.so
 VNDK-SP: libhardware.so
 VNDK-SP: libhidlbase.so
@@ -68,6 +69,7 @@
 VNDK-core: android.hardware.graphics.bufferqueue@2.0.so
 VNDK-core: android.hardware.identity-V2-ndk_platform.so
 VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
+VNDK-core: android.hardware.keymint-V1-ndk_platform.so
 VNDK-core: android.hardware.light-V1-ndk_platform.so
 VNDK-core: android.hardware.media.bufferpool@2.0.so
 VNDK-core: android.hardware.media.omx@1.0.so
diff --git a/target/product/legacy_gsi_release.mk b/target/product/legacy_gsi_release.mk
deleted file mode 100644
index 09b96fb..0000000
--- a/target/product/legacy_gsi_release.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# 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.
-#
-
-include $(SRC_TARGET_DIR)/product/gsi_release.mk
-
-# Legacy GSI support additional O-MR1 interface
-PRODUCT_EXTRA_VNDK_VERSIONS += 27
-
-# Legacy GSI relax the compatible property checking
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := false
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index 63671dc..9096ff3 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -50,8 +50,8 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_x86/device.mk)
 
 # Define the host tools and libs that are parts of the SDK.
--include sdk/build/product_sdk.mk
--include development/build/product_sdk.mk
+$(call inherit-product-if-exists, sdk/build/product_sdk.mk)
+$(call inherit-product-if-exists, development/build/product_sdk.mk)
 
 # Overrides
 PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index c5a6245..161043b 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -51,8 +51,8 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_x86_64/device.mk)
 
 # Define the host tools and libs that are parts of the SDK.
--include sdk/build/product_sdk.mk
--include development/build/product_sdk.mk
+$(call inherit-product-if-exists, sdk/build/product_sdk.mk)
+$(call inherit-product-if-exists, development/build/product_sdk.mk)
 
 # Overrides
 PRODUCT_BRAND := Android
diff --git a/target/product/virtual_ab_ota.mk b/target/product/virtual_ab_ota.mk
new file mode 120000
index 0000000..16f7329
--- /dev/null
+++ b/target/product/virtual_ab_ota.mk
@@ -0,0 +1 @@
+virtual_ab_ota/launch.mk
\ No newline at end of file
diff --git a/target/product/virtual_ab_ota/README.md b/target/product/virtual_ab_ota/README.md
new file mode 100644
index 0000000..2d40c03
--- /dev/null
+++ b/target/product/virtual_ab_ota/README.md
@@ -0,0 +1,16 @@
+# Virtual A/B makefiles
+
+Devices that uses Virtual A/B must inherit from one of the makefiles in this directory.
+
+## Structure
+
+```
+launch.mk
+  |- retrofit.mk
+  |- plus_non_ab.mk
+
+launch_with_vendor_ramdisk.mk
+  |- compression.mk
+
+compression_retrofit.mk
+```
diff --git a/target/product/virtual_ab_ota_retrofit_compression.mk b/target/product/virtual_ab_ota/compression.mk
similarity index 88%
rename from target/product/virtual_ab_ota_retrofit_compression.mk
rename to target/product/virtual_ab_ota/compression.mk
index 8059f75..1dd8643 100644
--- a/target/product/virtual_ab_ota_retrofit_compression.mk
+++ b/target/product/virtual_ab_ota/compression.mk
@@ -14,9 +14,8 @@
 # limitations under the License.
 #
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk)
 
 PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
 
-PRODUCT_PACKAGES += snapuserd_ramdisk
-
+PRODUCT_PACKAGES += snapuserd.vendor_ramdisk snapuserd
diff --git a/target/product/virtual_ab_ota_retrofit_compression.mk b/target/product/virtual_ab_ota/compression_retrofit.mk
similarity index 66%
copy from target/product/virtual_ab_ota_retrofit_compression.mk
copy to target/product/virtual_ab_ota/compression_retrofit.mk
index 8059f75..b34e3f1 100644
--- a/target/product/virtual_ab_ota_retrofit_compression.mk
+++ b/target/product/virtual_ab_ota/compression_retrofit.mk
@@ -14,9 +14,11 @@
 # limitations under the License.
 #
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
-
 PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
 
-PRODUCT_PACKAGES += snapuserd_ramdisk
-
+# For devices that are not GKI-capable (eg do not have vendor_boot),
+# snapuserd.ramdisk is included rather than snapuserd.vendor_ramdisk.
+# When using virtual_ab_ota_compression_retrofit.mk, either
+# virtual_ab_ota.mk or virtual_ab_ota_retrofit.mk must be inherited
+# as well.
+PRODUCT_PACKAGES += snapuserd.ramdisk snapuserd
diff --git a/target/product/virtual_ab_ota.mk b/target/product/virtual_ab_ota/launch.mk
similarity index 100%
rename from target/product/virtual_ab_ota.mk
rename to target/product/virtual_ab_ota/launch.mk
diff --git a/target/product/virtual_ab_ota_retrofit_compression.mk b/target/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk
similarity index 66%
copy from target/product/virtual_ab_ota_retrofit_compression.mk
copy to target/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk
index 8059f75..bc81b33 100644
--- a/target/product/virtual_ab_ota_retrofit_compression.mk
+++ b/target/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk
@@ -14,9 +14,13 @@
 # limitations under the License.
 #
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
+# Devices launching with Virtual A/B and has a vendor_boot partition is
+# preferred to inherit from this makefile instead of launch.mk.
 
-PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
+PRODUCT_VIRTUAL_AB_OTA := true
 
-PRODUCT_PACKAGES += snapuserd_ramdisk
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.enabled=true
 
+PRODUCT_PACKAGES += \
+    linker.vendor_ramdisk \
+    e2fsck.vendor_ramdisk \
diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota/plus_non_ab.mk
similarity index 97%
rename from target/product/virtual_ab_ota_plus_non_ab.mk
rename to target/product/virtual_ab_ota/plus_non_ab.mk
index 99a10ed..820fa1e 100644
--- a/target/product/virtual_ab_ota_plus_non_ab.mk
+++ b/target/product/virtual_ab_ota/plus_non_ab.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch.mk)
 
 PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true
 
diff --git a/target/product/virtual_ab_ota_retrofit.mk b/target/product/virtual_ab_ota/retrofit.mk
similarity index 97%
rename from target/product/virtual_ab_ota_retrofit.mk
rename to target/product/virtual_ab_ota/retrofit.mk
index 3416a4f..93b42b7 100644
--- a/target/product/virtual_ab_ota_retrofit.mk
+++ b/target/product/virtual_ab_ota/retrofit.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch.mk)
 
 PRODUCT_VIRTUAL_AB_OTA_RETROFIT := true
 
diff --git a/target/product/virtual_ab_ota_compression.mk b/target/product/virtual_ab_ota_compression.mk
deleted file mode 100644
index c4849be..0000000
--- a/target/product/virtual_ab_ota_compression.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# 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_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
-
-PRODUCT_PACKAGES += snapuserd_ramdisk
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 120000
index 0000000..4979957
--- /dev/null
+++ b/target/product/virtual_ab_ota_plus_non_ab.mk
@@ -0,0 +1 @@
+virtual_ab_ota/plus_non_ab.mk
\ No newline at end of file
diff --git a/target/product/virtual_ab_ota_retrofit.mk b/target/product/virtual_ab_ota_retrofit.mk
new file mode 120000
index 0000000..1e16ca8
--- /dev/null
+++ b/target/product/virtual_ab_ota_retrofit.mk
@@ -0,0 +1 @@
+virtual_ab_ota/retrofit.mk
\ No newline at end of file
diff --git a/tools/fs_config/fs_config.go b/tools/fs_config/fs_config.go
index 16bcefa..4c324fb 100644
--- a/tools/fs_config/fs_config.go
+++ b/tools/fs_config/fs_config.go
@@ -48,10 +48,10 @@
 		path := android.PathForModuleGen(ctx, "empty")
 		t.paths = android.Paths{path}
 
-		rule := android.NewRuleBuilder()
+		rule := android.NewRuleBuilder(pctx, ctx)
 		rule.Command().Text("rm -rf").Output(path)
 		rule.Command().Text("touch").Output(path)
-		rule.Build(pctx, ctx, "fs_config_empty", "create empty file")
+		rule.Build("fs_config_empty", "create empty file")
 	}
 }
 
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
index 940a398..098fde6 100755
--- a/tools/fs_config/fs_config_generator.py
+++ b/tools/fs_config/fs_config_generator.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 """Generates config files for Android file system properties.
 
 This script is used for generating configuration files for configuring
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index e1543e7..cafc2bb 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -49,6 +49,7 @@
     required: [
         "blk_alloc_to_base_fs",
         "e2fsck",
+        "mkerofsimage.sh",
         "mkuserimg_mke2fs",
         "simg2img",
         "tune2fs",
@@ -368,6 +369,32 @@
     ],
 }
 
+python_defaults {
+    name: "releasetools_find_shareduid_violation_defaults",
+    srcs: [
+        "find_shareduid_violation.py",
+    ],
+    libs: [
+        "releasetools_common",
+    ],
+}
+
+python_binary_host {
+    name: "find_shareduid_violation",
+    defaults: [
+        "releasetools_binary_defaults",
+        "releasetools_find_shareduid_violation_defaults",
+    ],
+}
+
+python_library_host {
+    name: "releasetools_find_shareduid_violation",
+    defaults: [
+        "releasetools_find_shareduid_violation_defaults",
+        "releasetools_library_defaults",
+    ],
+}
+
 python_binary_host {
     name: "make_recovery_patch",
     defaults: ["releasetools_binary_defaults"],
@@ -402,11 +429,13 @@
         "releasetools_build_super_image",
         "releasetools_check_target_files_vintf",
         "releasetools_common",
+        "releasetools_find_shareduid_violation",
         "releasetools_img_from_target_files",
         "releasetools_ota_from_target_files",
     ],
     required: [
         "checkvintf",
+        "host_init_verifier",
     ],
     target: {
         darwin: {
@@ -504,6 +533,7 @@
         "releasetools_build_super_image",
         "releasetools_check_target_files_vintf",
         "releasetools_common",
+        "releasetools_find_shareduid_violation",
         "releasetools_img_from_target_files",
         "releasetools_ota_from_target_files",
         "releasetools_verity_utils",
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index eb041ec..d836d65 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -959,8 +959,9 @@
           if item not in vbmeta_vendor.split()]
       vbmeta_partitions.append("vbmeta_vendor")
 
-    banner("vbmeta")
-    AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
+    if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
+      banner("vbmeta")
+      AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
 
   if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
     banner("super_empty")
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 169a112..6487b9b 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -296,6 +296,18 @@
       build_command.extend(["--inode_size", "256"])
     if "selinux_fc" in prop_dict:
       build_command.append(prop_dict["selinux_fc"])
+  elif fs_type.startswith("erofs"):
+    build_command = ["mkerofsimage.sh"]
+    build_command.extend([in_dir, out_file])
+    if "erofs_sparse_flag" in prop_dict:
+      build_command.extend([prop_dict["erofs_sparse_flag"]])
+    build_command.extend(["-m", prop_dict["mount_point"]])
+    if target_out:
+      build_command.extend(["-d", target_out])
+    if fs_config:
+      build_command.extend(["-C", fs_config])
+    if "selinux_fc" in prop_dict:
+      build_command.extend(["-c", prop_dict["selinux_fc"]])
   elif fs_type.startswith("squash"):
     build_command = ["mksquashfsimage.sh"]
     build_command.extend([in_dir, out_file])
@@ -532,6 +544,7 @@
 
   common_props = (
       "extfs_sparse_flag",
+      "erofs_sparse_flag",
       "squashfs_sparse_flag",
       "f2fs_sparse_flag",
       "skip_fsck",
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index 3c2406c..a2ddfe7 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -100,10 +100,7 @@
                 'PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is not set')
     return []
 
-  with open(version_path) as f:
-    version = f.read().strip()
-
-  return ['--kernel', '{}:{}'.format(version, config_path)]
+  return ['--kernel', '{}:{}'.format(version_path, config_path)]
 
 
 def CheckVintfFromExtractedTargetFiles(input_tmp, info_dict=None):
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 5e70af1..bae0b20 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -217,6 +217,25 @@
 def SetHostToolLocation(tool_name, location):
   OPTIONS.host_tools[tool_name] = location
 
+def FindHostToolPath(tool_name):
+  """Finds the path to the host tool.
+
+  Args:
+    tool_name: name of the tool to find
+  Returns:
+    path to the tool if found under either one of the host_tools map or under
+    the same directory as this binary is located at. If not found, tool_name
+    is returned.
+  """
+  if tool_name in OPTIONS.host_tools:
+    return OPTIONS.host_tools[tool_name]
+
+  my_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
+  tool_path = os.path.join(my_dir, tool_name)
+  if os.path.exists(tool_path):
+    return tool_path
+
+  return tool_name
 
 def Run(args, verbose=None, **kwargs):
   """Creates and returns a subprocess.Popen object.
@@ -240,12 +259,10 @@
   if 'universal_newlines' not in kwargs:
     kwargs['universal_newlines'] = True
 
-  # If explicitly set host tool location before, use that location to avoid
-  # PATH violation. Make a copy of args in case client relies on the content
-  # of args later.
-  if args and args[0] in OPTIONS.host_tools:
+  if args:
+    # Make a copy of args in case client relies on the content of args later.
     args = args[:]
-    args[0] = OPTIONS.host_tools[args[0]]
+    args[0] = FindHostToolPath(args[0])
 
   # Don't log any if caller explicitly says so.
   if verbose:
@@ -1085,6 +1102,91 @@
   return merged_dict
 
 
+def PartitionMapFromTargetFiles(target_files_dir):
+  """Builds a map from partition -> path within an extracted target files directory."""
+  # Keep possible_subdirs in sync with build/make/core/board_config.mk.
+  possible_subdirs = {
+      "system": ["SYSTEM"],
+      "vendor": ["VENDOR", "SYSTEM/vendor"],
+      "product": ["PRODUCT", "SYSTEM/product"],
+      "system_ext": ["SYSTEM_EXT", "SYSTEM/system_ext"],
+      "odm": ["ODM", "VENDOR/odm", "SYSTEM/vendor/odm"],
+      "vendor_dlkm": [
+          "VENDOR_DLKM", "VENDOR/vendor_dlkm", "SYSTEM/vendor/vendor_dlkm"
+      ],
+      "odm_dlkm": ["ODM_DLKM", "VENDOR/odm_dlkm", "SYSTEM/vendor/odm_dlkm"],
+  }
+  partition_map = {}
+  for partition, subdirs in possible_subdirs.items():
+    for subdir in subdirs:
+      if os.path.exists(os.path.join(target_files_dir, subdir)):
+        partition_map[partition] = subdir
+        break
+  return partition_map
+
+
+def SharedUidPartitionViolations(uid_dict, partition_groups):
+  """Checks for APK sharedUserIds that cross partition group boundaries.
+
+  This uses a single or merged build's shareduid_violation_modules.json
+  output file, as generated by find_shareduid_violation.py or
+  core/tasks/find-shareduid-violation.mk.
+
+  An error is defined as a sharedUserId that is found in a set of partitions
+  that span more than one partition group.
+
+  Args:
+    uid_dict: A dictionary created by using the standard json module to read a
+      complete shareduid_violation_modules.json file.
+    partition_groups: A list of groups, where each group is a list of
+      partitions.
+
+  Returns:
+    A list of error messages.
+  """
+  errors = []
+  for uid, partitions in uid_dict.items():
+    found_in_groups = [
+        group for group in partition_groups
+        if set(partitions.keys()) & set(group)
+    ]
+    if len(found_in_groups) > 1:
+      errors.append(
+          "APK sharedUserId \"%s\" found across partition groups in partitions \"%s\""
+          % (uid, ",".join(sorted(partitions.keys()))))
+  return errors
+
+
+def RunHostInitVerifier(product_out, partition_map):
+  """Runs host_init_verifier on the init rc files within partitions.
+
+  host_init_verifier searches the etc/init path within each partition.
+
+  Args:
+    product_out: PRODUCT_OUT directory, containing partition directories.
+    partition_map: A map of partition name -> relative path within product_out.
+  """
+  allowed_partitions = ("system", "system_ext", "product", "vendor", "odm")
+  cmd = ["host_init_verifier"]
+  for partition, path in partition_map.items():
+    if partition not in allowed_partitions:
+      raise ExternalError("Unable to call host_init_verifier for partition %s" %
+                          partition)
+    cmd.extend(["--out_%s" % partition, os.path.join(product_out, path)])
+    # Add --property-contexts if the file exists on the partition.
+    property_contexts = "%s_property_contexts" % (
+        "plat" if partition == "system" else partition)
+    property_contexts_path = os.path.join(product_out, path, "etc", "selinux",
+                                          property_contexts)
+    if os.path.exists(property_contexts_path):
+      cmd.append("--property-contexts=%s" % property_contexts_path)
+    # Add the passwd file if the file exists on the partition.
+    passwd_path = os.path.join(product_out, path, "etc", "passwd")
+    if os.path.exists(passwd_path):
+      cmd.extend(["-p", passwd_path])
+  return RunAndCheckOutput(cmd)
+
+
 def AppendAVBSigningArgs(cmd, partition):
   """Append signing arguments for avbtool."""
   # e.g., "--key path/to/signing_key --algorithm SHA256_RSA4096"
diff --git a/tools/releasetools/find_shareduid_violation.py b/tools/releasetools/find_shareduid_violation.py
new file mode 100755
index 0000000..35acde3
--- /dev/null
+++ b/tools/releasetools/find_shareduid_violation.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Find APK sharedUserId violators.
+
+Usage: find_shareduid_violation [args]
+
+  --product_out
+    PRODUCT_OUT directory
+
+  --aapt
+    Path to aapt or aapt2
+
+  --copy_out_system
+    TARGET_COPY_OUT_SYSTEM
+
+  --copy_out_vendor_
+    TARGET_COPY_OUT_VENDOR
+
+  --copy_out_product
+    TARGET_COPY_OUT_PRODUCT
+
+  --copy_out_system_ext
+    TARGET_COPY_OUT_SYSTEM_EXT
+"""
+
+import json
+import logging
+import os
+import re
+import subprocess
+import sys
+
+from collections import defaultdict
+from glob import glob
+
+import common
+
+logger = logging.getLogger(__name__)
+
+OPTIONS = common.OPTIONS
+OPTIONS.product_out = os.environ.get("PRODUCT_OUT")
+OPTIONS.aapt = "aapt2"
+OPTIONS.copy_out_system = "system"
+OPTIONS.copy_out_vendor = "vendor"
+OPTIONS.copy_out_product = "product"
+OPTIONS.copy_out_system_ext = "system_ext"
+
+
+def execute(cmd):
+  p = subprocess.Popen(
+      cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  out, err = map(lambda b: b.decode("utf-8"), p.communicate())
+  return p.returncode == 0, out, err
+
+
+def make_aapt_cmds(aapt, apk):
+  return [
+      aapt + " dump " + apk + " --file AndroidManifest.xml",
+      aapt + " dump xmltree " + apk + " --file AndroidManifest.xml"
+  ]
+
+
+def extract_shared_uid(aapt, apk):
+  for cmd in make_aapt_cmds(aapt, apk):
+    success, manifest, error_msg = execute(cmd)
+    if success:
+      break
+  else:
+    logger.error(error_msg)
+    sys.exit()
+
+  pattern = re.compile(r"sharedUserId.*=\"([^\"]*)")
+
+  for line in manifest.split("\n"):
+    match = pattern.search(line)
+    if match:
+      return match.group(1)
+  return None
+
+
+def FindShareduidViolation(product_out, partition_map, aapt="aapt2"):
+  """Find sharedUserId violators in the given partitions.
+
+  Args:
+    product_out: The base directory containing the partition directories.
+    partition_map: A map of partition name -> directory name.
+    aapt: The name of the aapt binary. Defaults to aapt2.
+
+  Returns:
+    A string containing a JSON object describing the shared UIDs.
+  """
+  shareduid_app_dict = defaultdict(lambda: defaultdict(list))
+
+  for part, location in partition_map.items():
+    for f in glob(os.path.join(product_out, location, "*", "*", "*.apk")):
+      apk_file = os.path.basename(f)
+      shared_uid = extract_shared_uid(aapt, f)
+
+      if shared_uid is None:
+        continue
+      shareduid_app_dict[shared_uid][part].append(apk_file)
+
+  # Only output sharedUserId values that appear in >1 partition.
+  output = {}
+  for uid, partitions in shareduid_app_dict.items():
+    if len(partitions) > 1:
+      output[uid] = shareduid_app_dict[uid]
+
+  return json.dumps(output, indent=2, sort_keys=True)
+
+
+def main():
+  common.InitLogging()
+
+  def option_handler(o, a):
+    if o == "--product_out":
+      OPTIONS.product_out = a
+    elif o == "--aapt":
+      OPTIONS.aapt = a
+    elif o == "--copy_out_system":
+      OPTIONS.copy_out_system = a
+    elif o == "--copy_out_vendor":
+      OPTIONS.copy_out_vendor = a
+    elif o == "--copy_out_product":
+      OPTIONS.copy_out_product = a
+    elif o == "--copy_out_system_ext":
+      OPTIONS.copy_out_system_ext = a
+    else:
+      return False
+    return True
+
+  args = common.ParseOptions(
+      sys.argv[1:],
+      __doc__,
+      extra_long_opts=[
+          "product_out=",
+          "aapt=",
+          "copy_out_system=",
+          "copy_out_vendor=",
+          "copy_out_product=",
+          "copy_out_system_ext=",
+      ],
+      extra_option_handler=option_handler)
+
+  if args:
+    common.Usage(__doc__)
+    sys.exit(1)
+
+  partition_map = {
+      "system": OPTIONS.copy_out_system,
+      "vendor": OPTIONS.copy_out_vendor,
+      "product": OPTIONS.copy_out_product,
+      "system_ext": OPTIONS.copy_out_system_ext,
+  }
+
+  print(
+      FindShareduidViolation(OPTIONS.product_out, partition_map, OPTIONS.aapt))
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 2da5cc0..9360d7b 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -85,6 +85,7 @@
 from __future__ import print_function
 
 import fnmatch
+import json
 import logging
 import os
 import re
@@ -98,6 +99,7 @@
 import check_target_files_vintf
 import common
 import img_from_target_files
+import find_shareduid_violation
 import ota_from_target_files
 
 logger = logging.getLogger(__name__)
@@ -454,6 +456,12 @@
     # false in the partial builds to prevent duplicate building of super.img.
     merged_dict['build_super_partition'] = 'true'
 
+  # If AVB is enabled then ensure that we build vbmeta.img.
+  # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to
+  # skip building an incomplete vbmeta.img.
+  if merged_dict.get('avb_enable') == 'true':
+    merged_dict['avb_building_vbmeta_image'] = 'true'
+
   # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
   # depending on which dictionary the key came from.
   # Only the file basename is required because all selinux_fc properties are
@@ -943,6 +951,43 @@
   if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
     raise RuntimeError('Incompatible VINTF metadata')
 
+  partition_map = common.PartitionMapFromTargetFiles(
+      output_target_files_temp_dir)
+
+  # Generate and check for cross-partition violations of sharedUserId
+  # values in APKs. This requires the input target-files packages to contain
+  # *.apk files.
+  shareduid_violation_modules = os.path.join(
+      output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
+  with open(shareduid_violation_modules, 'w') as f:
+    violation = find_shareduid_violation.FindShareduidViolation(
+        output_target_files_temp_dir, partition_map)
+
+    # Write the output to a file to enable debugging.
+    f.write(violation)
+
+    # Check for violations across the input builds' partition groups.
+    framework_partitions = item_list_to_partition_set(framework_item_list)
+    vendor_partitions = item_list_to_partition_set(vendor_item_list)
+    shareduid_errors = common.SharedUidPartitionViolations(
+        json.loads(violation), [framework_partitions, vendor_partitions])
+    if shareduid_errors:
+      for error in shareduid_errors:
+        logger.error(error)
+      raise ValueError('sharedUserId APK error. See %s' %
+                       shareduid_violation_modules)
+
+  # Run host_init_verifier on the combined init rc files.
+  filtered_partitions = {
+      partition: path
+      for partition, path in partition_map.items()
+      # host_init_verifier checks only the following partitions:
+      if partition in ['system', 'system_ext', 'product', 'vendor', 'odm']
+  }
+  common.RunHostInitVerifier(
+      product_out=output_target_files_temp_dir,
+      partition_map=filtered_partitions)
+
   generate_images(output_target_files_temp_dir, rebuild_recovery)
 
   generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index fba43e9..6b82d32 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -217,10 +217,13 @@
 
 import logging
 import multiprocessing
+import os
 import os.path
+import re
 import shlex
 import shutil
 import struct
+import subprocess
 import sys
 import zipfile
 
@@ -266,6 +269,7 @@
 OPTIONS.skip_postinstall = False
 OPTIONS.skip_compatibility_check = False
 OPTIONS.disable_fec_computation = False
+OPTIONS.disable_verity_computation = False
 OPTIONS.partial = None
 OPTIONS.custom_images = {}
 
@@ -399,6 +403,8 @@
       cmd.extend(["--source_image", source_file])
       if OPTIONS.disable_fec_computation:
         cmd.extend(["--disable_fec_computation", "true"])
+      if OPTIONS.disable_verity_computation:
+        cmd.extend(["--disable_verity_computation", "true"])
     cmd.extend(additional_args)
     self._Run(cmd)
 
@@ -751,6 +757,9 @@
   common.ZipDelete(target_file, POSTINSTALL_CONFIG)
   return target_file
 
+def ParseInfoDict(target_file_path):
+  with zipfile.ZipFile(target_file_path, 'r', allowZip64=True) as zfp:
+    return common.LoadInfoDict(zfp)
 
 def GetTargetFilesZipForPartialUpdates(input_file, ab_partitions):
   """Returns a target-files.zip for partial ota update package generation.
@@ -781,7 +790,8 @@
     raise ValueError("Cannot find {} in input zipfile".format(partition_name))
 
   with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
-    original_ab_partitions = input_zip.read(AB_PARTITIONS).decode().splitlines()
+    original_ab_partitions = input_zip.read(
+        AB_PARTITIONS).decode().splitlines()
     namelist = input_zip.namelist()
 
   unrecognized_partitions = [partition for partition in ab_partitions if
@@ -871,7 +881,7 @@
   with open(new_ab_partitions, 'w') as f:
     for partition in ab_partitions:
       if (partition in dynamic_partition_list and
-              partition not in super_block_devices):
+          partition not in super_block_devices):
         logger.info("Dropping %s from ab_partitions.txt", partition)
         continue
       f.write(partition + "\n")
@@ -906,6 +916,7 @@
 
   return target_file
 
+
 def GetTargetFilesZipForCustomImagesUpdates(input_file, custom_images):
   """Returns a target-files.zip for custom partitions update.
 
@@ -944,6 +955,69 @@
 
   return target_file
 
+def GeneratePartitionTimestampFlags(partition_state):
+  partition_timestamps = [
+      part.partition_name + ":" + part.version
+      for part in partition_state]
+  return ["--partition_timestamps", ",".join(partition_timestamps)]
+
+def GeneratePartitionTimestampFlagsDowngrade(pre_partition_state, post_partition_state):
+  assert pre_partition_state is not None
+  partition_timestamps = {}
+  for part in pre_partition_state:
+    partition_timestamps[part.partition_name] = part.version
+  for part in post_partition_state:
+    partition_timestamps[part.partition_name] = \
+      max(part.version, partition_timestamps[part.partition_name])
+  return [
+    "--partition_timestamps",
+    ",".join([key + ":" + val for (key, val) in partition_timestamps.items()])
+    ]
+
+def IsSparseImage(filepath):
+  with open(filepath, 'rb') as fp:
+    # Magic for android sparse image format
+    # https://source.android.com/devices/bootloader/images
+    return fp.read(4) == b'\x3A\xFF\x26\xED'
+
+def SupportsMainlineGkiUpdates(target_file):
+  """Return True if the build supports MainlineGKIUpdates.
+
+  This function scans the product.img file in IMAGES/ directory for
+  pattern |*/apex/com.android.gki.*.apex|. If there are files
+  matching this pattern, conclude that build supports mainline
+  GKI and return True
+
+  Args:
+    target_file: Path to a target_file.zip, or an extracted directory
+  Return:
+    True if thisb uild supports Mainline GKI Updates.
+  """
+  if target_file is None:
+    return False
+  if os.path.isfile(target_file):
+    target_file = common.UnzipTemp(target_file, ["IMAGES/product.img"])
+  if not os.path.isdir(target_file):
+    assert os.path.isdir(target_file), \
+        "{} must be a path to zip archive or dir containing extracted"\
+        " target_files".format(target_file)
+  image_file = os.path.join(target_file, "IMAGES", "product.img")
+
+  if not os.path.isfile(image_file):
+    return False
+
+  if IsSparseImage(image_file):
+    # Unsparse the image
+    tmp_img = common.MakeTempFile(suffix=".img")
+    subprocess.check_output(["simg2img", image_file, tmp_img])
+    image_file = tmp_img
+
+  cmd = ["debugfs_static", "-R", "ls -p /apex", image_file]
+  output = subprocess.check_output(cmd).decode()
+
+  pattern = re.compile(r"com\.android\.gki\..*\.apex")
+  return pattern.search(output) is not None
+
 def GenerateAbOtaPackage(target_file, output_file, source_file=None):
   """Generates an Android OTA package that has A/B update payload."""
   # Stage the output zip package for package signing.
@@ -961,6 +1035,13 @@
         "META/ab_partitions.txt is required for ab_update."
     target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
     source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
+    vendor_prop = source_info.info_dict.get("vendor.build.prop")
+    if vendor_prop and \
+        vendor_prop.GetProp("ro.virtual_ab.compression.enabled") == "true":
+      # TODO(zhangkelvin) Remove this once FEC on VABC is supported
+      logger.info("Virtual AB Compression enabled, disabling FEC")
+      OPTIONS.disable_fec_computation = True
+      OPTIONS.disable_verity_computation = True
   else:
     assert "ab_partitions" in OPTIONS.info_dict, \
         "META/ab_partitions.txt is required for ab_update."
@@ -987,30 +1068,37 @@
   # Target_file may have been modified, reparse ab_partitions
   with zipfile.ZipFile(target_file, allowZip64=True) as zfp:
     target_info.info_dict['ab_partitions'] = zfp.read(
-        AB_PARTITIONS).strip().split("\n")
+        AB_PARTITIONS).decode().strip().split("\n")
 
   # Metadata to comply with Android OTA package format.
   metadata = GetPackageMetadata(target_info, source_info)
   # Generate payload.
   payload = Payload()
 
-  partition_timestamps = []
+  partition_timestamps_flags = []
   # Enforce a max timestamp this payload can be applied on top of.
   if OPTIONS.downgrade:
     max_timestamp = source_info.GetBuildProp("ro.build.date.utc")
+    partition_timestamps_flags = GeneratePartitionTimestampFlagsDowngrade(
+      metadata.precondition.partition_state,
+      metadata.postcondition.partition_state
+      )
   else:
     max_timestamp = str(metadata.postcondition.timestamp)
-    partition_timestamps = [
-        part.partition_name + ":" + part.version
-        for part in metadata.postcondition.partition_state]
-  additional_args += ["--max_timestamp", max_timestamp]
-  if partition_timestamps:
-    additional_args.extend(
-        ["--partition_timestamps", ",".join(
-            partition_timestamps)]
-    )
+    partition_timestamps_flags = GeneratePartitionTimestampFlags(
+        metadata.postcondition.partition_state)
 
-  payload.Generate(target_file, source_file, additional_args)
+  additional_args += ["--max_timestamp", max_timestamp]
+
+  if SupportsMainlineGkiUpdates(source_file):
+    logger.warn("Detected build with mainline GKI, include full boot image.")
+    additional_args.extend(["--full_boot", "true"])
+
+  payload.Generate(
+      target_file,
+      source_file,
+      additional_args + partition_timestamps_flags
+   )
 
   # Sign the payload.
   payload_signer = PayloadSigner()
@@ -1028,7 +1116,8 @@
         target_file, OPTIONS.skip_postinstall)
     secondary_payload = Payload(secondary=True)
     secondary_payload.Generate(secondary_target_file,
-                               additional_args=additional_args)
+                               additional_args=["--max_timestamp",
+                               max_timestamp])
     secondary_payload.Sign(payload_signer)
     secondary_payload.WriteToZip(output_zip)
 
@@ -1143,6 +1232,8 @@
       OPTIONS.output_metadata_path = a
     elif o == "--disable_fec_computation":
       OPTIONS.disable_fec_computation = True
+    elif o == "--disable_verity_computation":
+      OPTIONS.disable_verity_computation = True
     elif o == "--force_non_ab":
       OPTIONS.force_non_ab = True
     elif o == "--boot_variable_file":
@@ -1191,6 +1282,7 @@
                                  "skip_compatibility_check",
                                  "output_metadata_path=",
                                  "disable_fec_computation",
+                                 "disable_verity_computation",
                                  "force_non_ab",
                                  "boot_variable_file=",
                                  "partial=",
@@ -1203,15 +1295,6 @@
 
   common.InitLogging()
 
-  if OPTIONS.downgrade:
-    # We should only allow downgrading incrementals (as opposed to full).
-    # Otherwise the device may go back from arbitrary build with this full
-    # OTA package.
-    if OPTIONS.incremental_source is None:
-      raise ValueError("Cannot generate downgradable full OTAs")
-    if OPTIONS.partial:
-      raise ValueError("Cannot generate downgradable partial OTAs")
-
   # Load the build info dicts from the zip directly or the extracted input
   # directory. We don't need to unzip the entire target-files zips, because they
   # won't be needed for A/B OTAs (brillo_update_payload does that on its own).
@@ -1222,8 +1305,15 @@
   if OPTIONS.extracted_input is not None:
     OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.extracted_input)
   else:
-    with zipfile.ZipFile(args[0], 'r', allowZip64=True) as input_zip:
-      OPTIONS.info_dict = common.LoadInfoDict(input_zip)
+    OPTIONS.info_dict = ParseInfoDict(args[0])
+
+  if OPTIONS.downgrade:
+    # We should only allow downgrading incrementals (as opposed to full).
+    # Otherwise the device may go back from arbitrary build with this full
+    # OTA package.
+    if OPTIONS.incremental_source is None:
+      raise ValueError("Cannot generate downgradable full OTAs")
+
 
   # TODO(xunchang) for retrofit and partial updates, maybe we should rebuild the
   # target-file and reload the info_dict. So the info will be consistent with
@@ -1232,15 +1322,26 @@
   logger.info("--- target info ---")
   common.DumpInfoDict(OPTIONS.info_dict)
 
+
   # Load the source build dict if applicable.
   if OPTIONS.incremental_source is not None:
     OPTIONS.target_info_dict = OPTIONS.info_dict
-    with zipfile.ZipFile(OPTIONS.incremental_source, 'r', allowZip64=True) as source_zip:
-      OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
+    OPTIONS.source_info_dict = ParseInfoDict(OPTIONS.incremental_source)
 
     logger.info("--- source info ---")
     common.DumpInfoDict(OPTIONS.source_info_dict)
 
+  if OPTIONS.partial:
+    OPTIONS.info_dict['ab_partitions'] = \
+      list(
+        set(OPTIONS.info_dict['ab_partitions']) & set(OPTIONS.partial)
+        )
+    if OPTIONS.source_info_dict:
+      OPTIONS.source_info_dict['ab_partitions'] = \
+        list(
+          set(OPTIONS.source_info_dict['ab_partitions']) & set(OPTIONS.partial)
+          )
+
   # Load OEM dicts if provided.
   OPTIONS.oem_dicts = _LoadOemDicts(OPTIONS.oem_source)
 
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index ee28571..ecd759c 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -15,6 +15,7 @@
 #
 
 import copy
+import json
 import os
 import subprocess
 import tempfile
@@ -995,6 +996,55 @@
         },
         sparse_image.file_map)
 
+  def test_PartitionMapFromTargetFiles(self):
+    target_files_dir = common.MakeTempDir()
+    os.makedirs(os.path.join(target_files_dir, 'SYSTEM'))
+    os.makedirs(os.path.join(target_files_dir, 'SYSTEM', 'vendor'))
+    os.makedirs(os.path.join(target_files_dir, 'PRODUCT'))
+    os.makedirs(os.path.join(target_files_dir, 'SYSTEM', 'product'))
+    os.makedirs(os.path.join(target_files_dir, 'SYSTEM', 'vendor', 'odm'))
+    os.makedirs(os.path.join(target_files_dir, 'VENDOR_DLKM'))
+    partition_map = common.PartitionMapFromTargetFiles(target_files_dir)
+    self.assertDictEqual(
+        partition_map,
+        {
+            'system': 'SYSTEM',
+            'vendor': 'SYSTEM/vendor',
+            # Prefer PRODUCT over SYSTEM/product
+            'product': 'PRODUCT',
+            'odm': 'SYSTEM/vendor/odm',
+            'vendor_dlkm': 'VENDOR_DLKM',
+            # No system_ext or odm_dlkm
+        })
+
+  def test_SharedUidPartitionViolations(self):
+    uid_dict = {
+        'android.uid.phone': {
+            'system': ['system_phone.apk'],
+            'system_ext': ['system_ext_phone.apk'],
+        },
+        'android.uid.wifi': {
+            'vendor': ['vendor_wifi.apk'],
+            'odm': ['odm_wifi.apk'],
+        },
+    }
+    errors = common.SharedUidPartitionViolations(
+        uid_dict, [('system', 'system_ext'), ('vendor', 'odm')])
+    self.assertEqual(errors, [])
+
+  def test_SharedUidPartitionViolations_Violation(self):
+    uid_dict = {
+        'android.uid.phone': {
+            'system': ['system_phone.apk'],
+            'vendor': ['vendor_phone.apk'],
+        },
+    }
+    errors = common.SharedUidPartitionViolations(
+        uid_dict, [('system', 'system_ext'), ('vendor', 'odm')])
+    self.assertIn(
+        ('APK sharedUserId "android.uid.phone" found across partition groups '
+         'in partitions "system,vendor"'), errors)
+
   def test_GetSparseImage_missingImageFile(self):
     self.assertRaises(
         AssertionError, common.GetSparseImage, 'system2', self.testdata_dir,
diff --git a/tools/signapk/Android.bp b/tools/signapk/Android.bp
index c799dbf..f5b2ba7 100644
--- a/tools/signapk/Android.bp
+++ b/tools/signapk/Android.bp
@@ -16,7 +16,7 @@
 
 // the signapk tool (a .jar application used to sign packages)
 // ============================================================
-java_library_host {
+java_binary_host {
     name: "signapk",
     srcs: ["src/**/*.java"],
     manifest: "SignApk.mf",
@@ -32,6 +32,7 @@
     // The post-build signing tools need signapk.jar (and its shared libraries,
     // handled in their own Android.bp files)
     dist: {
+        tag: ".jar",
         targets: ["droidcore"],
     },
 }
diff --git a/tools/warn/android_project_list.py b/tools/warn/android_project_list.py
index c357e98..82c0fbd 100644
--- a/tools/warn/android_project_list.py
+++ b/tools/warn/android_project_list.py
@@ -118,8 +118,8 @@
     create_pattern('system/core/healthd'),
     create_pattern('system/core/include'),
     create_pattern('system/core/init'),
-    create_pattern('system/core/libbacktrace'),
-    create_pattern('system/core/liblog'),
+    create_pattern('system/unwinding/libbacktrace'),
+    create_pattern('system/logging/liblog'),
     create_pattern('system/core/libpixelflinger'),
     create_pattern('system/core/libprocessgroup'),
     create_pattern('system/core/libsysutils'),
diff --git a/tools/warn/html_writer.py b/tools/warn/html_writer.py
index b8d3fe6..026a6d0 100644
--- a/tools/warn/html_writer.py
+++ b/tools/warn/html_writer.py
@@ -359,6 +359,25 @@
   csvwriter.writerow([total, '', 'All warnings'])
 
 
+def dump_csv_with_description(csvwriter, warning_records, warning_messages,
+                              warn_patterns, project_names):
+  """Outputs all the warning messages by project."""
+  csv_output = []
+  for record in warning_records:
+    project_name = project_names[record[1]]
+    pattern = warn_patterns[record[0]]
+    severity = pattern['severity'].header
+    category = pattern['category']
+    description = pattern['description']
+    warning = warning_messages[record[2]]
+    csv_output.append([project_name, severity,
+                       category, description,
+                       warning])
+  csv_output = sorted(csv_output)
+  for output in csv_output:
+    csvwriter.writerow(output)
+
+
 # Return s with escaped backslash and quotation characters.
 def escape_string(s):
   return s.replace('\\', '\\\\').replace('"', '\\"')
@@ -666,6 +685,12 @@
     with open(flags.csvpath, 'w') as f:
       dump_csv(csv.writer(f, lineterminator='\n'), warn_patterns)
 
+  if flags.csvwithdescription:
+    with open(flags.csvwithdescription, 'w') as f:
+      dump_csv_with_description(csv.writer(f, lineterminator='\n'),
+                                warning_records, warning_messages,
+                                warn_patterns, project_names)
+
   if flags.gencsv:
     dump_csv(csv.writer(sys.stdout, lineterminator='\n'), warn_patterns)
   else:
diff --git a/tools/warn/warn_common.py b/tools/warn/warn_common.py
index 68ed995..b2dd8ab 100755
--- a/tools/warn/warn_common.py
+++ b/tools/warn/warn_common.py
@@ -77,6 +77,9 @@
                       help='Save CSV warning file to the passed path')
   parser.add_argument('--gencsv', action='store_true',
                       help='Generate CSV file with number of various warnings')
+  parser.add_argument('--csvwithdescription', default='',
+                      help="""Save CSV warning file to the passed path this csv
+                            will contain all the warning descriptions""")
   parser.add_argument('--byproject', action='store_true',
                       help='Separate warnings in HTML output by project names')
   parser.add_argument('--url', default='',
diff --git a/tools/zipalign/Android.bp b/tools/zipalign/Android.bp
index 8e6196d..135cd76 100644
--- a/tools/zipalign/Android.bp
+++ b/tools/zipalign/Android.bp
@@ -4,20 +4,31 @@
 // Zip alignment tool
 //
 
-cc_binary_host {
-    name: "zipalign",
+cc_defaults {
+    name: "zipalign_defaults",
+    target: {
+        windows: {
+            host_ldlibs: ["-lpthread"],
+            enabled: true,
+        },
+    },
+}
 
+cc_library_host_static {
+    name: "libzipalign",
     srcs: [
         "ZipAlign.cpp",
         "ZipEntry.cpp",
         "ZipFile.cpp",
     ],
-
+    export_include_dirs: [
+        "include",
+    ],
     cflags: ["-Wall", "-Werror"],
 
     // NOTE: Do not add any shared_libs dependencies because they will break the
     // static_sdk_tools target.
-    static_libs: [
+    whole_static_libs: [
         "libutils",
         "libcutils",
         "liblog",
@@ -26,11 +37,36 @@
         "libbase",
         "libzopfli",
     ],
+    defaults: ["zipalign_defaults"],
+}
 
-    target: {
-        windows: {
-            host_ldlibs: ["-lpthread"],
-            enabled: true,
-        },
-    },
+cc_binary_host {
+    name: "zipalign",
+    srcs: [
+        "ZipAlignMain.cpp",
+    ],
+    cflags: ["-Wall", "-Werror"],
+    static_libs: [
+        "libzipalign",
+    ],
+    defaults: ["zipalign_defaults"],
+}
+
+cc_test_host {
+    name: "zipalign_tests",
+    srcs: [
+        "tests/src/*_test.cpp",
+    ],
+    static_libs: [
+        "libbase",
+        "libzipalign",
+        "libgmock",
+    ],
+    data: [
+         "tests/data/diffOrders.zip",
+         "tests/data/holes.zip",
+         "tests/data/unaligned.zip",
+    ],
+    defaults: ["zipalign_defaults"],
+    test_suites: ["general-tests"],
 }
diff --git a/tools/zipalign/OWNERS b/tools/zipalign/OWNERS
new file mode 100644
index 0000000..d701e4a
--- /dev/null
+++ b/tools/zipalign/OWNERS
@@ -0,0 +1,2 @@
+include platform/system/core:/janitors/OWNERS
+sanglardf@google.com
diff --git a/tools/zipalign/TEST_MAPPING b/tools/zipalign/TEST_MAPPING
new file mode 100644
index 0000000..98420f3
--- /dev/null
+++ b/tools/zipalign/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+  "presubmit": [
+    {
+      "name": "zipalign_tests",
+      "host": true
+    }
+  ]
+}
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index eea1749..08f67ff 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -14,35 +14,13 @@
  * limitations under the License.
  */
 
-/*
- * Zip alignment tool
- */
 #include "ZipFile.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-using namespace android;
-
-/*
- * Show program usage.
- */
-void usage(void)
-{
-    fprintf(stderr, "Zip alignment utility\n");
-    fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
-    fprintf(stderr,
-        "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
-        "       zipalign -c [-p] [-v] <align> infile.zip\n\n" );
-    fprintf(stderr,
-        "  <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
-    fprintf(stderr, "  -c: check alignment only (does not modify file)\n");
-    fprintf(stderr, "  -f: overwrite existing outfile.zip\n");
-    fprintf(stderr, "  -p: memory page alignment for stored shared object files\n");
-    fprintf(stderr, "  -v: verbose output\n");
-    fprintf(stderr, "  -z: recompress using Zopfli\n");
-}
+namespace android {
 
 static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
     ZipEntry* pEntry) {
@@ -69,7 +47,6 @@
 {
     int numEntries = pZin->getNumEntries();
     ZipEntry* pEntry;
-    int bias = 0;
     status_t status;
 
     for (int i = 0; i < numEntries; i++) {
@@ -90,30 +67,20 @@
 
             if (zopfli) {
                 status = pZout->addRecompress(pZin, pEntry, &pNewEntry);
-                bias += pNewEntry->getCompressedLen() - pEntry->getCompressedLen();
             } else {
                 status = pZout->add(pZin, pEntry, padding, &pNewEntry);
             }
         } else {
             const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
 
-            /*
-             * Copy the entry, adjusting as required.  We assume that the
-             * file position in the new file will be equal to the file
-             * position in the original.
-             */
-            off_t newOffset = pEntry->getFileOffset() + bias;
-            padding = (alignTo - (newOffset % alignTo)) % alignTo;
-
             //printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n",
             //    pEntry->getFileName(), (long) pEntry->getFileOffset(),
             //    bias, (long) pEntry->getUncompressedLen(), padding);
-            status = pZout->add(pZin, pEntry, padding, &pNewEntry);
+            status = pZout->add(pZin, pEntry, alignTo, &pNewEntry);
         }
 
         if (status != OK)
             return 1;
-        bias += padding;
         //printf(" added '%s' at %ld (pad=%d)\n",
         //    pNewEntry->getFileName(), (long) pNewEntry->getFileOffset(),
         //    padding);
@@ -126,7 +93,7 @@
  * Process a file.  We open the input and output files, failing if the
  * output file exists and "force" wasn't specified.
  */
-static int process(const char* inFileName, const char* outFileName,
+int process(const char* inFileName, const char* outFileName,
     int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
 {
     ZipFile zin, zout;
@@ -169,7 +136,7 @@
 /*
  * Verify the alignment of a zip archive.
  */
-static int verify(const char* fileName, int alignment, bool verbose,
+int verify(const char* fileName, int alignment, bool verbose,
     bool pageAlignSharedLibs)
 {
     ZipFile zipFile;
@@ -218,92 +185,4 @@
     return foundBad ? 1 : 0;
 }
 
-/*
- * Parse args.
- */
-int main(int argc, char* const argv[])
-{
-    bool wantUsage = false;
-    bool check = false;
-    bool force = false;
-    bool verbose = false;
-    bool zopfli = false;
-    bool pageAlignSharedLibs = false;
-    int result = 1;
-    int alignment;
-    char* endp;
-
-    if (argc < 4) {
-        wantUsage = true;
-        goto bail;
-    }
-
-    argc--;
-    argv++;
-
-    while (argc && argv[0][0] == '-') {
-        const char* cp = argv[0] +1;
-
-        while (*cp != '\0') {
-            switch (*cp) {
-            case 'c':
-                check = true;
-                break;
-            case 'f':
-                force = true;
-                break;
-            case 'v':
-                verbose = true;
-                break;
-            case 'z':
-                zopfli = true;
-                break;
-            case 'p':
-                pageAlignSharedLibs = true;
-                break;
-            default:
-                fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
-                wantUsage = true;
-                goto bail;
-            }
-
-            cp++;
-        }
-
-        argc--;
-        argv++;
-    }
-
-    if (!((check && argc == 2) || (!check && argc == 3))) {
-        wantUsage = true;
-        goto bail;
-    }
-
-    alignment = strtol(argv[0], &endp, 10);
-    if (*endp != '\0' || alignment <= 0) {
-        fprintf(stderr, "Invalid value for alignment: %s\n", argv[0]);
-        wantUsage = true;
-        goto bail;
-    }
-
-    if (check) {
-        /* check existing archive for correct alignment */
-        result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
-    } else {
-        /* create the new archive */
-        result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
-
-        /* trust, but verify */
-        if (result == 0) {
-            result = verify(argv[2], alignment, verbose, pageAlignSharedLibs);
-        }
-    }
-
-bail:
-    if (wantUsage) {
-        usage();
-        result = 2;
-    }
-
-    return result;
-}
+} // namespace android
diff --git a/tools/zipalign/ZipAlignMain.cpp b/tools/zipalign/ZipAlignMain.cpp
new file mode 100644
index 0000000..49be916
--- /dev/null
+++ b/tools/zipalign/ZipAlignMain.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Zip alignment tool
+ */
+
+#include "ZipAlign.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace android;
+
+/*
+ * Show program usage.
+ */
+void usage(void)
+{
+    fprintf(stderr, "Zip alignment utility\n");
+    fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
+    fprintf(stderr,
+        "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
+        "       zipalign -c [-p] [-v] <align> infile.zip\n\n" );
+    fprintf(stderr,
+        "  <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
+    fprintf(stderr, "  -c: check alignment only (does not modify file)\n");
+    fprintf(stderr, "  -f: overwrite existing outfile.zip\n");
+    fprintf(stderr, "  -p: memory page alignment for stored shared object files\n");
+    fprintf(stderr, "  -v: verbose output\n");
+    fprintf(stderr, "  -z: recompress using Zopfli\n");
+}
+
+
+/*
+ * Parse args.
+ */
+int main(int argc, char* const argv[])
+{
+    bool wantUsage = false;
+    bool check = false;
+    bool force = false;
+    bool verbose = false;
+    bool zopfli = false;
+    bool pageAlignSharedLibs = false;
+    int result = 1;
+    int alignment;
+    char* endp;
+
+    if (argc < 4) {
+        wantUsage = true;
+        goto bail;
+    }
+
+    argc--;
+    argv++;
+
+    while (argc && argv[0][0] == '-') {
+        const char* cp = argv[0] +1;
+
+        while (*cp != '\0') {
+            switch (*cp) {
+            case 'c':
+                check = true;
+                break;
+            case 'f':
+                force = true;
+                break;
+            case 'v':
+                verbose = true;
+                break;
+            case 'z':
+                zopfli = true;
+                break;
+            case 'p':
+                pageAlignSharedLibs = true;
+                break;
+            default:
+                fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
+                wantUsage = true;
+                goto bail;
+            }
+
+            cp++;
+        }
+
+        argc--;
+        argv++;
+    }
+
+    if (!((check && argc == 2) || (!check && argc == 3))) {
+        wantUsage = true;
+        goto bail;
+    }
+
+    alignment = strtol(argv[0], &endp, 10);
+    if (*endp != '\0' || alignment <= 0) {
+        fprintf(stderr, "Invalid value for alignment: %s\n", argv[0]);
+        wantUsage = true;
+        goto bail;
+    }
+
+    if (check) {
+        /* check existing archive for correct alignment */
+        result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
+    } else {
+        /* create the new archive */
+        result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
+
+        /* trust, but verify */
+        if (result == 0) {
+            result = verify(argv[2], alignment, verbose, pageAlignSharedLibs);
+        }
+    }
+
+bail:
+    if (wantUsage) {
+        usage();
+        result = 2;
+    }
+
+    return result;
+}
diff --git a/tools/zipalign/ZipEntry.cpp b/tools/zipalign/ZipEntry.cpp
index 810d74a..5233f0a 100644
--- a/tools/zipalign/ZipEntry.cpp
+++ b/tools/zipalign/ZipEntry.cpp
@@ -29,7 +29,7 @@
 #include <string.h>
 #include <time.h>
 
-using namespace android;
+namespace android {
 
 /*
  * Initialize a new ZipEntry structure from a FILE* positioned at a
@@ -696,3 +696,5 @@
         ALOGD("  comment: '%s'\n", mFileComment);
 }
 
+} // namespace android
+
diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp
index 88505b7..9938a06 100644
--- a/tools/zipalign/ZipFile.cpp
+++ b/tools/zipalign/ZipFile.cpp
@@ -35,7 +35,7 @@
 #include <assert.h>
 #include <inttypes.h>
 
-using namespace android;
+namespace android {
 
 /*
  * Some environments require the "b", some choke on it.
@@ -134,7 +134,7 @@
 /*
  * Return the Nth entry in the archive.
  */
-android::ZipEntry* ZipFile::getEntryByIndex(int idx) const
+ZipEntry* ZipFile::getEntryByIndex(int idx) const
 {
     if (idx < 0 || idx >= (int) mEntries.size())
         return NULL;
@@ -145,7 +145,7 @@
 /*
  * Find an entry by name.
  */
-android::ZipEntry* ZipFile::getEntryByName(const char* fileName) const
+ZipEntry* ZipFile::getEntryByName(const char* fileName) const
 {
     /*
      * Do a stupid linear string-compare search.
@@ -503,6 +503,32 @@
 }
 
 /*
+ * Based on the current position in the output zip, assess where the entry
+ * payload will end up if written as-is. If alignment is not satisfactory,
+ * add some padding in the extra field.
+ *
+ */
+status_t ZipFile::alignEntry(android::ZipEntry* pEntry, uint32_t alignTo){
+    if (alignTo == 0 || alignTo == 1)
+        return OK;
+
+    // Calculate where the entry payload offset will end up if we were to write
+    // it as-is.
+    uint64_t expectedPayloadOffset = ftell(mZipFp) +
+        android::ZipEntry::LocalFileHeader::kLFHLen +
+        pEntry->mLFH.mFileNameLength +
+        pEntry->mLFH.mExtraFieldLength;
+
+    // If the alignment is not what was requested, add some padding in the extra
+    // so the payload ends up where is requested.
+    uint64_t alignDiff = alignTo - (expectedPayloadOffset % alignTo);
+    if (alignDiff == 0)
+        return OK;
+
+    return pEntry->addPadding(alignDiff);
+}
+
+/*
  * Add an entry by copying it from another zip file.  If "padding" is
  * nonzero, the specified number of bytes will be added to the "extra"
  * field in the header.
@@ -510,7 +536,7 @@
  * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
  */
 status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
-    int padding, ZipEntry** ppEntry)
+    int alignTo, ZipEntry** ppEntry)
 {
     ZipEntry* pEntry = NULL;
     status_t result;
@@ -537,11 +563,10 @@
     result = pEntry->initFromExternal(pSourceEntry);
     if (result != OK)
         goto bail;
-    if (padding != 0) {
-        result = pEntry->addPadding(padding);
-        if (result != OK)
-            goto bail;
-    }
+
+    result = alignEntry(pEntry, alignTo);
+    if (result != OK)
+      goto bail;
 
     /*
      * From here on out, failures are more interesting.
@@ -1397,3 +1422,4 @@
         mCentralDirSize, mCentralDirOffset, mCommentLen);
 }
 
+} // namespace android
diff --git a/tools/zipalign/ZipFile.h b/tools/zipalign/ZipFile.h
index 11d20c5..854f981 100644
--- a/tools/zipalign/ZipFile.h
+++ b/tools/zipalign/ZipFile.h
@@ -102,14 +102,14 @@
     }
 
     /*
-     * Add an entry by copying it from another zip file.  If "padding" is
-     * nonzero, the specified number of bytes will be added to the "extra"
-     * field in the header.
+     * Add an entry by copying it from another zip file.  If "alignment" is
+     * nonzero, an appropriate number of bytes will be added to the "extra"
+     * field in the header so the entry payload is aligned.
      *
      * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
      */
     status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
-        int padding, ZipEntry** ppEntry);
+        int alignment, ZipEntry** ppEntry);
 
     /*
      * Add an entry by copying it from another zip file, recompressing with
@@ -163,6 +163,8 @@
     ZipFile(const ZipFile& src);
     ZipFile& operator=(const ZipFile& src);
 
+    status_t alignEntry(android::ZipEntry* pEntry, uint32_t alignTo);
+
     class EndOfCentralDir {
     public:
         EndOfCentralDir(void) :
diff --git a/tools/zipalign/include/ZipAlign.h b/tools/zipalign/include/ZipAlign.h
new file mode 100644
index 0000000..ab36086
--- /dev/null
+++ b/tools/zipalign/include/ZipAlign.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef ZIPALIGN_H
+#define ZIPALIGN_H
+
+namespace android {
+
+/*
+ * Generate a new, aligned, zip "output" from an "input" zip.
+ * - alignTo: Alignment (in bytes) for uncompressed entries.
+ * - force  : Overwrite output if it exists, fail otherwise.
+ * - zopfli : Recompress compressed entries with more efficient algorithm.
+ *            Copy compressed entries as-is, and unaligned, otherwise.
+ * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ *   alignTo, or all files to alignTo if false..
+ *
+ * Returns 0 on success.
+ */
+int process(const char* input, const char* output, int alignTo, bool force,
+    bool zopfli, bool pageAlignSharedLibs);
+
+/*
+ * Verify the alignment of a zip archive.
+ * - alignTo: Alignment (in bytes) for uncompressed entries.
+ * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ *   alignTo, or all files to alignTo if false..
+ *
+ * Returns 0 on success.
+ */
+int verify(const char* fileName, int alignTo, bool verbose,
+    bool pageAlignSharedLibs);
+
+} // namespace android
+
+#endif // ZIPALIGN_H
diff --git a/tools/zipalign/tests/data/diffOrders.zip b/tools/zipalign/tests/data/diffOrders.zip
new file mode 100644
index 0000000..8f512ed
--- /dev/null
+++ b/tools/zipalign/tests/data/diffOrders.zip
Binary files differ
diff --git a/tools/zipalign/tests/data/holes.zip b/tools/zipalign/tests/data/holes.zip
new file mode 100644
index 0000000..c88f891
--- /dev/null
+++ b/tools/zipalign/tests/data/holes.zip
Binary files differ
diff --git a/tools/zipalign/tests/data/unaligned.zip b/tools/zipalign/tests/data/unaligned.zip
new file mode 100644
index 0000000..d572b1a
--- /dev/null
+++ b/tools/zipalign/tests/data/unaligned.zip
Binary files differ
diff --git a/tools/zipalign/tests/src/align_test.cpp b/tools/zipalign/tests/src/align_test.cpp
new file mode 100644
index 0000000..c79e791
--- /dev/null
+++ b/tools/zipalign/tests/src/align_test.cpp
@@ -0,0 +1,53 @@
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "ZipAlign.h"
+
+#include <stdio.h>
+#include <string>
+
+#include <android-base/file.h>
+
+using namespace android;
+
+static std::string GetTestPath(const std::string& filename) {
+  static std::string test_data_dir = android::base::GetExecutableDirectory() + "/tests/data/";
+  return test_data_dir + filename;
+}
+
+TEST(Align, Unaligned) {
+  const std::string src = GetTestPath("unaligned.zip");
+  const std::string dst = GetTestPath("unaligned_out.zip");
+
+  int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+  ASSERT_EQ(0, processed);
+
+  int verified = verify(dst.c_str(), 4, true, false);
+  ASSERT_EQ(0, verified);
+}
+
+// Align a zip featuring a hole at the beginning. The
+// hole in the archive is a delete entry in the Central
+// Directory.
+TEST(Align, Holes) {
+  const std::string src = GetTestPath("holes.zip");
+  const std::string dst = GetTestPath("holes_out.zip");
+
+  int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+  ASSERT_EQ(0, processed);
+
+  int verified = verify(dst.c_str(), 4, false, true);
+  ASSERT_EQ(0, verified);
+}
+
+// Align a zip where LFH order and CD entries differ.
+TEST(Align, DifferenteOrders) {
+  const std::string src = GetTestPath("diffOrders.zip");
+  const std::string dst = GetTestPath("diffOrders_out.zip");
+
+  int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+  ASSERT_EQ(0, processed);
+
+  int verified = verify(dst.c_str(), 4, false, true);
+  ASSERT_EQ(0, verified);
+}