Merge "Reland: Add PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT"
diff --git a/core/Makefile b/core/Makefile
index 63ec1a6..a848630 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -163,7 +163,9 @@
 .PHONY: ndk-docs
 endif
 
+ifeq ($(HOST_OS),linux)
 $(call dist-for-goals,sdk,$(API_FINGERPRINT))
+endif
 
 INSTALLED_RECOVERYIMAGE_TARGET :=
 # Build recovery image if
@@ -775,7 +777,9 @@
 	$(FILESLIST) $(TARGET_ROOT_OUT) > $(@:.txt=.json)
 	$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
 
+ifeq ($(HOST_OS),linux)
 $(call dist-for-goals, sdk win_sdk sdk_addon, $(INSTALLED_FILES_FILE_ROOT))
+endif
 
 #------------------------------------------------------------------
 # dtb
@@ -805,7 +809,9 @@
 	$(FILESLIST) $(TARGET_RAMDISK_OUT) > $(@:.txt=.json)
 	$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
 
+ifeq ($(HOST_OS),linux)
 $(call dist-for-goals, sdk win_sdk sdk_addon, $(INSTALLED_FILES_FILE_RAMDISK))
+endif
 BUILT_RAMDISK_TARGET := $(PRODUCT_OUT)/ramdisk.img
 
 ifeq ($(BOARD_RAMDISK_USE_LZ4),true)
@@ -1601,16 +1607,35 @@
 
 endif # PRODUCT_USE_DYNAMIC_PARTITIONS
 
-# $(1) the partition variable component (eg SYSTEM)
-# $(2) the partition prefix in properties (eg system)
-# $(3) the image prop file
-# $(4) optional "other" size
-define add-sparse-flags-to-image-props
-$(eval _size := $(BOARD_$(1)IMAGE_PARTITION_SIZE))
-$(eval _reserved := $(BOARD_$(1)IMAGE_PARTITION_RESERVED_SIZE))
-$(eval _headroom := $(PRODUCT_$(1)_HEADROOM))
-$(if $(or $(_size), $(_reserved), $(_headroom), $(4)),,
-    $(hide) echo "$(2)_disable_sparse=true" >> $(3))
+# $(1) the partition name (eg system)
+# $(2) the image prop file
+define add-common-flags-to-image-props
+$(eval _var := $(call to-upper,$(1)))
+$(hide) echo "$(1)_selinux_fc=$(SELINUX_FC)" >> $(2)
+$(hide) echo "building_$(1)_image=$(BUILDING_$(_var)_IMAGE)" >> $(2)
+endef
+
+# $(1) the partition name (eg system)
+# $(2) the image prop file
+define add-common-ro-flags-to-image-props
+$(eval _var := $(call to-upper,$(1)))
+$(if $(BOARD_$(_var)IMAGE_EXTFS_INODE_COUNT),$(hide) echo "$(1)_extfs_inode_count=$(BOARD_$(_var)IMAGE_EXTFS_INODE_COUNT)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_EXTFS_RSV_PCT),$(hide) echo "$(1)_extfs_rsv_pct=$(BOARD_$(_var)IMAGE_EXTFS_RSV_PCT)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "$(1)_f2fs_sldc_flags=$(BOARD_$(_var)IMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "$(1)_f2fs_compress=$(BOARD_$(_var)IMAGE_FILE_SYSTEM_COMPRESS)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_FILE_SYSTEM_TYPE),$(hide) echo "$(1)_fs_type=$(BOARD_$(_var)IMAGE_FILE_SYSTEM_TYPE)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_JOURNAL_SIZE),$(hide) echo "$(1)_journal_size=$(BOARD_$(_var)IMAGE_JOURNAL_SIZE)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "$(1)_reserved_size=$(BOARD_$(_var)IMAGE_PARTITION_RESERVED_SIZE)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_PARTITION_SIZE),$(hide) echo "$(1)_size=$(BOARD_$(_var)IMAGE_PARTITION_SIZE)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "$(1)_squashfs_block_size=$(BOARD_$(_var)IMAGE_SQUASHFS_BLOCK_SIZE)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "$(1)_squashfs_compressor=$(BOARD_$(_var)IMAGE_SQUASHFS_COMPRESSOR)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "$(1)_squashfs_compressor_opt=$(BOARD_$(_var)IMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(2))
+$(if $(BOARD_$(_var)IMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "$(1)_squashfs_disable_4k_align=$(BOARD_$(_var)IMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(2))
+$(if $(PRODUCT_$(_var)_BASE_FS_PATH),$(hide) echo "$(1)_base_fs_file=$(PRODUCT_$(_var)_BASE_FS_PATH)" >> $(2))
+$(eval _size := $(BOARD_$(_var)IMAGE_PARTITION_SIZE))
+$(eval _reserved := $(BOARD_$(_var)IMAGE_PARTITION_RESERVED_SIZE))
+$(eval _headroom := $(PRODUCT_$(_var)_HEADROOM))
+$(call add-common-flags-to-image-props,$(1),$(2))
 endef
 
 # $(1): the path of the output dictionary file
@@ -1618,24 +1643,9 @@
 # $(3): additional "key=value" pairs to append to the dictionary file.
 define generate-image-prop-dictionary
 $(if $(filter $(2),system),\
-    $(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1))
     $(if $(INTERNAL_SYSTEM_OTHER_PARTITION_SIZE),$(hide) echo "system_other_size=$(INTERNAL_SYSTEM_OTHER_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "system_f2fs_compress=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_COMPRESS)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "system_f2fs_sldc_flags=$(BOARD_SYSTEMIMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "system_extfs_inode_count=$(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_EXTFS_RSV_PCT),$(hide) echo "system_extfs_rsv_pct=$(BOARD_SYSTEMIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_JOURNAL_SIZE),$(hide) echo "system_journal_size=$(BOARD_SYSTEMIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_squashfs_block_size=$(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_squashfs_disable_4k_align=$(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCT_SYSTEM_BASE_FS_PATH),$(hide) echo "system_base_fs_file=$(PRODUCT_SYSTEM_BASE_FS_PATH)" >> $(1))
     $(if $(PRODUCT_SYSTEM_HEADROOM),$(hide) echo "system_headroom=$(PRODUCT_SYSTEM_HEADROOM)" >> $(1))
-    $(if $(BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "system_reserved_size=$(BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,SYSTEM,system,$(1))
-    $(hide) echo "system_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_system_image=$(BUILDING_SYSTEM_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,system,$(1))
 )
 $(if $(filter $(2),system_other),\
     $(hide) echo "building_system_other_image=$(BUILDING_SYSTEM_OTHER_IMAGE)" >> $(1)
@@ -1648,122 +1658,37 @@
     $(if $(PRODUCT_FS_CASEFOLD),$(hide) echo "needs_casefold=$(PRODUCT_FS_CASEFOLD)" >> $(1))
     $(if $(PRODUCT_QUOTA_PROJID),$(hide) echo "needs_projid=$(PRODUCT_QUOTA_PROJID)" >> $(1))
     $(if $(PRODUCT_FS_COMPRESSION),$(hide) echo "needs_compress=$(PRODUCT_FS_COMPRESSION)" >> $(1))
-    $(hide) echo "userdata_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_userdata_image=$(BUILDING_USERDATA_IMAGE)" >> $(1)
+    $(call add-common-flags-to-image-props,userdata,$(1))
 )
 $(if $(filter $(2),cache),\
     $(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
     $(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1))
-    $(hide) echo "cache_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_cache_image=$(BUILDING_CACHE_IMAGE)" >> $(1)
+    $(call add-common-flags-to-image-props,cache,$(1))
 )
 $(if $(filter $(2),vendor),\
-    $(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "vendor_f2fs_compress=$(BOARD_VENDORIMAGE_FILE_SYSTEM_COMPRESS)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "vendor_f2fs_sldc_flags=$(BOARD_VENDORIMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_EXTFS_INODE_COUNT),$(hide) echo "vendor_extfs_inode_count=$(BOARD_VENDORIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_EXTFS_RSV_PCT),$(hide) echo "vendor_extfs_rsv_pct=$(BOARD_VENDORIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_PARTITION_SIZE),$(hide) echo "vendor_size=$(BOARD_VENDORIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_JOURNAL_SIZE),$(hide) echo "vendor_journal_size=$(BOARD_VENDORIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "vendor_squashfs_compressor=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "vendor_squashfs_compressor_opt=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_squashfs_block_size=$(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_squashfs_disable_4k_align=$(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1))
-    $(if $(BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "vendor_reserved_size=$(BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,VENDOR,vendor,$(1))
-    $(hide) echo "vendor_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_vendor_image=$(BUILDING_VENDOR_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,vendor,$(1))
 )
 $(if $(filter $(2),product),\
-    $(if $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "product_fs_type=$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "product_f2fs_compress=$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_COMPRESS)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "product_f2fs_sldc_flags=$(BOARD_PRODUCTIMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_EXTFS_INODE_COUNT),$(hide) echo "product_extfs_inode_count=$(BOARD_PRODUCTIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_EXTFS_RSV_PCT),$(hide) echo "product_extfs_rsv_pct=$(BOARD_PRODUCTIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_PARTITION_SIZE),$(hide) echo "product_size=$(BOARD_PRODUCTIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_JOURNAL_SIZE),$(hide) echo "product_journal_size=$(BOARD_PRODUCTIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "product_squashfs_compressor=$(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "product_squashfs_compressor_opt=$(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "product_squashfs_block_size=$(BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "product_squashfs_disable_4k_align=$(BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCT_PRODUCT_BASE_FS_PATH),$(hide) echo "product_base_fs_file=$(PRODUCT_PRODUCT_BASE_FS_PATH)" >> $(1))
-    $(if $(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "product_reserved_size=$(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,PRODUCT,product,$(1))
-    $(hide) echo "product_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_product_image=$(BUILDING_PRODUCT_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,product,$(1))
 )
 $(if $(filter $(2),system_ext),\
-    $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_ext_fs_type=$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "system_ext_f2fs_compress=$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_COMPRESS)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "system_ext_f2fs_sldc_flags=$(BOARD_SYSTEM_EXTIMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_EXTFS_INODE_COUNT),$(hide) echo "system_ext_extfs_inode_count=$(BOARD_SYSTEM_EXTIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_EXTFS_RSV_PCT),$(hide) echo "system_ext_extfs_rsv_pct=$(BOARD_SYSTEM_EXTIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE),$(hide) echo "system_ext_size=$(BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_JOURNAL_SIZE),$(hide) echo "system_ext_journal_size=$(BOARD_SYSTEM_EXTIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_ext_squashfs_compressor=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_ext_squashfs_compressor_opt=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_ext_squashfs_block_size=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_ext_squashfs_disable_4k_align=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "system_ext_reserved_size=$(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,SYSTEM_EXT,system_ext,$(1))
-    $(hide) echo "system_ext_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_system_ext_image=$(BUILDING_SYSTEM_EXT_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,system_ext,$(1))
 )
 $(if $(filter $(2),odm),\
-    $(if $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "odm_fs_type=$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "odm_extfs_inode_count=$(BOARD_ODMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_EXTFS_RSV_PCT),$(hide) echo "odm_extfs_rsv_pct=$(BOARD_ODMIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_PARTITION_SIZE),$(hide) echo "odm_size=$(BOARD_ODMIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_JOURNAL_SIZE),$(hide) echo "odm_journal_size=$(BOARD_ODMIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "odm_squashfs_compressor=$(BOARD_ODMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "odm_squashfs_compressor_opt=$(BOARD_ODMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "odm_squashfs_block_size=$(BOARD_ODMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "odm_squashfs_disable_4k_align=$(BOARD_ODMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(PRODUCT_ODM_BASE_FS_PATH),$(hide) echo "odm_base_fs_file=$(PRODUCT_ODM_BASE_FS_PATH)" >> $(1))
-    $(if $(BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "odm_reserved_size=$(BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,ODM,odm,$(1))
-    $(hide) echo "odm_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_odm_image=$(BUILDING_ODM_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,odm,$(1))
 )
 $(if $(filter $(2),vendor_dlkm),\
-    $(if $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_dlkm_fs_type=$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "vendor_dlkm_f2fs_compress=$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_COMPRESS)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "vendor_dlkm_f2fs_sldc_flags=$(BOARD_VENDOR_DLKMIMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "vendor_dlkm_extfs_inode_count=$(BOARD_VENDOR_DLKMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_EXTFS_RSV_PCT),$(hide) echo "vendor_dlkm_extfs_rsv_pct=$(BOARD_VENDOR_DLKMIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE),$(hide) echo "vendor_dlkm_size=$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_JOURNAL_SIZE),$(hide) echo "vendor_dlkm_journal_size=$(BOARD_VENDOR_DLKMIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "vendor_dlkm_squashfs_compressor=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "vendor_dlkm_squashfs_compressor_opt=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_dlkm_squashfs_block_size=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_dlkm_squashfs_disable_4k_align=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "vendor_dlkm_reserved_size=$(BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,VENDOR_DLKM,vendor_dlkm,$(1))
-    $(hide) echo "vendor_dlkm_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_vendor_dlkm_image=$(BUILDING_VENDOR_DLKM_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,vendor_dlkm,$(1))
 )
 $(if $(filter $(2),odm_dlkm),\
-    $(if $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "odm_dlkm_fs_type=$(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "odm_dlkm_extfs_inode_count=$(BOARD_ODM_DLKMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_EXTFS_RSV_PCT),$(hide) echo "odm_dlkm_extfs_rsv_pct=$(BOARD_ODM_DLKMIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE),$(hide) echo "odm_dlkm_size=$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_JOURNAL_SIZE),$(hide) echo "odm_dlkm_journal_size=$(BOARD_ODM_DLKMIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "odm_dlkm_squashfs_compressor=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "odm_dlkm_squashfs_compressor_opt=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "odm_dlkm_squashfs_block_size=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "odm_dlkm_squashfs_disable_4k_align=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "odm_dlkm_reserved_size=$(BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(call add-sparse-flags-to-image-props,ODM_DLKM,odm_dlkm,$(1))
-    $(hide) echo "odm_dlkm_selinux_fc=$(SELINUX_FC)" >> $(1)
-    $(hide) echo "building_odm_dlkm_image=$(BUILDING_ODM_DLKM_IMAGE)" >> $(1)
+    $(call add-common-ro-flags-to-image-props,odm_dlkm,$(1))
 )
 $(if $(filter $(2),oem),\
     $(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1))
     $(if $(BOARD_OEMIMAGE_JOURNAL_SIZE),$(hide) echo "oem_journal_size=$(BOARD_OEMIMAGE_JOURNAL_SIZE)" >> $(1))
     $(if $(BOARD_OEMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "oem_extfs_inode_count=$(BOARD_OEMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
     $(if $(BOARD_OEMIMAGE_EXTFS_RSV_PCT),$(hide) echo "oem_extfs_rsv_pct=$(BOARD_OEMIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(hide) echo "oem_selinux_fc=$(SELINUX_FC)" >> $(1)
+    $(call add-common-flags-to-image-props,oem,$(1))
 )
 $(hide) echo "ext_mkuserimg=$(notdir $(MKEXTUSERIMG))" >> $(1)
 
@@ -2430,6 +2355,7 @@
 #
 # Note: it's intentional to skip signing for boot-debug.img, because it
 # can only be used if the device is unlocked with verification error.
+ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
 ifneq ($(INSTALLED_BOOTIMAGE_TARGET),)
 ifneq ($(strip $(TARGET_NO_KERNEL)),true)
 ifneq ($(strip $(BOARD_KERNEL_BINARIES)),)
@@ -2488,6 +2414,7 @@
 
 endif # TARGET_NO_KERNEL
 endif # INSTALLED_BOOTIMAGE_TARGET
+endif # BUILDING_VENDOR_BOOT_IMAGE is not true
 
 ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
 ifeq ($(BUILDING_RAMDISK_IMAGE),true)
@@ -2633,6 +2560,7 @@
 #
 # Note: it's intentional to skip signing for boot-test-harness.img, because it
 # can only be used if the device is unlocked with verification error.
+ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
 ifneq ($(INSTALLED_BOOTIMAGE_TARGET),)
 ifneq ($(strip $(TARGET_NO_KERNEL)),true)
 
@@ -2675,6 +2603,7 @@
 
 endif # TARGET_NO_KERNEL
 endif # INSTALLED_BOOTIMAGE_TARGET
+endif # BUILDING_VENDOR_BOOT_IMAGE is not true
 endif # BOARD_BUILD_SYSTEM_ROOT_IMAGE is not true
 
 ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
@@ -2804,7 +2733,9 @@
 .PHONY: installed-file-list
 installed-file-list: $(INSTALLED_FILES_FILE)
 
+ifeq ($(HOST_OS),linux)
 $(call dist-for-goals, sdk win_sdk sdk_addon, $(INSTALLED_FILES_FILE))
+endif
 
 systemimage_intermediates := \
     $(call intermediates-dir-for,PACKAGING,systemimage)
@@ -5371,7 +5302,9 @@
 	@echo Package NDK sysroot...
 	$(hide) tar cjf $@ -C $(SOONG_OUT_DIR) ndk
 
+ifeq ($(HOST_OS),linux)
 $(call dist-for-goals,sdk,$(NDK_SYSROOT_TARGET))
+endif
 
 ifeq ($(build_ota_package),true)
 # -----------------------------------------------------------------
diff --git a/core/config.mk b/core/config.mk
index 0b317fb..bead8f6 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -490,11 +490,8 @@
 #
 ifeq (,$(TARGET_BUILD_USE_PREBUILT_SDKS))
   AAPT := $(HOST_OUT_EXECUTABLES)/aapt
-  MAINDEXCLASSES := $(HOST_OUT_EXECUTABLES)/mainDexClasses
-
 else # TARGET_BUILD_USE_PREBUILT_SDKS
   AAPT := $(prebuilt_sdk_tools_bin)/aapt
-  MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses
 endif # TARGET_BUILD_USE_PREBUILT_SDKS
 
 ifeq (,$(TARGET_BUILD_USE_PREBUILT_SDKS))
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 1d16eab..7655b42 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -60,11 +60,6 @@
   LOCAL_DEX_PREOPT :=
 endif
 
-# Don't preopt system server jars that are updatable.
-ifneq (,$(filter %:$(LOCAL_MODULE), $(PRODUCT_APEX_SYSTEM_SERVER_JARS)))
-  LOCAL_DEX_PREOPT :=
-endif
-
 # if WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY=true and module is not in boot class path skip
 # Also preopt system server jars since selinux prevents system server from loading anything from
 # /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
@@ -429,6 +424,16 @@
 $(LOCAL_INSTALLED_MODULE): $(my_dexpreopt_config_for_postprocessing)
 
 ifdef LOCAL_DEX_PREOPT
+  # System server jars must be copied into predefined locations expected by
+  # dexpreopt. Copy rule must be exposed to Ninja (as it uses these files as
+  # inputs), so it cannot go in dexpreopt.sh.
+  ifneq (,$(filter %:$(LOCAL_MODULE), $(PRODUCT_SYSTEM_SERVER_JARS)))
+    my_dexpreopt_jar_copy := $(OUT_DIR)/soong/system_server_dexjars/$(LOCAL_MODULE).jar
+    $(my_dexpreopt_jar_copy): PRIVATE_BUILT_MODULE := $(LOCAL_BUILT_MODULE)
+    $(my_dexpreopt_jar_copy): $(LOCAL_BUILT_MODULE)
+	  @cp $(PRIVATE_BUILT_MODULE) $@
+  endif
+
   my_dexpreopt_script := $(intermediates)/dexpreopt.sh
   my_dexpreopt_zip := $(intermediates)/dexpreopt.zip
   .KATI_RESTAT: $(my_dexpreopt_script)
@@ -437,6 +442,7 @@
   $(my_dexpreopt_script): PRIVATE_GLOBAL_CONFIG := $(DEX_PREOPT_CONFIG_FOR_MAKE)
   $(my_dexpreopt_script): PRIVATE_MODULE_CONFIG := $(my_dexpreopt_config)
   $(my_dexpreopt_script): $(DEXPREOPT_GEN)
+  $(my_dexpreopt_script): $(my_dexpreopt_jar_copy)
   $(my_dexpreopt_script): $(my_dexpreopt_config) $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE) $(DEX_PREOPT_CONFIG_FOR_MAKE)
 	@echo "$(PRIVATE_MODULE) dexpreopt gen"
 	$(DEXPREOPT_GEN) \
diff --git a/core/envsetup.rbc b/core/envsetup.rbc
index 69c4989..4cc98c8 100644
--- a/core/envsetup.rbc
+++ b/core/envsetup.rbc
@@ -38,7 +38,7 @@
     return all_versions[min_i:max_i + 1]
 
 # This function is a manual conversion of the version_defaults.mk
-def _versions_default(g, all_versions):
+def _versions_default(g, all_versions, v):
     """Handle various build version information.
 
     Guarantees that the following are defined:
@@ -59,17 +59,21 @@
         _build_id_init(g)
         g["INTERNAL_BUILD_ID_MAKEFILE"] = "build/make/core/build_id"
 
-    allowed_versions = _allowed_versions(all_versions, v_min, v_max, v_default)
-    g.setdefault("TARGET_PLATFORM_VERSION", v_default)
+    allowed_versions = _allowed_versions(all_versions, v.min_platform_version, v.max_platform_version, v.default_platform_version)
+    g.setdefault("TARGET_PLATFORM_VERSION", v.default_platform_version)
     if g["TARGET_PLATFORM_VERSION"] not in allowed_versions:
         fail("% is not valid, must be one of %s" % (g["TARGET_PLATFORM_VERSION"], allowed_versions))
 
-    g["DEFAULT_PLATFORM_VERSION"] = v_default
-    g["PLATFORM_VERSION_LAST_STABLE"] = 11
-    g.setdefault("PLATFORM_VERSION_CODENAME", g["TARGET_PLATFORM_VERSION"])
+    g["DEFAULT_PLATFORM_VERSION"] = v.default_platform_version
+    g["PLATFORM_VERSION_LAST_STABLE"] = v.platform_version_last_stable
+    target_platform_version = g["TARGET_PLATFORM_VERSION"]
+    if v.codenames[target_platform_version]:
+        g.setdefault("PLATFORM_VERSION_CODENAME", v.codenames[target_platform_version])
+    else:
+        g.setdefault("PLATFORM_VERSION_CODENAME", target_platform_version)
     # TODO(asmundak): set PLATFORM_VERSION_ALL_CODENAMES
 
-    g.setdefault("PLATFORM_SDK_VERSION", 30)
+    g.setdefault("PLATFORM_SDK_VERSION", v.platform_sdk_version)
     version_codename = g["PLATFORM_VERSION_CODENAME"]
     if version_codename == "REL":
         g.setdefault("PLATFORM_VERSION", g["PLATFORM_VERSION_LAST_STABLE"])
@@ -92,7 +96,8 @@
     #  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.
-    g.setdefault("PLATFORM_SECURITY_PATCH", "2021-03-05")
+
+    g.setdefault("PLATFORM_SECURITY_PATCH", v.platform_security_patch)
     dt = 'TZ="GMT" %s' % g["PLATFORM_SECURITY_PATCH"]
     g.setdefault("PLATFORM_SECURITY_PATCH_TIMESTAMP", rblf_shell("date -d '%s' +%%s" % dt))
 
@@ -116,16 +121,23 @@
     # in a warning being shown when any activity from the app is started.
     g.setdefault("PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION", 23)
 
-def init(g):
+    # This is the sdk extension version of this tree.
+    g["PLATFORM_SDK_EXTENSION_VERSION"] = v.platform_sdk_extension_version
+    # This is the sdk extension version that PLATFORM_SDK_VERSION ships with.
+    g["PLATFORM_BASE_SDK_EXTENSION_VERSION"] = v.platform_base_sdk_extension_version
+
+
+def init(g, v):
     """Initializes globals.
 
     The code is the Starlark counterpart of the contents of the
     envsetup.mk file.
     Args:
         g: globals dictionary
+        v: version info struct
     """
     all_versions = _all_versions()
-    _versions_default(g, all_versions)
+    _versions_default(g, all_versions, v)
     for v in all_versions:
         g["IS_AT_LEAST" + v] = True
         if v == g["TARGET_PLATFORM_VERSION"]:
@@ -210,7 +222,3 @@
 
     if g.get("TARGET_BUILD_TYPE", "") != "debug":
         g["TARGET_BUILD_TYPE"] = "release"
-
-v_default = "SP1A"
-v_min = "SP1A"
-v_max = "SP1A"
diff --git a/core/main.mk b/core/main.mk
index 6b8080c..8ba1396 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1913,6 +1913,7 @@
 docs: $(ALL_DOCS)
 
 .PHONY: sdk win_sdk winsdk-tools sdk_addon
+ifeq ($(HOST_OS),linux)
 ALL_SDK_TARGETS := $(INTERNAL_SDK_TARGET)
 sdk: $(ALL_SDK_TARGETS)
 $(call dist-for-goals,sdk win_sdk, \
@@ -1922,6 +1923,7 @@
     $(APPCOMPAT_ZIP) \
     $(INSTALLED_BUILD_PROP_TARGET) \
 )
+endif
 
 # umbrella targets to assit engineers in verifying builds
 .PHONY: java native target host java-host java-target native-host native-target \
diff --git a/core/product_config.mk b/core/product_config.mk
index 4a780b6..08974ef 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -100,6 +100,16 @@
 $(join $(patsubst %,$(1),$(3)),$(patsubst %,:$(2),$(3)))
 endef
 
+# Return empty unless the board matches
+define is-board-platform2
+$(filter $(1), $(TARGET_BOARD_PLATFORM))
+endef
+
+# Return empty unless the board is in the list
+define is-board-platform-in-list2
+$(filter $(1),$(TARGET_BOARD_PLATFORM))
+endef
+
 # ---------------------------------------------------------------
 # Check for obsolete PRODUCT- and APP- goals
 ifeq ($(CALLED_FROM_SETUP),true)
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 28b37a3..62777f9 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -17,7 +17,7 @@
 """Runtime functions."""
 
 _soong_config_namespaces_key = "$SOONG_CONFIG_NAMESPACES"
-def _global_init():
+def _global_init(version_info):
     """Returns dict created from the runtime environment."""
     globals = dict()
 
@@ -31,7 +31,7 @@
 
     globals.setdefault("PRODUCT_SOONG_NAMESPACES", [])
     globals.setdefault(_soong_config_namespaces_key, {})
-    _envsetup_init(globals)
+    _envsetup_init(globals, version_info)
 
     # Variables that should be defined.
     mandatory_vars = [
@@ -46,10 +46,8 @@
     for bv in mandatory_vars:
         if not bv in globals:
             fail(bv, " is not defined")
-
     return globals
 
-_globals_base = _global_init()
 
 def __print_attr(attr, value):
     if not value:
@@ -69,8 +67,9 @@
     else:
         fail("bad output format", _options.format)
 
-def _printvars(globals, cfg):
-    """Prints known configuration variables."""
+def _printvars(state):
+    """Prints configuration and global variables."""
+    (globals, cfg, globals_base) = state
     for attr, val in sorted(cfg.items()):
         __print_attr(attr, val)
     if _options.print_globals:
@@ -85,7 +84,7 @@
                         print("SOONG_CONFIG_" + nsname, ":=", " ".join(nsvars.keys()))
                     for var, val in sorted(nsvars.items()):
                         __print_attr("SOONG_CONFIG_%s_%s" % (nsname, var), val)
-            elif attr not in _globals_base:
+            elif attr not in globals_base:
                 __print_attr(attr, val)
 
 def __printvars_rearrange_list(value_list):
@@ -93,7 +92,7 @@
     seen = {item: 0 for item in value_list}
     return sorted(seen.keys()) if _options.rearrange == "sort" else seen.keys()
 
-def _product_configuration(top_pcm_name, top_pcm):
+def _product_configuration(top_pcm_name, top_pcm, version_info):
     """Creates configuration."""
 
     # Product configuration is created by traversing product's inheritance
@@ -107,7 +106,8 @@
     # PCM means "Product Configuration Module", i.e., a Starlark file
     # whose body consists of a single init function.
 
-    globals = dict(**_globals_base)
+    globals_base = _global_init(version_info)
+    globals = dict(**globals_base)
 
     config_postfix = []  # Configs in postfix order
 
@@ -198,7 +198,7 @@
         _percolate_inherited(configs, pcm_name, cfg, children_names)
         configs[pcm_name] = pcm, cfg, children_names, True
 
-    return globals, configs[top_pcm_name][1]
+    return (globals, configs[top_pcm_name][1], globals_base)
 
 def _substitute_inherited(configs, pcm_name, cfg):
     """Substitutes inherited values in all the attributes.
@@ -526,6 +526,8 @@
     That is, removes string's leading and trailing whitespace characters and
     replaces any sequence of whitespace characters with with a single space.
     """
+    if type(s) != "string":
+        return s
     result = ""
     was_space = False
     for ch in s.strip().elems():
diff --git a/core/rbe.mk b/core/rbe.mk
index 19c0e42..370d4bd 100644
--- a/core/rbe.mk
+++ b/core/rbe.mk
@@ -22,6 +22,18 @@
     rbe_dir := prebuilts/remoteexecution-client/live/
   endif
 
+  ifdef RBE_CXX_POOL
+    cxx_pool := $(RBE_CXX_POOL)
+  else
+    cxx_pool := default
+  endif
+
+  ifdef RBE_JAVA_POOL
+    java_pool := $(RBE_JAVA_POOL)
+  else
+    java_pool := java16
+  endif
+
   ifdef RBE_CXX_EXEC_STRATEGY
     cxx_rbe_exec_strategy := $(RBE_CXX_EXEC_STRATEGY)
   else
@@ -59,8 +71,8 @@
   endif
 
   platform := container-image=docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62
-  cxx_platform := $(platform),Pool=default
-  java_r8_d8_platform := $(platform),Pool=java16
+  cxx_platform := $(platform),Pool=$(cxx_pool)
+  java_r8_d8_platform := $(platform),Pool=$(java_pool)
 
   RBE_WRAPPER := $(rbe_dir)/rewrapper
   RBE_CXX := --labels=type=compile,lang=cpp,compiler=clang --env_var_allowlist=PWD --exec_strategy=$(cxx_rbe_exec_strategy) --platform=$(cxx_platform) --compare=$(cxx_compare)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index a39707e..9eb02b2 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -165,6 +165,7 @@
 $(call add_json_list, VendorSnapshotDirsExcluded,        $(VENDOR_SNAPSHOT_DIRS_EXCLUDED))
 $(call add_json_list, RecoverySnapshotDirsIncluded,      $(RECOVERY_SNAPSHOT_DIRS_INCLUDED))
 $(call add_json_list, RecoverySnapshotDirsExcluded,      $(RECOVERY_SNAPSHOT_DIRS_EXCLUDED))
+$(call add_json_bool, HostFakeSnapshotEnabled,           $(HOST_FAKE_SNAPSHOT_ENABLE))
 
 $(call add_json_bool, Treble_linker_namespaces,          $(filter true,$(PRODUCT_TREBLE_LINKER_NAMESPACES)))
 $(call add_json_bool, Enforce_vintf_manifest,            $(filter true,$(PRODUCT_ENFORCE_VINTF_MANIFEST)))
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index fdd9591..16b5c49 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -25,3 +25,202 @@
 
 .PHONY: cts_v2
 cts_v2: cts
+
+# platform version check (b/32056228)
+# ============================================================
+ifneq (,$(wildcard cts/))
+  cts_platform_version_path := cts/tests/tests/os/assets/platform_versions.txt
+  cts_platform_version_string := $(shell cat $(cts_platform_version_path))
+  cts_platform_release_path := cts/tests/tests/os/assets/platform_releases.txt
+  cts_platform_release_string := $(shell cat $(cts_platform_release_path))
+
+  ifeq (,$(findstring $(PLATFORM_VERSION),$(cts_platform_version_string)))
+    define error_msg
+      ============================================================
+      Could not find version "$(PLATFORM_VERSION)" in CTS platform version file:
+      $(cts_platform_version_path)
+      Most likely PLATFORM_VERSION in build/core/version_defaults.mk
+      has changed and a new version must be added to this CTS file.
+      ============================================================
+    endef
+    $(error $(error_msg))
+  endif
+  ifeq (,$(findstring $(PLATFORM_VERSION_LAST_STABLE),$(cts_platform_release_string)))
+    define error_msg
+      ============================================================
+      Could not find version "$(PLATFORM_VERSION_LAST_STABLE)" in CTS platform release file:
+      $(cts_platform_release_path)
+      Most likely PLATFORM_VERSION_LAST_STABLE in build/core/version_defaults.mk
+      has changed and a new version must be added to this CTS file.
+      ============================================================
+    endef
+    $(error $(error_msg))
+  endif
+endif
+
+# Creates a "cts-verifier" directory that will contain:
+#
+# 1. Out directory with a "android-cts-verifier" containing the CTS Verifier
+#    and other binaries it needs.
+#
+# 2. Zipped version of the android-cts-verifier directory to be included with
+#    the build distribution.
+##
+cts-dir := $(HOST_OUT)/cts-verifier
+verifier-dir-name := android-cts-verifier
+verifier-dir := $(cts-dir)/$(verifier-dir-name)
+verifier-zip-name := $(verifier-dir-name).zip
+verifier-zip := $(cts-dir)/$(verifier-zip-name)
+
+cts : $(verifier-zip)
+$(verifier-zip): PRIVATE_DIR := $(cts-dir)
+$(verifier-zip): $(SOONG_ANDROID_CTS_VERIFIER_ZIP)
+	rm -rf $(PRIVATE_DIR)
+	mkdir -p $(PRIVATE_DIR)
+	unzip -q -d $(PRIVATE_DIR) $<
+	$(copy-file-to-target)
+
+# For producing CTS coverage reports.
+# Run "make cts-test-coverage" in the $ANDROID_BUILD_TOP directory.
+
+cts_api_coverage_exe := $(HOST_OUT_EXECUTABLES)/cts-api-coverage
+dexdeps_exe := $(HOST_OUT_EXECUTABLES)/dexdeps
+
+coverage_out := $(HOST_OUT)/cts-api-coverage
+
+api_xml_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/api.xml
+
+napi_text_description := cts/tools/cts-api-coverage/etc/ndk-api.xml
+napi_xml_description := $(coverage_out)/ndk-api.xml
+$(napi_xml_description) : $(napi_text_description) $(ACP)
+		$(hide) echo "Preparing NDK API XML: $@"
+		$(hide) mkdir -p $(dir $@)
+		$(hide) $(ACP)  $< $@
+
+system_api_xml_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/system-api.xml
+
+cts-test-coverage-report := $(coverage_out)/test-coverage.html
+cts-system-api-coverage-report := $(coverage_out)/system-api-coverage.html
+cts-system-api-xml-coverage-report := $(coverage_out)/system-api-coverage.xml
+cts-verifier-coverage-report := $(coverage_out)/verifier-coverage.html
+cts-combined-coverage-report := $(coverage_out)/combined-coverage.html
+cts-combined-xml-coverage-report := $(coverage_out)/combined-coverage.xml
+
+cts_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(api_xml_description) $(napi_xml_description)
+cts_system_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(system_api_xml_description)
+
+android_cts_zip := $(HOST_OUT)/cts/android-cts.zip
+cts_verifier_apk := $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk
+
+$(cts-test-coverage-report): PRIVATE_TEST_CASES := $(COMPATIBILITY_TESTCASES_OUT_cts)
+$(cts-test-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
+$(cts-test-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
+$(cts-test-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
+$(cts-test-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
+$(cts-test-coverage-report) : $(android_cts_zip) $(cts_api_coverage_dependencies) | $(ACP)
+	$(call generate-coverage-report-cts,"CTS Tests API-NDK Coverage Report",\
+			$(PRIVATE_TEST_CASES),html)
+
+$(cts-system-api-coverage-report): PRIVATE_TEST_CASES := $(COMPATIBILITY_TESTCASES_OUT_cts)
+$(cts-system-api-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
+$(cts-system-api-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
+$(cts-system-api-coverage-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-system-api-coverage-report): PRIVATE_NAPI_XML_DESC := ""
+$(cts-system-api-coverage-report) : $(android_cts_zip) $(cts_system_api_coverage_dependencies) | $(ACP)
+	$(call generate-coverage-report-cts,"CTS System API Coverage Report",\
+			$(PRIVATE_TEST_CASES),html)
+
+$(cts-system-api-xml-coverage-report): PRIVATE_TEST_CASES := $(COMPATIBILITY_TESTCASES_OUT_cts)
+$(cts-system-api-xml-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
+$(cts-system-api-xml-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
+$(cts-system-api-xml-coverage-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-system-api-xml-coverage-report): PRIVATE_NAPI_XML_DESC := ""
+$(cts-system-api-xml-coverage-report) : $(android_cts_zip) $(cts_system_api_coverage_dependencies) | $(ACP)
+	$(call generate-coverage-report-cts,"CTS System API Coverage Report - XML",\
+			$(PRIVATE_TEST_CASES),xml)
+
+$(cts-verifier-coverage-report): PRIVATE_TEST_CASES := $(cts_verifier_apk)
+$(cts-verifier-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
+$(cts-verifier-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
+$(cts-verifier-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
+$(cts-verifier-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
+$(cts-verifier-coverage-report) : $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+	$(call generate-coverage-report-cts,"CTS Verifier API Coverage Report",\
+			$(PRIVATE_TEST_CASES),html)
+
+$(cts-combined-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts), $(c))
+$(cts-combined-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
+$(cts-combined-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
+$(cts-combined-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
+$(cts-combined-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
+$(cts-combined-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+	$(call generate-coverage-report-cts,"CTS Combined API Coverage Report",\
+			$(PRIVATE_TEST_CASES),html)
+
+$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts), $(c))
+$(cts-combined-xml-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
+$(cts-combined-xml-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
+$(cts-combined-xml-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
+$(cts-combined-xml-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
+$(cts-combined-xml-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+	$(call generate-coverage-report-cts,"CTS Combined API Coverage Report - XML",\
+			$(PRIVATE_TEST_CASES),xml)
+
+.PHONY: cts-test-coverage
+cts-test-coverage : $(cts-test-coverage-report)
+
+.PHONY: cts-system-api-coverage
+cts-system-api-coverage : $(cts-system-api-coverage-report)
+
+.PHONY: cts-system-api-xml-coverage
+cts-system-api-xml-coverage : $(cts-system-api-xml-coverage-report)
+
+.PHONY: cts-verifier-coverage
+cts-verifier-coverage : $(cts-verifier-coverage-report)
+
+.PHONY: cts-combined-coverage
+cts-combined-coverage : $(cts-combined-coverage-report)
+
+.PHONY: cts-combined-xml-coverage
+cts-combined-xml-coverage : $(cts-combined-xml-coverage-report)
+
+.PHONY: cts-coverage-report-all cts-api-coverage
+cts-coverage-report-all: cts-test-coverage cts-verifier-coverage cts-combined-coverage cts-combined-xml-coverage
+
+# Put the test coverage report in the dist dir if "cts-api-coverage" is among the build goals.
+$(call dist-for-goals, cts-api-coverage, $(cts-test-coverage-report):cts-test-coverage-report.html)
+$(call dist-for-goals, cts-api-coverage, $(cts-system-api-coverage-report):cts-system-api-coverage-report.html)
+$(call dist-for-goals, cts-api-coverage, $(cts-system-api-xml-coverage-report):cts-system-api-coverage-report.xml)
+$(call dist-for-goals, cts-api-coverage, $(cts-verifier-coverage-report):cts-verifier-coverage-report.html)
+$(call dist-for-goals, cts-api-coverage, $(cts-combined-coverage-report):cts-combined-coverage-report.html)
+$(call dist-for-goals, cts-api-coverage, $(cts-combined-xml-coverage-report):cts-combined-coverage-report.xml)
+
+# Arguments;
+#  1 - Name of the report printed out on the screen
+#  2 - List of apk files that will be scanned to generate the report
+#  3 - Format of the report
+define generate-coverage-report-cts
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(PRIVATE_CTS_API_COVERAGE_EXE) -d $(PRIVATE_DEXDEPS_EXE) -a $(PRIVATE_API_XML_DESC) -n $(PRIVATE_NAPI_XML_DESC) -f $(3) -o $@ $(2)
+	@ echo $(1): file://$$(cd $(dir $@); pwd)/$(notdir $@)
+endef
+
+# Reset temp vars
+cts_api_coverage_dependencies :=
+cts_system_api_coverage_dependencies :=
+cts-combined-coverage-report :=
+cts-combined-xml-coverage-report :=
+cts-verifier-coverage-report :=
+cts-test-coverage-report :=
+cts-system-api-coverage-report :=
+cts-system-api-xml-coverage-report :=
+api_xml_description :=
+api_text_description :=
+system_api_xml_description :=
+napi_xml_description :=
+napi_text_description :=
+coverage_out :=
+dexdeps_exe :=
+cts_api_coverage_exe :=
+cts_verifier_apk :=
+android_cts_zip :=
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index c8fa49f..dbb1def 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -40,51 +40,10 @@
 endif
 
 DEFAULT_PLATFORM_VERSION := TP1A
+.KATI_READONLY := DEFAULT_PLATFORM_VERSION
 MIN_PLATFORM_VERSION := TP1A
 MAX_PLATFORM_VERSION := TP1A
 
-ALLOWED_VERSIONS := $(call allowed-platform-versions,\
-  $(MIN_PLATFORM_VERSION),\
-  $(MAX_PLATFORM_VERSION),\
-  $(DEFAULT_PLATFORM_VERSION))
-
-ifndef TARGET_PLATFORM_VERSION
-  TARGET_PLATFORM_VERSION := $(DEFAULT_PLATFORM_VERSION)
-endif
-
-ifeq (,$(filter $(ALLOWED_VERSIONS), $(TARGET_PLATFORM_VERSION)))
-  $(warning Invalid TARGET_PLATFORM_VERSION '$(TARGET_PLATFORM_VERSION)', must be one of)
-  $(error $(ALLOWED_VERSIONS))
-endif
-ALLOWED_VERSIONS :=
-MIN_PLATFORM_VERSION :=
-MAX_PLATFORM_VERSION :=
-
-.KATI_READONLY := \
-  DEFAULT_PLATFORM_VERSION \
-  TARGET_PLATFORM_VERSION
-
-# Default versions for each TARGET_PLATFORM_VERSION
-# TODO: PLATFORM_VERSION, PLATFORM_SDK_VERSION, etc. should be conditional
-# on this
-
-# This is the canonical definition of the platform version,
-# which is the version that we reveal to the end user.
-# Update this value when the platform version changes (rather
-# than overriding it somewhere else).  Can be an arbitrary string.
-
-# When you change PLATFORM_VERSION for a given PLATFORM_SDK_VERSION
-# please add that PLATFORM_VERSION as well as clean up obsolete PLATFORM_VERSION's
-# in the following text file:
-# cts/tests/tests/os/assets/platform_versions.txt
-
-# Note that there should be one PLATFORM_VERSION and PLATFORM_VERSION_CODENAME
-# entry for each unreleased API level, regardless of
-# MIN_PLATFORM_VERSION/MAX_PLATFORM_VERSION. PLATFORM_VERSION is used to
-# generate the range of allowed SDK versions, so it must have an entry for every
-# unreleased API level targetable by this branch, not just those that are valid
-# lunch targets for this branch.
-
 # The last stable version name of the platform that was released.  During
 # development, this stays at that previous version, while the codename indicates
 # further work based on the previous version.
@@ -96,49 +55,6 @@
 PLATFORM_VERSION_CODENAME.SP1A := S
 PLATFORM_VERSION_CODENAME.TP1A := Tiramisu
 
-ifndef PLATFORM_VERSION_CODENAME
-  PLATFORM_VERSION_CODENAME := $(PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION))
-  ifndef PLATFORM_VERSION_CODENAME
-    # PLATFORM_VERSION_CODENAME falls back to TARGET_PLATFORM_VERSION
-    PLATFORM_VERSION_CODENAME := $(TARGET_PLATFORM_VERSION)
-  endif
-
-  # This is all of the *active* development codenames.
-  # This confusing name is needed because
-  # all_codenames has been baked into build.prop for ages.
-  #
-  # Should be either the same as PLATFORM_VERSION_CODENAME or a comma-separated
-  # list of additional codenames after PLATFORM_VERSION_CODENAME.
-  PLATFORM_VERSION_ALL_CODENAMES :=
-
-  # Build a list of all active code names. Avoid duplicates, and stop when we
-  # reach a codename that matches PLATFORM_VERSION_CODENAME (anything beyond
-  # that is not included in our build).
-  _versions_in_target := \
-    $(call find_and_earlier,$(ALL_VERSIONS),$(TARGET_PLATFORM_VERSION))
-  $(foreach version,$(_versions_in_target),\
-    $(eval _codename := $(PLATFORM_VERSION_CODENAME.$(version)))\
-    $(if $(filter $(_codename),$(PLATFORM_VERSION_ALL_CODENAMES)),,\
-      $(eval PLATFORM_VERSION_ALL_CODENAMES += $(_codename))))
-
-  # And convert from space separated to comma separated.
-  PLATFORM_VERSION_ALL_CODENAMES := \
-    $(subst $(space),$(comma),$(strip $(PLATFORM_VERSION_ALL_CODENAMES)))
-
-endif
-.KATI_READONLY := \
-  PLATFORM_VERSION_CODENAME \
-  PLATFORM_VERSION_ALL_CODENAMES
-
-ifndef PLATFORM_VERSION
-  ifeq (REL,$(PLATFORM_VERSION_CODENAME))
-      PLATFORM_VERSION := $(PLATFORM_VERSION_LAST_STABLE)
-  else
-      PLATFORM_VERSION := $(PLATFORM_VERSION_CODENAME)
-  endif
-endif
-.KATI_READONLY := PLATFORM_VERSION
-
 ifndef PLATFORM_SDK_VERSION
   # This is the canonical definition of the SDK version, which defines
   # the set of APIs and functionality available in the platform.  It
@@ -157,89 +73,13 @@
 .KATI_READONLY := PLATFORM_SDK_VERSION
 
 # This is the sdk extension version of this tree.
-PLATFORM_SDK_EXTENSION_VERSION :=$= 0
+PLATFORM_SDK_EXTENSION_VERSION := 0
+.KATI_READONLY := PLATFORM_SDK_EXTENSION_VERSION
+
 
 # This is the sdk extension version that PLATFORM_SDK_VERSION ships with.
-PLATFORM_BASE_SDK_EXTENSION_VERSION :=$= 0
-
-ifeq (REL,$(PLATFORM_VERSION_CODENAME))
-  PLATFORM_PREVIEW_SDK_VERSION := 0
-else
-  ifndef PLATFORM_PREVIEW_SDK_VERSION
-    # This is the definition of a preview SDK version over and above the current
-    # platform SDK version. Unlike the platform SDK version, a higher value
-    # for preview SDK version does NOT mean that all prior preview APIs are
-    # included. Packages reading this value to determine compatibility with
-    # known APIs should check that this value is precisely equal to the preview
-    # SDK version the package was built for, otherwise it should fall back to
-    # assuming the device can only support APIs as of the previous official
-    # public release.
-    # This value will always be forced to 0 for release builds by the logic
-    # in the "ifeq" block above, so the value below will be used on any
-    # non-release builds, and it should always be at least 1, to indicate that
-    # APIs may have changed since the claimed PLATFORM_SDK_VERSION.
-    PLATFORM_PREVIEW_SDK_VERSION := 1
-  endif
-endif
-.KATI_READONLY := PLATFORM_PREVIEW_SDK_VERSION
-
-ifndef DEFAULT_APP_TARGET_SDK
-  # This is the default minSdkVersion and targetSdkVersion to use for
-  # all .apks created by the build system.  It can be overridden by explicitly
-  # setting these in the .apk's AndroidManifest.xml.  It is either the code
-  # name of the development build or, if this is a release build, the official
-  # SDK version of this release.
-  ifeq (REL,$(PLATFORM_VERSION_CODENAME))
-    DEFAULT_APP_TARGET_SDK := $(PLATFORM_SDK_VERSION)
-  else
-    DEFAULT_APP_TARGET_SDK := $(PLATFORM_VERSION_CODENAME)
-  endif
-endif
-.KATI_READONLY := DEFAULT_APP_TARGET_SDK
-
-ifndef PLATFORM_VNDK_VERSION
-  # This is the definition of the VNDK version for the current VNDK libraries.
-  # The version is only available when PLATFORM_VERSION_CODENAME == REL.
-  # Otherwise, it will be set to a CODENAME version. The ABI is allowed to be
-  # changed only before the Android version is released. Once
-  # PLATFORM_VNDK_VERSION is set to actual version, the ABI for this version
-  # will be frozon and emit build errors if any ABI for the VNDK libs are
-  # changed.
-  # After that the snapshot of the VNDK with this version will be generated.
-  #
-  # The VNDK version follows PLATFORM_SDK_VERSION.
-  ifeq (REL,$(PLATFORM_VERSION_CODENAME))
-    PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
-  else
-    PLATFORM_VNDK_VERSION := $(PLATFORM_VERSION_CODENAME)
-  endif
-endif
-.KATI_READONLY := PLATFORM_VNDK_VERSION
-
-ifndef PLATFORM_SYSTEMSDK_MIN_VERSION
-  # This is the oldest version of system SDK that the platform supports. Contrary
-  # to the public SDK where platform essentially supports all previous SDK versions,
-  # platform supports only a few number of recent system SDK versions as some of
-  # old system APIs are gradually deprecated, removed and then deleted.
-  PLATFORM_SYSTEMSDK_MIN_VERSION := 28
-endif
-.KATI_READONLY := PLATFORM_SYSTEMSDK_MIN_VERSION
-
-# This is the list of system SDK versions that the current platform supports.
-PLATFORM_SYSTEMSDK_VERSIONS :=
-ifneq (,$(PLATFORM_SYSTEMSDK_MIN_VERSION))
-  $(if $(call math_is_number,$(PLATFORM_SYSTEMSDK_MIN_VERSION)),,\
-    $(error PLATFORM_SYSTEMSDK_MIN_VERSION must be a number, but was $(PLATFORM_SYSTEMSDK_MIN_VERSION)))
-  PLATFORM_SYSTEMSDK_VERSIONS := $(call int_range_list,$(PLATFORM_SYSTEMSDK_MIN_VERSION),$(PLATFORM_SDK_VERSION))
-endif
-# Platform always supports the current version
-ifeq (REL,$(PLATFORM_VERSION_CODENAME))
-  PLATFORM_SYSTEMSDK_VERSIONS += $(PLATFORM_SDK_VERSION)
-else
-  PLATFORM_SYSTEMSDK_VERSIONS += $(subst $(comma),$(space),$(PLATFORM_VERSION_ALL_CODENAMES))
-endif
-PLATFORM_SYSTEMSDK_VERSIONS := $(strip $(sort $(PLATFORM_SYSTEMSDK_VERSIONS)))
-.KATI_READONLY := PLATFORM_SYSTEMSDK_VERSIONS
+PLATFORM_BASE_SDK_EXTENSION_VERSION := 0
+.KATI_READONLY := PLATFORM_BASE_SDK_EXTENSION_VERSION
 
 ifndef PLATFORM_SECURITY_PATCH
     #  Used to indicate the security patch that has been applied to the device.
@@ -251,65 +91,5 @@
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
-ifndef PLATFORM_SECURITY_PATCH_TIMESTAMP
-  # Used to indicate the matching timestamp for the security patch string in PLATFORM_SECURITY_PATCH.
-  PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
-endif
-.KATI_READONLY := PLATFORM_SECURITY_PATCH_TIMESTAMP
+include $(BUILD_SYSTEM)/version_util.mk
 
-ifndef PLATFORM_BASE_OS
-  # Used to indicate the base os applied to the device.
-  # Can be an arbitrary string, but must be a single word.
-  #
-  # If there is no $PLATFORM_BASE_OS set, keep it empty.
-  PLATFORM_BASE_OS :=
-endif
-.KATI_READONLY := PLATFORM_BASE_OS
-
-ifndef BUILD_ID
-  # Used to signify special builds.  E.g., branches and/or releases,
-  # like "M5-RC7".  Can be an arbitrary string, but must be a single
-  # word and a valid file name.
-  #
-  # If there is no BUILD_ID set, make it obvious.
-  BUILD_ID := UNKNOWN
-endif
-.KATI_READONLY := BUILD_ID
-
-ifndef BUILD_DATETIME
-  # Used to reproduce builds by setting the same time. Must be the number
-  # of seconds since the Epoch.
-  BUILD_DATETIME := $(shell date +%s)
-endif
-
-DATE := date -d @$(BUILD_DATETIME)
-.KATI_READONLY := DATE
-
-# Everything should be using BUILD_DATETIME_FROM_FILE instead.
-# BUILD_DATETIME and DATE can be removed once BUILD_NUMBER moves
-# to soong_ui.
-$(KATI_obsolete_var BUILD_DATETIME,Use BUILD_DATETIME_FROM_FILE)
-
-HAS_BUILD_NUMBER := true
-ifndef BUILD_NUMBER
-  # BUILD_NUMBER should be set to the source control value that
-  # represents the current state of the source code.  E.g., a
-  # perforce changelist number or a git hash.  Can be an arbitrary string
-  # (to allow for source control that uses something other than numbers),
-  # but must be a single word and a valid file name.
-  #
-  # If no BUILD_NUMBER is set, create a useful "I am an engineering build
-  # from this date/time" value.  Make it start with a non-digit so that
-  # anyone trying to parse it as an integer will probably get "0".
-  BUILD_NUMBER := eng.$(shell echo $${BUILD_USERNAME:0:6}).$(shell $(DATE) +%Y%m%d.%H%M%S)
-  HAS_BUILD_NUMBER := false
-endif
-.KATI_READONLY := BUILD_NUMBER HAS_BUILD_NUMBER
-
-ifndef PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION
-  # Used to set minimum supported target sdk version. Apps targeting sdk
-  # version lower than the set value will result in a warning being shown
-  # when any activity from the app is started.
-  PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23
-endif
-.KATI_READONLY := PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION
diff --git a/core/version_util.mk b/core/version_util.mk
new file mode 100644
index 0000000..b7c4e48
--- /dev/null
+++ b/core/version_util.mk
@@ -0,0 +1,245 @@
+#
+# 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.
+#
+
+#
+
+ALLOWED_VERSIONS := $(call allowed-platform-versions,\
+  $(MIN_PLATFORM_VERSION),\
+  $(MAX_PLATFORM_VERSION),\
+  $(DEFAULT_PLATFORM_VERSION))
+
+ifndef TARGET_PLATFORM_VERSION
+  TARGET_PLATFORM_VERSION := $(DEFAULT_PLATFORM_VERSION)
+endif
+
+ifeq (,$(filter $(ALLOWED_VERSIONS), $(TARGET_PLATFORM_VERSION)))
+  $(warning Invalid TARGET_PLATFORM_VERSION '$(TARGET_PLATFORM_VERSION)', must be one of)
+  $(error $(ALLOWED_VERSIONS))
+endif
+ALLOWED_VERSIONS :=
+MIN_PLATFORM_VERSION :=
+MAX_PLATFORM_VERSION :=
+
+.KATI_READONLY := TARGET_PLATFORM_VERSION
+
+# Default versions for each TARGET_PLATFORM_VERSION
+# TODO: PLATFORM_VERSION, PLATFORM_SDK_VERSION, etc. should be conditional
+# on this
+
+# This is the canonical definition of the platform version,
+# which is the version that we reveal to the end user.
+# Update this value when the platform version changes (rather
+# than overriding it somewhere else).  Can be an arbitrary string.
+
+# When you change PLATFORM_VERSION for a given PLATFORM_SDK_VERSION
+# please add that PLATFORM_VERSION as well as clean up obsolete PLATFORM_VERSION's
+# in the following text file:
+# cts/tests/tests/os/assets/platform_versions.txt
+
+# Note that there should be one PLATFORM_VERSION and PLATFORM_VERSION_CODENAME
+# entry for each unreleased API level, regardless of
+# MIN_PLATFORM_VERSION/MAX_PLATFORM_VERSION. PLATFORM_VERSION is used to
+# generate the range of allowed SDK versions, so it must have an entry for every
+# unreleased API level targetable by this branch, not just those that are valid
+# lunch targets for this branch.
+
+ifndef PLATFORM_VERSION_CODENAME
+  PLATFORM_VERSION_CODENAME := $(PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION))
+  ifndef PLATFORM_VERSION_CODENAME
+    # PLATFORM_VERSION_CODENAME falls back to TARGET_PLATFORM_VERSION
+    PLATFORM_VERSION_CODENAME := $(TARGET_PLATFORM_VERSION)
+  endif
+
+  # This is all of the *active* development codenames.
+  # This confusing name is needed because
+  # all_codenames has been baked into build.prop for ages.
+  #
+  # Should be either the same as PLATFORM_VERSION_CODENAME or a comma-separated
+  # list of additional codenames after PLATFORM_VERSION_CODENAME.
+  PLATFORM_VERSION_ALL_CODENAMES :=
+
+  # Build a list of all active code names. Avoid duplicates, and stop when we
+  # reach a codename that matches PLATFORM_VERSION_CODENAME (anything beyond
+  # that is not included in our build).
+  _versions_in_target := \
+    $(call find_and_earlier,$(ALL_VERSIONS),$(TARGET_PLATFORM_VERSION))
+  $(foreach version,$(_versions_in_target),\
+    $(eval _codename := $(PLATFORM_VERSION_CODENAME.$(version)))\
+    $(if $(filter $(_codename),$(PLATFORM_VERSION_ALL_CODENAMES)),,\
+      $(eval PLATFORM_VERSION_ALL_CODENAMES += $(_codename))))
+
+  # And convert from space separated to comma separated.
+  PLATFORM_VERSION_ALL_CODENAMES := \
+    $(subst $(space),$(comma),$(strip $(PLATFORM_VERSION_ALL_CODENAMES)))
+
+endif
+.KATI_READONLY := \
+  PLATFORM_VERSION_CODENAME \
+  PLATFORM_VERSION_ALL_CODENAMES
+
+ifndef PLATFORM_VERSION
+  ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+      PLATFORM_VERSION := $(PLATFORM_VERSION_LAST_STABLE)
+  else
+      PLATFORM_VERSION := $(PLATFORM_VERSION_CODENAME)
+  endif
+endif
+.KATI_READONLY := PLATFORM_VERSION
+
+
+ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+  PLATFORM_PREVIEW_SDK_VERSION := 0
+else
+  ifndef PLATFORM_PREVIEW_SDK_VERSION
+    # This is the definition of a preview SDK version over and above the current
+    # platform SDK version. Unlike the platform SDK version, a higher value
+    # for preview SDK version does NOT mean that all prior preview APIs are
+    # included. Packages reading this value to determine compatibility with
+    # known APIs should check that this value is precisely equal to the preview
+    # SDK version the package was built for, otherwise it should fall back to
+    # assuming the device can only support APIs as of the previous official
+    # public release.
+    # This value will always be forced to 0 for release builds by the logic
+    # in the "ifeq" block above, so the value below will be used on any
+    # non-release builds, and it should always be at least 1, to indicate that
+    # APIs may have changed since the claimed PLATFORM_SDK_VERSION.
+    PLATFORM_PREVIEW_SDK_VERSION := 1
+  endif
+endif
+.KATI_READONLY := PLATFORM_PREVIEW_SDK_VERSION
+
+ifndef DEFAULT_APP_TARGET_SDK
+  # This is the default minSdkVersion and targetSdkVersion to use for
+  # all .apks created by the build system.  It can be overridden by explicitly
+  # setting these in the .apk's AndroidManifest.xml.  It is either the code
+  # name of the development build or, if this is a release build, the official
+  # SDK version of this release.
+  ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+    DEFAULT_APP_TARGET_SDK := $(PLATFORM_SDK_VERSION)
+  else
+    DEFAULT_APP_TARGET_SDK := $(PLATFORM_VERSION_CODENAME)
+  endif
+endif
+.KATI_READONLY := DEFAULT_APP_TARGET_SDK
+
+ifndef PLATFORM_VNDK_VERSION
+  # This is the definition of the VNDK version for the current VNDK libraries.
+  # The version is only available when PLATFORM_VERSION_CODENAME == REL.
+  # Otherwise, it will be set to a CODENAME version. The ABI is allowed to be
+  # changed only before the Android version is released. Once
+  # PLATFORM_VNDK_VERSION is set to actual version, the ABI for this version
+  # will be frozon and emit build errors if any ABI for the VNDK libs are
+  # changed.
+  # After that the snapshot of the VNDK with this version will be generated.
+  #
+  # The VNDK version follows PLATFORM_SDK_VERSION.
+  ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+    PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
+  else
+    PLATFORM_VNDK_VERSION := $(PLATFORM_VERSION_CODENAME)
+  endif
+endif
+.KATI_READONLY := PLATFORM_VNDK_VERSION
+
+ifndef PLATFORM_SYSTEMSDK_MIN_VERSION
+  # This is the oldest version of system SDK that the platform supports. Contrary
+  # to the public SDK where platform essentially supports all previous SDK versions,
+  # platform supports only a few number of recent system SDK versions as some of
+  # old system APIs are gradually deprecated, removed and then deleted.
+  PLATFORM_SYSTEMSDK_MIN_VERSION := 28
+endif
+.KATI_READONLY := PLATFORM_SYSTEMSDK_MIN_VERSION
+
+# This is the list of system SDK versions that the current platform supports.
+PLATFORM_SYSTEMSDK_VERSIONS :=
+ifneq (,$(PLATFORM_SYSTEMSDK_MIN_VERSION))
+  $(if $(call math_is_number,$(PLATFORM_SYSTEMSDK_MIN_VERSION)),,\
+    $(error PLATFORM_SYSTEMSDK_MIN_VERSION must be a number, but was $(PLATFORM_SYSTEMSDK_MIN_VERSION)))
+  PLATFORM_SYSTEMSDK_VERSIONS := $(call int_range_list,$(PLATFORM_SYSTEMSDK_MIN_VERSION),$(PLATFORM_SDK_VERSION))
+endif
+# Platform always supports the current version
+ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+  PLATFORM_SYSTEMSDK_VERSIONS += $(PLATFORM_SDK_VERSION)
+else
+  PLATFORM_SYSTEMSDK_VERSIONS += $(subst $(comma),$(space),$(PLATFORM_VERSION_ALL_CODENAMES))
+endif
+PLATFORM_SYSTEMSDK_VERSIONS := $(strip $(sort $(PLATFORM_SYSTEMSDK_VERSIONS)))
+.KATI_READONLY := PLATFORM_SYSTEMSDK_VERSIONS
+
+.KATI_READONLY := PLATFORM_SECURITY_PATCH
+
+ifndef PLATFORM_SECURITY_PATCH_TIMESTAMP
+  # Used to indicate the matching timestamp for the security patch string in PLATFORM_SECURITY_PATCH.
+  PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
+endif
+.KATI_READONLY := PLATFORM_SECURITY_PATCH_TIMESTAMP
+
+ifndef PLATFORM_BASE_OS
+  # Used to indicate the base os applied to the device.
+  # Can be an arbitrary string, but must be a single word.
+  #
+  # If there is no $PLATFORM_BASE_OS set, keep it empty.
+  PLATFORM_BASE_OS :=
+endif
+.KATI_READONLY := PLATFORM_BASE_OS
+
+ifndef BUILD_ID
+  # Used to signify special builds.  E.g., branches and/or releases,
+  # like "M5-RC7".  Can be an arbitrary string, but must be a single
+  # word and a valid file name.
+  #
+  # If there is no BUILD_ID set, make it obvious.
+  BUILD_ID := UNKNOWN
+endif
+.KATI_READONLY := BUILD_ID
+
+ifndef BUILD_DATETIME
+  # Used to reproduce builds by setting the same time. Must be the number
+  # of seconds since the Epoch.
+  BUILD_DATETIME := $(shell date +%s)
+endif
+
+DATE := date -d @$(BUILD_DATETIME)
+.KATI_READONLY := DATE
+
+# Everything should be using BUILD_DATETIME_FROM_FILE instead.
+# BUILD_DATETIME and DATE can be removed once BUILD_NUMBER moves
+# to soong_ui.
+$(KATI_obsolete_var BUILD_DATETIME,Use BUILD_DATETIME_FROM_FILE)
+
+HAS_BUILD_NUMBER := true
+ifndef BUILD_NUMBER
+  # BUILD_NUMBER should be set to the source control value that
+  # represents the current state of the source code.  E.g., a
+  # perforce changelist number or a git hash.  Can be an arbitrary string
+  # (to allow for source control that uses something other than numbers),
+  # but must be a single word and a valid file name.
+  #
+  # If no BUILD_NUMBER is set, create a useful "I am an engineering build
+  # from this date/time" value.  Make it start with a non-digit so that
+  # anyone trying to parse it as an integer will probably get "0".
+  BUILD_NUMBER := eng.$(shell echo $${BUILD_USERNAME:0:6}).$(shell $(DATE) +%Y%m%d.%H%M%S)
+  HAS_BUILD_NUMBER := false
+endif
+.KATI_READONLY := BUILD_NUMBER HAS_BUILD_NUMBER
+
+ifndef PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION
+  # Used to set minimum supported target sdk version. Apps targeting sdk
+  # version lower than the set value will result in a warning being shown
+  # when any activity from the app is started.
+  PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23
+endif
+.KATI_READONLY := PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION
diff --git a/envsetup.sh b/envsetup.sh
index d70e815..b92e399 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -1720,14 +1720,6 @@
 
 function m()
 (
-    if [[ "${USE_BAZEL_ANALYSIS}" =~ ^(true|1)$ ]]; then
-        # This only short-circuits to Bazel for a single module target now.
-        b cquery "@soong_injection//module_name_to_label:$@" 2>/dev/null
-        if [[ $? == 0 ]]; then
-            bazel build "@soong_injection//module_name_to_label:$@" --config=bp2build
-            return $?
-        fi
-    fi
     _trigger_build "all-modules" "$@"
 )
 
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 1133564..8d8555c 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -57,12 +57,6 @@
 
 BOARD_KERNEL-4.19-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
 BOARD_KERNEL-4.19-GZ-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.4-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-5.4-GZ-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-5.4-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376
-BOARD_KERNEL-5.4-LZ4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 53477376
 BOARD_KERNEL-5.10_BOOTIMAGE_PARTITION_SIZE := 67108864
 BOARD_KERNEL-5.10-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
 BOARD_KERNEL-5.10-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
@@ -77,14 +71,12 @@
 
 BOARD_KERNEL_BINARIES := \
     kernel-4.19-gz \
-    kernel-5.4 kernel-5.4-gz kernel-5.4-lz4 \
     kernel-5.10 kernel-5.10-gz kernel-5.10-lz4 \
     kernel-mainline kernel-mainline-gz kernel-mainline-lz4 \
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 BOARD_KERNEL_BINARIES += \
     kernel-4.19-gz-allsyms \
-    kernel-5.4-allsyms kernel-5.4-gz-allsyms kernel-5.4-lz4-allsyms \
     kernel-5.10-allsyms kernel-5.10-gz-allsyms kernel-5.10-lz4-allsyms \
 
 endif
diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk
index 0064aec..fe56fd3 100644
--- a/target/board/generic_arm64/device.mk
+++ b/target/board/generic_arm64/device.mk
@@ -16,9 +16,6 @@
 
 PRODUCT_COPY_FILES += \
     kernel/prebuilts/4.19/arm64/kernel-4.19-gz:kernel-4.19-gz \
-    kernel/prebuilts/5.4/arm64/kernel-5.4:kernel-5.4 \
-    kernel/prebuilts/5.4/arm64/kernel-5.4-gz:kernel-5.4-gz \
-    kernel/prebuilts/5.4/arm64/kernel-5.4-lz4:kernel-5.4-lz4 \
     kernel/prebuilts/5.10/arm64/kernel-5.10:kernel-5.10 \
     kernel/prebuilts/5.10/arm64/kernel-5.10-gz:kernel-5.10-gz \
     kernel/prebuilts/5.10/arm64/kernel-5.10-lz4:kernel-5.10-lz4 \
@@ -27,16 +24,12 @@
     kernel/prebuilts/mainline/arm64/kernel-mainline-lz4-allsyms:kernel-mainline-lz4 \
 
 $(call dist-for-goals, dist_files, kernel/prebuilts/4.19/arm64/prebuilt-info.txt:kernel/4.19/prebuilt-info.txt)
-$(call dist-for-goals, dist_files, kernel/prebuilts/5.4/arm64/prebuilt-info.txt:kernel/5.4/prebuilt-info.txt)
 $(call dist-for-goals, dist_files, kernel/prebuilts/5.10/arm64/prebuilt-info.txt:kernel/5.10/prebuilt-info.txt)
 $(call dist-for-goals, dist_files, kernel/prebuilts/mainline/arm64/prebuilt-info.txt:kernel/mainline/prebuilt-info.txt)
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 PRODUCT_COPY_FILES += \
     kernel/prebuilts/4.19/arm64/kernel-4.19-gz-allsyms:kernel-4.19-gz-allsyms \
-    kernel/prebuilts/5.4/arm64/kernel-5.4-allsyms:kernel-5.4-allsyms \
-    kernel/prebuilts/5.4/arm64/kernel-5.4-gz-allsyms:kernel-5.4-gz-allsyms \
-    kernel/prebuilts/5.4/arm64/kernel-5.4-lz4-allsyms:kernel-5.4-lz4-allsyms \
     kernel/prebuilts/5.10/arm64/kernel-5.10-allsyms:kernel-5.10-allsyms \
     kernel/prebuilts/5.10/arm64/kernel-5.10-gz-allsyms:kernel-5.10-gz-allsyms \
     kernel/prebuilts/5.10/arm64/kernel-5.10-lz4-allsyms:kernel-5.10-lz4-allsyms \
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index bdc862e..640216c 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -28,19 +28,16 @@
 include build/make/target/board/BoardConfigGkiCommon.mk
 
 BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
 BOARD_KERNEL-5.10_BOOTIMAGE_PARTITION_SIZE := 67108864
 BOARD_KERNEL-5.10-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
 
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
 
 BOARD_KERNEL_BINARIES := \
-    kernel-5.4 \
     kernel-5.10 \
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 BOARD_KERNEL_BINARIES += \
-    kernel-5.4-allsyms \
     kernel-5.10-allsyms \
 
 endif
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index f31a491..d28ace7 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -15,15 +15,12 @@
 #
 
 PRODUCT_COPY_FILES += \
-    kernel/prebuilts/5.4/x86_64/kernel-5.4:kernel-5.4 \
     kernel/prebuilts/5.10/x86_64/kernel-5.10:kernel-5.10 \
 
-$(call dist-for-goals, dist_files, kernel/prebuilts/5.4/x86_64/prebuilt-info.txt:kernel/5.4/prebuilt-info.txt)
 $(call dist-for-goals, dist_files, kernel/prebuilts/5.10/x86_64/prebuilt-info.txt:kernel/5.10/prebuilt-info.txt)
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 PRODUCT_COPY_FILES += \
-    kernel/prebuilts/5.4/x86_64/kernel-5.4-allsyms:kernel-5.4-allsyms \
     kernel/prebuilts/5.10/x86_64/kernel-5.10-allsyms:kernel-5.10-allsyms \
 
 endif
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 755d85e..c5ec791 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -95,6 +95,20 @@
 VNDK-core: android.hardware.power.stats-V1-ndk_platform.so
 VNDK-core: android.hardware.radio-V1-ndk.so
 VNDK-core: android.hardware.radio-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.config-V1-ndk.so
+VNDK-core: android.hardware.radio.config-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.data-V1-ndk.so
+VNDK-core: android.hardware.radio.data-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.messaging-V1-ndk.so
+VNDK-core: android.hardware.radio.messaging-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.modem-V1-ndk.so
+VNDK-core: android.hardware.radio.modem-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.network-V1-ndk.so
+VNDK-core: android.hardware.radio.network-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.sim-V1-ndk.so
+VNDK-core: android.hardware.radio.sim-V1-ndk_platform.so
+VNDK-core: android.hardware.radio.voice-V1-ndk.so
+VNDK-core: android.hardware.radio.voice-V1-ndk_platform.so
 VNDK-core: android.hardware.rebootescrow-V1-ndk.so
 VNDK-core: android.hardware.rebootescrow-V1-ndk_platform.so
 VNDK-core: android.hardware.security.keymint-V1-ndk.so
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index b511aa6..1d52b9f 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -93,7 +93,7 @@
     dalvik.vm.appimageformat=lz4
 
 PRODUCT_SYSTEM_PROPERTIES += \
-    ro.dalvik.vm.native.bridge=0
+    ro.dalvik.vm.native.bridge?=0
 
 # Different dexopt types for different package update/install times.
 # On eng builds, make "boot" reasons only extract for faster turnaround.
diff --git a/tests/run.rbc b/tests/run.rbc
index 2c15b81..eef217b 100644
--- a/tests/run.rbc
+++ b/tests/run.rbc
@@ -21,15 +21,17 @@
 #  * all runtime functions (wildcard, regex, etc.) work
 
 load("//build/make/core:product_config.rbc", "rblf")
+load(":version_defaults.rbc", "version_defaults")
 load(":device.rbc", "init")
 
 def assert_eq(expected, actual):
     if expected != actual:
-        fail("Expected %s, got %s" % (expected, actual))
+        fail("Expected '%s', got '%s'" % (expected, actual))
 
 # Unit tests for non-trivial runtime functions
 assert_eq("", rblf.mkstrip(" \n \t    "))
 assert_eq("a b c", rblf.mkstrip("  a b   \n  c \t"))
+assert_eq(1, rblf.mkstrip(1))
 
 assert_eq("b1 b2", rblf.mksubst("a", "b", "a1 a2"))
 assert_eq(["b1", "x2"], rblf.mksubst("a", "b", ["a1", "x2"]))
@@ -50,7 +52,7 @@
 assert_eq([], rblf.filter(["a", "", "b"], "f"))
 assert_eq(["", "b"], rblf.filter_out(["a", "" ], ["a", "", "b"] ))
 
-globals, config = rblf.product_configuration("test/device", init)
+(globals, config, globals_base) = rblf.product_configuration("test/device", init, version_defaults)
 assert_eq(
     {
       "PRODUCT_COPY_FILES": [
@@ -87,3 +89,6 @@
     },
     {k:v for k, v in sorted(ns.items()) }
 )
+
+assert_eq("S", globals["PLATFORM_VERSION"])
+assert_eq(30, globals["PLATFORM_SDK_VERSION"])
diff --git a/tests/version_defaults.rbc b/tests/version_defaults.rbc
new file mode 100644
index 0000000..9b35b57
--- /dev/null
+++ b/tests/version_defaults.rbc
@@ -0,0 +1,11 @@
+version_defaults = struct(
+    codenames = { "SP1A" : "S" },
+    default_platform_version = "SP1A",
+    max_platform_version = "SP1A",
+    min_platform_version = "SP1A",
+    platform_base_sdk_extension_version = 0,
+    platform_sdk_extension_version = 1,
+    platform_sdk_version = 30,
+    platform_security_patch = "2021-08-05",
+    platform_version_last_stable = 11,
+)
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
new file mode 100644
index 0000000..75b0de6
--- /dev/null
+++ b/tools/BUILD.bazel
@@ -0,0 +1,20 @@
+py_library(
+    name="event_log_tags",
+    srcs = ["event_log_tags.py"],
+)
+
+py_binary(
+    name="java-event-log-tags",
+    srcs=["java-event-log-tags.py"],
+    deps=[":event_log_tags"],
+    visibility = ["//visibility:public"],
+    python_version = "PY2",
+)
+
+py_binary(
+    name="merge-event-log-tags",
+    srcs=["merge-event-log-tags.py"],
+    deps=[":event_log_tags"],
+    visibility = ["//visibility:public"],
+    python_version = "PY2",
+)
diff --git a/tools/event_log_tags.bzl b/tools/event_log_tags.bzl
new file mode 100644
index 0000000..3766da4
--- /dev/null
+++ b/tools/event_log_tags.bzl
@@ -0,0 +1,47 @@
+"""Event log tags generation rule"""
+
+load("@bazel_skylib//lib:paths.bzl", "paths")
+load("@rules_android//rules:rules.bzl", "android_library")
+
+def _event_log_tags_impl(ctx):
+    out_files = []
+    for logtag_file in ctx.files.srcs:
+        out_filename = paths.replace_extension(logtag_file.basename, ".java")
+        out_file = ctx.actions.declare_file(out_filename)
+        out_files.append(out_file)
+        ctx.actions.run(
+            inputs = [logtag_file],
+            outputs = [out_file],
+            arguments = [
+                "-o",
+                out_file.path,
+                logtag_file.path,
+            ],
+            progress_message = "Generating Java logtag file from %s" % logtag_file.short_path,
+            executable = ctx.executable._logtag_to_java_tool,
+        )
+    return [DefaultInfo(files = depset(out_files))]
+
+_event_log_tags = rule(
+    implementation = _event_log_tags_impl,
+    attrs = {
+        "srcs": attr.label_list(allow_files = [".logtags"], mandatory = True),
+        "_logtag_to_java_tool": attr.label(
+            executable = True,
+            cfg = "exec",
+            allow_files = True,
+            default = Label("//build/make/tools:java-event-log-tags"),
+        ),
+    },
+)
+
+def event_log_tags(name, srcs):
+    _event_log_tags(
+        name = name + "_gen_logtags",
+        srcs = srcs,
+    )
+
+    android_library(
+        name = name,
+        srcs = [name + "_gen_logtags"],
+    )
diff --git a/tools/generate-notice-files.py b/tools/generate-notice-files.py
index bf958fb..5e3010f 100755
--- a/tools/generate-notice-files.py
+++ b/tools/generate-notice-files.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2012 The Android Open Source Project
 #
@@ -30,20 +30,18 @@
 import os
 import os.path
 import re
+import struct
 import sys
 
 MD5_BLOCKSIZE = 1024 * 1024
 HTML_ESCAPE_TABLE = {
-    "&": "&amp;",
-    '"': "&quot;",
-    "'": "&apos;",
-    ">": "&gt;",
-    "<": "&lt;",
+    b"&": b"&amp;",
+    b'"': b"&quot;",
+    b"'": b"&apos;",
+    b">": b"&gt;",
+    b"<": b"&lt;",
     }
 
-def hexify(s):
-    return ("%02x"*len(s)) % tuple(map(ord, s))
-
 def md5sum(filename):
     """Calculate an MD5 of the file given by FILENAME,
     and return hex digest as a string.
@@ -57,20 +55,26 @@
             break
         sum.update(block)
     f.close()
-    return hexify(sum.digest())
+    return sum.hexdigest()
 
 
 def html_escape(text):
     """Produce entities within text."""
-    return "".join(HTML_ESCAPE_TABLE.get(c,c) for c in text)
+    # Using for i in text doesn't work since i will be an int, not a byte.
+    # There are multiple ways to solve this, but the most performant way
+    # to iterate over a byte array is to use unpack. Using the
+    # for i in range(len(text)) and using that to get a byte using array
+    # slices is twice as slow as this method.
+    return b"".join(HTML_ESCAPE_TABLE.get(i,i) for i in struct.unpack(str(len(text)) + 'c', text))
 
-HTML_OUTPUT_CSS="""
+HTML_OUTPUT_CSS=b"""
 <style type="text/css">
 body { padding: 0; font-family: sans-serif; }
 .same-license { background-color: #eeeeee; border-top: 20px solid white; padding: 10px; }
 .label { font-weight: bold; }
 .file-list { margin-left: 1em; color: blue; }
 </style>
+
 """
 
 def combine_notice_files_html(file_hash, input_dirs, output_filename):
@@ -90,13 +94,13 @@
     # Open the output file, and output the header pieces
     output_file = open(output_filename, "wb")
 
-    print >> output_file, "<html><head>"
-    print >> output_file, HTML_OUTPUT_CSS
-    print >> output_file, '</head><body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">'
+    output_file.write(b"<html><head>\n")
+    output_file.write(HTML_OUTPUT_CSS)
+    output_file.write(b'</head><body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">\n')
 
     # Output our table of contents
-    print >> output_file, '<div class="toc">'
-    print >> output_file, "<ul>"
+    output_file.write(b'<div class="toc">\n')
+    output_file.write(b"<ul>\n")
 
     # Flatten the list of lists into a single list of filenames
     sorted_filenames = sorted(itertools.chain.from_iterable(file_hash))
@@ -104,31 +108,29 @@
     # Print out a nice table of contents
     for filename in sorted_filenames:
         stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename)
-        print >> output_file, '<li><a href="#id%d">%s</a></li>' % (id_table.get(filename), stripped_filename)
+        output_file.write(('<li><a href="#id%d">%s</a></li>\n' % (id_table.get(filename), stripped_filename)).encode())
 
-    print >> output_file, "</ul>"
-    print >> output_file, "</div><!-- table of contents -->"
+    output_file.write(b"</ul>\n")
+    output_file.write(b"</div><!-- table of contents -->\n")
     # Output the individual notice file lists
-    print >>output_file, '<table cellpadding="0" cellspacing="0" border="0">'
+    output_file.write(b'<table cellpadding="0" cellspacing="0" border="0">\n')
     for value in file_hash:
-        print >> output_file, '<tr id="id%d"><td class="same-license">' % id_table.get(value[0])
-        print >> output_file, '<div class="label">Notices for file(s):</div>'
-        print >> output_file, '<div class="file-list">'
+        output_file.write(b'<tr id="id%d"><td class="same-license">\n' % id_table.get(value[0]))
+        output_file.write(b'<div class="label">Notices for file(s):</div>\n')
+        output_file.write(b'<div class="file-list">\n')
         for filename in value:
-            print >> output_file, "%s <br/>" % (SRC_DIR_STRIP_RE.sub(r"\1", filename))
-        print >> output_file, "</div><!-- file-list -->"
-        print >> output_file
-        print >> output_file, '<pre class="license-text">'
-        print >> output_file, html_escape(open(value[0]).read())
-        print >> output_file, "</pre><!-- license-text -->"
-        print >> output_file, "</td></tr><!-- same-license -->"
-        print >> output_file
-        print >> output_file
-        print >> output_file
+            output_file.write(("%s <br/>\n" % SRC_DIR_STRIP_RE.sub(r"\1", filename)).encode())
+        output_file.write(b"</div><!-- file-list -->\n")
+        output_file.write(b"\n")
+        output_file.write(b'<pre class="license-text">\n')
+        with open(value[0], "rb") as notice_file:
+            output_file.write(html_escape(notice_file.read()))
+        output_file.write(b"\n</pre><!-- license-text -->\n")
+        output_file.write(b"</td></tr><!-- same-license -->\n\n\n\n")
 
     # Finish off the file output
-    print >> output_file, "</table>"
-    print >> output_file, "</body></html>"
+    output_file.write(b"</table>\n")
+    output_file.write(b"</body></html>\n")
     output_file.close()
 
 def combine_notice_files_text(file_hash, input_dirs, output_filename, file_title):
@@ -136,14 +138,18 @@
 
     SRC_DIR_STRIP_RE = re.compile("(?:" + "|".join(input_dirs) + ")(/.*).txt")
     output_file = open(output_filename, "wb")
-    print >> output_file, file_title
+    output_file.write(file_title.encode())
+    output_file.write(b"\n")
     for value in file_hash:
-      print >> output_file, "============================================================"
-      print >> output_file, "Notices for file(s):"
-      for filename in value:
-        print >> output_file, SRC_DIR_STRIP_RE.sub(r"\1", filename)
-      print >> output_file, "------------------------------------------------------------"
-      print >> output_file, open(value[0]).read()
+        output_file.write(b"============================================================\n")
+        output_file.write(b"Notices for file(s):\n")
+        for filename in value:
+            output_file.write(SRC_DIR_STRIP_RE.sub(r"\1", filename).encode())
+            output_file.write(b"\n")
+        output_file.write(b"------------------------------------------------------------\n")
+        with open(value[0], "rb") as notice_file:
+            output_file.write(notice_file.read())
+            output_file.write(b"\n")
     output_file.close()
 
 def combine_notice_files_xml(files_with_same_hash, input_dirs, output_filename):
@@ -154,15 +160,15 @@
     # Set up a filename to row id table (anchors inside tables don't work in
     # most browsers, but href's to table row ids do)
     id_table = {}
-    for file_key in files_with_same_hash.keys():
-        for filename in files_with_same_hash[file_key]:
+    for file_key, files in files_with_same_hash.items():
+        for filename in files:
              id_table[filename] = file_key
 
     # Open the output file, and output the header pieces
     output_file = open(output_filename, "wb")
 
-    print >> output_file, '<?xml version="1.0" encoding="utf-8"?>'
-    print >> output_file, "<licenses>"
+    output_file.write(b'<?xml version="1.0" encoding="utf-8"?>\n')
+    output_file.write(b"<licenses>\n")
 
     # Flatten the list of lists into a single list of filenames
     sorted_filenames = sorted(id_table.keys())
@@ -170,10 +176,8 @@
     # Print out a nice table of contents
     for filename in sorted_filenames:
         stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename)
-        print >> output_file, '<file-name contentId="%s">%s</file-name>' % (id_table.get(filename), stripped_filename)
-
-    print >> output_file
-    print >> output_file
+        output_file.write(('<file-name contentId="%s">%s</file-name>\n' % (id_table.get(filename), stripped_filename)).encode())
+    output_file.write(b"\n\n")
 
     processed_file_keys = []
     # Output the individual notice file lists
@@ -183,11 +187,13 @@
             continue
         processed_file_keys.append(file_key)
 
-        print >> output_file, '<file-content contentId="%s"><![CDATA[%s]]></file-content>' % (file_key, html_escape(open(filename).read()))
-        print >> output_file
+        output_file.write(('<file-content contentId="%s"><![CDATA[' % file_key).encode())
+        with open(filename, "rb") as notice_file:
+            output_file.write(html_escape(notice_file.read()))
+        output_file.write(b"]]></file-content>\n\n")
 
     # Finish off the file output
-    print >> output_file, "</licenses>"
+    output_file.write(b"</licenses>\n")
     output_file.close()
 
 def get_args():
@@ -254,7 +260,7 @@
                     file_md5sum = md5sum(filename)
                     files_with_same_hash[file_md5sum].append(filename)
 
-    filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())]
+    filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(list(files_with_same_hash))]
     combine_notice_files_text(filesets, input_dirs, txt_output_file, file_title)
 
     if html_output_file is not None:
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index f3b58f8..01cc233 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -589,7 +589,7 @@
     AssertionError: If it can't find an image.
   """
   for partition in ab_partitions:
-    img_name = partition.strip() + ".img"
+    img_name = partition + ".img"
 
     # Assert that the image is present under IMAGES/ now.
     if output_zip:
@@ -856,39 +856,23 @@
         if output_zip:
           recovery_two_step_image.AddToZip(output_zip)
 
-  if has_system:
-    banner("system")
-    partitions['system'] = AddSystem(
-        output_zip, recovery_img=recovery_image, boot_img=boot_image)
+  def add_partition(partition, has_partition, add_func, add_args):
+    if has_partition:
+      banner(partition)
+      partitions[partition] = add_func(output_zip, *add_args)
 
-  if has_vendor:
-    banner("vendor")
-    partitions['vendor'] = AddVendor(
-        output_zip, recovery_img=recovery_image, boot_img=boot_image)
-
-  if has_product:
-    banner("product")
-    partitions['product'] = AddProduct(output_zip)
-
-  if has_system_ext:
-    banner("system_ext")
-    partitions['system_ext'] = AddSystemExt(output_zip)
-
-  if has_odm:
-    banner("odm")
-    partitions['odm'] = AddOdm(output_zip)
-
-  if has_vendor_dlkm:
-    banner("vendor_dlkm")
-    partitions['vendor_dlkm'] = AddVendorDlkm(output_zip)
-
-  if has_odm_dlkm:
-    banner("odm_dlkm")
-    partitions['odm_dlkm'] = AddOdmDlkm(output_zip)
-
-  if has_system_other:
-    banner("system_other")
-    AddSystemOther(output_zip)
+  add_partition_calls = (
+      ("system", has_system, AddSystem, [recovery_image, boot_image]),
+      ("vendor", has_vendor, AddVendor, [recovery_image, boot_image]),
+      ("product", has_product, AddProduct, []),
+      ("system_ext", has_system_ext, AddSystemExt, []),
+      ("odm", has_odm, AddOdm, []),
+      ("vendor_dlkm", has_vendor_dlkm, AddVendorDlkm, []),
+      ("odm_dlkm", has_odm_dlkm, AddOdmDlkm, []),
+      ("system_other", has_system_other, AddSystemOther, []),
+  )
+  for call in add_partition_calls:
+    add_partition(*call)
 
   AddApexInfo(output_zip)
 
@@ -902,13 +886,10 @@
     banner("partition-table")
     AddPartitionTable(output_zip)
 
-  if OPTIONS.info_dict.get("has_dtbo") == "true":
-    banner("dtbo")
-    partitions['dtbo'] = AddDtbo(output_zip)
-
-  if OPTIONS.info_dict.get("has_pvmfw") == "true":
-    banner("pvmfw")
-    partitions['pvmfw'] = AddPvmfw(output_zip)
+  add_partition("dtbo",
+                OPTIONS.info_dict.get("has_dtbo") == "true", AddDtbo, [])
+  add_partition("pvmfw",
+                OPTIONS.info_dict.get("has_pvmfw") == "true", AddPvmfw, [])
 
   # Custom images.
   custom_partitions = OPTIONS.info_dict.get(
@@ -965,7 +946,7 @@
                                    "ab_partitions.txt")
   if os.path.exists(ab_partitions_txt):
     with open(ab_partitions_txt) as f:
-      ab_partitions = f.readlines()
+      ab_partitions = f.read().splitlines()
 
     # For devices using A/B update, make sure we have all the needed images
     # ready under IMAGES/ or RADIO/.
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 1fe468e..02f66b4 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -231,6 +231,22 @@
             mount_point, total_blocks, used_blocks, headroom_blocks,
             adjusted_blocks))
 
+def CalculateSizeAndReserved(prop_dict, size):
+  fs_type = prop_dict.get("fs_type", "")
+  partition_headroom = int(prop_dict.get("partition_headroom", 0))
+  # If not specified, give us 16MB margin for GetDiskUsage error ...
+  reserved_size = int(prop_dict.get("partition_reserved_size", BYTES_IN_MB * 16))
+
+  if fs_type == "erofs":
+    reserved_size = int(prop_dict.get("partition_reserved_size", 0))
+    if reserved_size == 0:
+      # give .3% margin or a minimum size for AVB footer
+      return max(size * 1003 // 1000, 256 * 1024)
+
+  if fs_type.startswith("ext4") and partition_headroom > reserved_size:
+    reserved_size = partition_headroom
+
+  return size + reserved_size
 
 def BuildImageMkfs(in_dir, prop_dict, out_file, target_out, fs_config):
   """Builds a pure image for the files under in_dir and writes it to out_file.
@@ -468,12 +484,7 @@
       size = GetDiskUsage(in_dir)
     logger.info(
         "The tree size of %s is %d MB.", in_dir, size // BYTES_IN_MB)
-    # If not specified, give us 16MB margin for GetDiskUsage error ...
-    reserved_size = int(prop_dict.get("partition_reserved_size", BYTES_IN_MB * 16))
-    partition_headroom = int(prop_dict.get("partition_headroom", 0))
-    if fs_type.startswith("ext4") and partition_headroom > reserved_size:
-      reserved_size = partition_headroom
-    size += reserved_size
+    size = CalculateSizeAndReserved(prop_dict, size)
     # Round this up to a multiple of 4K so that avbtool works
     size = common.RoundUpTo4K(size)
     if fs_type.startswith("ext"):
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index c6800e8..5affa32 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1925,14 +1925,14 @@
   RunAndCheckOutput(cmd)
 
 
-def UnzipTemp(filename, pattern=None):
+def UnzipTemp(filename, patterns=None):
   """Unzips the given archive into a temporary directory and returns the name.
 
   Args:
     filename: If filename is of the form "foo.zip+bar.zip", unzip foo.zip into
     a temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
 
-    pattern: Files to unzip from the archive. If omitted, will unzip the entire
+    patterns: Files to unzip from the archive. If omitted, will unzip the entire
     archvie.
 
   Returns:
@@ -1942,11 +1942,11 @@
   tmp = MakeTempDir(prefix="targetfiles-")
   m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)
   if m:
-    UnzipToDir(m.group(1), tmp, pattern)
-    UnzipToDir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"), pattern)
+    UnzipToDir(m.group(1), tmp, patterns)
+    UnzipToDir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"), patterns)
     filename = m.group(1)
   else:
-    UnzipToDir(filename, tmp, pattern)
+    UnzipToDir(filename, tmp, patterns)
 
   return tmp
 
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 0842af9..d219ed6 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -189,6 +189,8 @@
 OPTIONS.gki_signing_algorithm = None
 OPTIONS.gki_signing_extra_args = None
 OPTIONS.android_jar_path = None
+OPTIONS.vendor_partitions = set()
+OPTIONS.vendor_otatools = None
 
 
 AVB_FOOTER_ARGS_BY_PARTITION = {
@@ -216,6 +218,10 @@
   if partition not in AVB_FOOTER_ARGS_BY_PARTITION:
     raise RuntimeError("Missing {} in AVB_FOOTER_ARGS".format(partition))
 
+# Partitions that can be regenerated after signing using a separate
+# vendor otatools package.
+ALLOWED_VENDOR_PARTITIONS = set(["vendor", "odm"])
+
 
 def IsApexFile(filename):
   return filename.endswith(".apex") or filename.endswith(".capex")
@@ -1180,6 +1186,63 @@
   return keys
 
 
+def BuildVendorPartitions(output_zip_path):
+  """Builds OPTIONS.vendor_partitions using OPTIONS.vendor_otatools."""
+  if OPTIONS.vendor_partitions.difference(ALLOWED_VENDOR_PARTITIONS):
+    logger.warning("Allowed --vendor_partitions: %s",
+                   ",".join(ALLOWED_VENDOR_PARTITIONS))
+    OPTIONS.vendor_partitions = ALLOWED_VENDOR_PARTITIONS.intersection(
+        OPTIONS.vendor_partitions)
+
+  logger.info("Building vendor partitions using vendor otatools.")
+  vendor_tempdir = common.UnzipTemp(output_zip_path, [
+      "META/*",
+  ] + ["{}/*".format(p.upper()) for p in OPTIONS.vendor_partitions])
+
+  # Disable various partitions that build based on misc_info fields.
+  # Only partitions in ALLOWED_VENDOR_PARTITIONS can be rebuilt using
+  # vendor otatools. These other partitions will be rebuilt using the main
+  # otatools if necessary.
+  vendor_misc_info_path = os.path.join(vendor_tempdir, "META/misc_info.txt")
+  vendor_misc_info = common.LoadDictionaryFromFile(vendor_misc_info_path)
+  vendor_misc_info["no_boot"] = "true"  # boot
+  vendor_misc_info["vendor_boot"] = "false"  # vendor_boot
+  vendor_misc_info["no_recovery"] = "true"  # recovery
+  vendor_misc_info["board_bpt_enable"] = "false"  # partition-table
+  vendor_misc_info["has_dtbo"] = "false"  # dtbo
+  vendor_misc_info["has_pvmfw"] = "false"  # pvmfw
+  vendor_misc_info["avb_custom_images_partition_list"] = ""  # custom images
+  vendor_misc_info["avb_enable"] = "false"  # vbmeta
+  vendor_misc_info["use_dynamic_partitions"] = "false"  # super_empty
+  vendor_misc_info["build_super_partition"] = "false"  # super split
+  with open(vendor_misc_info_path, "w") as output:
+    for key in sorted(vendor_misc_info):
+      output.write("{}={}\n".format(key, vendor_misc_info[key]))
+
+  # Disable care_map.pb as not all ab_partitions are available when
+  # vendor otatools regenerates vendor images.
+  os.remove(os.path.join(vendor_tempdir, "META/ab_partitions.txt"))
+
+  # Build vendor images using vendor otatools.
+  vendor_otatools_dir = common.MakeTempDir(prefix="vendor_otatools_")
+  common.UnzipToDir(OPTIONS.vendor_otatools, vendor_otatools_dir)
+  cmd = [
+      os.path.join(vendor_otatools_dir, "bin", "add_img_to_target_files"),
+      "--is_signing",
+      "--verbose",
+      vendor_tempdir,
+  ]
+  common.RunAndCheckOutput(cmd, verbose=True)
+
+  logger.info("Writing vendor partitions to output archive.")
+  with zipfile.ZipFile(
+      output_zip_path, "a", compression=zipfile.ZIP_DEFLATED,
+      allowZip64=True) as output_zip:
+    for p in OPTIONS.vendor_partitions:
+      path = "IMAGES/{}.img".format(p)
+      common.ZipWrite(output_zip, os.path.join(vendor_tempdir, path), path)
+
+
 def main(argv):
 
   key_mapping_options = []
@@ -1289,6 +1352,10 @@
       OPTIONS.gki_signing_algorithm = a
     elif o == "--gki_signing_extra_args":
       OPTIONS.gki_signing_extra_args = a
+    elif o == "--vendor_otatools":
+      OPTIONS.vendor_otatools = a
+    elif o == "--vendor_partitions":
+      OPTIONS.vendor_partitions = set(a.split(","))
     else:
       return False
     return True
@@ -1339,6 +1406,8 @@
           "gki_signing_key=",
           "gki_signing_algorithm=",
           "gki_signing_extra_args=",
+          "vendor_partitions=",
+          "vendor_otatools=",
       ],
       extra_option_handler=option_handler)
 
@@ -1384,8 +1453,11 @@
   common.ZipClose(input_zip)
   common.ZipClose(output_zip)
 
+  if OPTIONS.vendor_partitions and OPTIONS.vendor_otatools:
+    BuildVendorPartitions(args[1])
+
   # Skip building userdata.img and cache.img when signing the target files.
-  new_args = ["--is_signing"]
+  new_args = ["--is_signing", "--add_missing", "--verbose"]
   # add_img_to_target_files builds the system image from scratch, so the
   # recovery patch is guaranteed to be regenerated there.
   if OPTIONS.rebuild_recovery:
diff --git a/tools/warn/cpp_warn_patterns.py b/tools/warn/cpp_warn_patterns.py
index 90759d9..b738086 100644
--- a/tools/warn/cpp_warn_patterns.py
+++ b/tools/warn/cpp_warn_patterns.py
@@ -93,6 +93,8 @@
          [r".*: warning: Null passed to a callee that requires a non-null"]),
     medium('Unused command line argument',
            [r".*: warning: argument unused during compilation: .+"]),
+    medium('Set but not used',
+           [r".*: warning: .* set but not used.*Wunused-but-set"]),
     medium('Unused parameter',
            [r".*: warning: unused parameter '.*'"]),
     medium('Unused function, variable, label, comparison, etc.',
diff --git a/tools/warn/tidy_warn_patterns.py b/tools/warn/tidy_warn_patterns.py
index 7018d10..1297966 100644
--- a/tools/warn/tidy_warn_patterns.py
+++ b/tools/warn/tidy_warn_patterns.py
@@ -23,15 +23,19 @@
 from .severity import Severity
 
 
-def tidy_warn_pattern(description, pattern):
+def tidy_warn(description, patterns):
   return {
       'category': 'C/C++',
       'severity': Severity.TIDY,
       'description': 'clang-tidy ' + description,
-      'patterns': [r'.*: .+\[' + pattern + r'\]$']
+      'patterns': patterns,
   }
 
 
+def tidy_warn_pattern(description, pattern):
+  return tidy_warn(description, [r'.*: .+\[' + pattern + r'\]$'])
+
+
 def simple_tidy_warn_pattern(description):
   return tidy_warn_pattern(description, description)
 
@@ -168,6 +172,8 @@
     simple_tidy_warn_pattern('portability-simd-intrinsics'),
     group_tidy_warn_pattern('portability'),
 
+    tidy_warn('TIMEOUT', [r".*: warning: clang-tidy aborted "]),
+
     # warnings from clang-tidy's clang-analyzer checks
     analyzer_high('clang-analyzer-core, null pointer',
                   [r".*: warning: .+ pointer is null .*\[clang-analyzer-core"]),
diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp
index 1e3c413..f2f65a6 100644
--- a/tools/zipalign/ZipFile.cpp
+++ b/tools/zipalign/ZipFile.cpp
@@ -530,7 +530,7 @@
     // 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)
+    if (alignDiff == alignTo)
         return OK;
 
     return pEntry->addPadding(alignDiff);
@@ -654,7 +654,7 @@
 {
     ZipEntry* pEntry = NULL;
     status_t result;
-    long lfhPosn, startPosn, endPosn, uncompressedLen;
+    long lfhPosn, uncompressedLen;
 
     if (mReadOnly)
         return INVALID_OPERATION;
@@ -690,7 +690,6 @@
      */
     lfhPosn = ftell(mZipFp);
     pEntry->mLFH.write(mZipFp);
-    startPosn = ftell(mZipFp);
 
     /*
      * Copy the data over.
@@ -741,18 +740,13 @@
     }
 
     /*
-     * Update file offsets.
-     */
-    endPosn = ftell(mZipFp);
-
-    /*
      * Success!  Fill out new values.
      */
     pEntry->setLFHOffset(lfhPosn);
     mEOCD.mNumEntries++;
     mEOCD.mTotalNumEntries++;
     mEOCD.mCentralDirSize = 0;      // mark invalid; set by flush()
-    mEOCD.mCentralDirOffset = endPosn;
+    mEOCD.mCentralDirOffset = ftell(mZipFp);
 
     /*
      * Go back and write the LFH.
diff --git a/tools/zipalign/tests/src/align_test.cpp b/tools/zipalign/tests/src/align_test.cpp
index c79e791..96d4f73 100644
--- a/tools/zipalign/tests/src/align_test.cpp
+++ b/tools/zipalign/tests/src/align_test.cpp
@@ -9,6 +9,7 @@
 #include <android-base/file.h>
 
 using namespace android;
+using namespace base;
 
 static std::string GetTestPath(const std::string& filename) {
   static std::string test_data_dir = android::base::GetExecutableDirectory() + "/tests/data/";
@@ -26,6 +27,34 @@
   ASSERT_EQ(0, verified);
 }
 
+TEST(Align, DoubleAligment) {
+  const std::string src = GetTestPath("unaligned.zip");
+  const std::string tmp = GetTestPath("da_aligned.zip");
+  const std::string dst = GetTestPath("da_d_aligner.zip");
+
+  int processed = process(src.c_str(), tmp.c_str(), 4, true, false, 4096);
+  ASSERT_EQ(0, processed);
+
+  int verified = verify(tmp.c_str(), 4, true, false);
+  ASSERT_EQ(0, verified);
+
+  // Align the result of the previous run. Essentially double aligning.
+  processed = process(tmp.c_str(), dst.c_str(), 4, true, false, 4096);
+  ASSERT_EQ(0, processed);
+
+  verified = verify(dst.c_str(), 4, true, false);
+  ASSERT_EQ(0, verified);
+
+  // Nothing should have changed between tmp and dst.
+  std::string tmp_content;
+  ASSERT_EQ(true, ReadFileToString(tmp, &tmp_content));
+
+  std::string dst_content;
+  ASSERT_EQ(true, ReadFileToString(dst, &dst_content));
+
+  ASSERT_EQ(tmp_content, dst_content);
+}
+
 // Align a zip featuring a hole at the beginning. The
 // hole in the archive is a delete entry in the Central
 // Directory.