Merge "Revert^3 "Make the target_files zip reflect the recent partition change"" into main
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 957da92..4a7e957 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -773,6 +773,9 @@
 # Don't use SOONG_HOST_OUT, it is now an alias for HOST_OUT.
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/host)
 
+# Clear out tools/metalava Bazel output dir
+$(call add-clean-step, rm -rf $(OUT_DIR)/bazel/output/execroot/__main__/bazel-out/mixed_builds_product-*/bin/tools/metalava)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index a591fbb..fc2a132 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2210,73 +2210,71 @@
 $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
 $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(notdir $(FUTILITY))" >> $(1))
 $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_avbtool=$(notdir $(AVBTOOL))" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
-    $(if $(BOARD_AVB_SYSTEM_KEY_PATH),\
-        $(hide) echo "avb_system_key_path=$(BOARD_AVB_SYSTEM_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_system_algorithm=$(BOARD_AVB_SYSTEM_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_system_rollback_index_location=$(BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_other_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_other_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+$(if $(BOARD_AVB_ENABLE), \
+  $(hide) echo "avb_avbtool=$(notdir $(AVBTOOL))" >> $(1)$(newline) \
+  $(if $(filter $(2),system), \
+    $(hide) echo "avb_system_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_system_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
+    $(if $(BOARD_AVB_SYSTEM_KEY_PATH), \
+      $(hide) echo "avb_system_key_path=$(BOARD_AVB_SYSTEM_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_algorithm=$(BOARD_AVB_SYSTEM_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_rollback_index_location=$(BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),system_other), \
+    $(hide) echo "avb_system_other_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_system_other_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH),\
-        $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)$(newline))) \
+  $(if $(filter $(2),vendor), \
+    $(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_VENDOR_KEY_PATH),\
-        $(hide) echo "avb_vendor_key_path=$(BOARD_AVB_VENDOR_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_vendor_algorithm=$(BOARD_AVB_VENDOR_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_vendor_rollback_index_location=$(BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_add_hashtree_footer_args=$(BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_vendor_key_path=$(BOARD_AVB_VENDOR_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_vendor_algorithm=$(BOARD_AVB_VENDOR_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_vendor_rollback_index_location=$(BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),product), \
+    $(hide) echo "avb_product_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_product_add_hashtree_footer_args=$(BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
-        $(hide) echo "avb_product_key_path=$(BOARD_AVB_PRODUCT_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_product_algorithm=$(BOARD_AVB_PRODUCT_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_product_rollback_index_location=$(BOARD_AVB_PRODUCT_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_ext_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
-    $(hide) echo "avb_system_ext_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_product_key_path=$(BOARD_AVB_PRODUCT_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_product_algorithm=$(BOARD_AVB_PRODUCT_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_product_rollback_index_location=$(BOARD_AVB_PRODUCT_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),system_ext), \
+    $(hide) echo "avb_system_ext_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_system_ext_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_SYSTEM_EXT_KEY_PATH),\
-        $(hide) echo "avb_system_ext_key_path=$(BOARD_AVB_SYSTEM_EXT_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_system_ext_algorithm=$(BOARD_AVB_SYSTEM_EXT_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_system_ext_rollback_index_location=$(BOARD_AVB_SYSTEM_EXT_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_add_hashtree_footer_args=$(BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_system_ext_key_path=$(BOARD_AVB_SYSTEM_EXT_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_ext_algorithm=$(BOARD_AVB_SYSTEM_EXT_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_ext_rollback_index_location=$(BOARD_AVB_SYSTEM_EXT_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),odm), \
+    $(hide) echo "avb_odm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_odm_add_hashtree_footer_args=$(BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_ODM_KEY_PATH),\
-        $(hide) echo "avb_odm_key_path=$(BOARD_AVB_ODM_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_odm_algorithm=$(BOARD_AVB_ODM_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_odm_rollback_index_location=$(BOARD_AVB_ODM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
-    $(hide) echo "avb_vendor_dlkm_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_odm_key_path=$(BOARD_AVB_ODM_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_odm_algorithm=$(BOARD_AVB_ODM_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_odm_rollback_index_location=$(BOARD_AVB_ODM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),vendor_dlkm), \
+    $(hide) echo "avb_vendor_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_vendor_dlkm_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_VENDOR_DLKM_KEY_PATH),\
-        $(hide) echo "avb_vendor_dlkm_key_path=$(BOARD_AVB_VENDOR_DLKM_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_vendor_dlkm_algorithm=$(BOARD_AVB_VENDOR_DLKM_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_vendor_dlkm_rollback_index_location=$(BOARD_AVB_VENDOR_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
-    $(hide) echo "avb_odm_dlkm_add_hashtree_footer_args=$(BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_vendor_dlkm_key_path=$(BOARD_AVB_VENDOR_DLKM_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_vendor_dlkm_algorithm=$(BOARD_AVB_VENDOR_DLKM_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_vendor_dlkm_rollback_index_location=$(BOARD_AVB_VENDOR_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),odm_dlkm), \
+    $(hide) echo "avb_odm_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_odm_dlkm_add_hashtree_footer_args=$(BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_ODM_DLKM_KEY_PATH),\
-        $(hide) echo "avb_odm_dlkm_key_path=$(BOARD_AVB_ODM_DLKM_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_odm_dlkm_algorithm=$(BOARD_AVB_ODM_DLKM_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_odm_dlkm_rollback_index_location=$(BOARD_AVB_ODM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
-    $(hide) echo "avb_system_dlkm_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+      $(hide) echo "avb_odm_dlkm_key_path=$(BOARD_AVB_ODM_DLKM_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_odm_dlkm_algorithm=$(BOARD_AVB_ODM_DLKM_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_odm_dlkm_rollback_index_location=$(BOARD_AVB_ODM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+  $(if $(filter $(2),system_dlkm), \
+    $(hide) echo "avb_system_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+    $(hide) echo "avb_system_dlkm_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
     $(if $(BOARD_AVB_SYSTEM_DLKM_KEY_PATH),\
-        $(hide) echo "avb_system_dlkm_key_path=$(BOARD_AVB_SYSTEM_DLKM_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_system_dlkm_algorithm=$(BOARD_AVB_SYSTEM_DLKM_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_system_dlkm_rollback_index_location=$(BOARD_SYSTEM_SYSTEM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
+      $(hide) echo "avb_system_dlkm_key_path=$(BOARD_AVB_SYSTEM_DLKM_KEY_PATH)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_dlkm_algorithm=$(BOARD_AVB_SYSTEM_DLKM_ALGORITHM)" >> $(1)$(newline) \
+      $(hide) echo "avb_system_dlkm_rollback_index_location=$(BOARD_SYSTEM_SYSTEM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+)
 $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
     $(hide) echo "recovery_as_boot=true" >> $(1))
 $(if $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)),\
@@ -2287,6 +2285,7 @@
 $(if $(COPY_IMAGES_FOR_TARGET_FILES_ZIP),\
     $(hide) echo "use_fixed_timestamp=true" >> $(1))
 $(if $(3),$(hide) $(foreach kv,$(3),echo "$(kv)" >> $(1);))
+$(hide) sort -o $(1) $(1)
 endef
 
 # $(1): the path of the output dictionary file
@@ -5137,40 +5136,48 @@
 
 my_board_extracted_kernel :=
 
-# BOARD_KERNEL_CONFIG_FILE and BOARD_KERNEL_VERSION can be used to override the values extracted
-# from INSTALLED_KERNEL_TARGET.
-ifdef BOARD_KERNEL_CONFIG_FILE
-ifdef BOARD_KERNEL_VERSION
-$(BUILT_KERNEL_CONFIGS_FILE): $(BOARD_KERNEL_CONFIG_FILE)
-	cp $< $@
-$(BUILT_KERNEL_VERSION_FILE):
-	echo $(BOARD_KERNEL_VERSION) > $@
-
-$(call declare-license-metadata,$(BUILT_KERNEL_CONFIGS_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
-$(call declare-license-metadata,$(BUILT_KERNEL_VERSION_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
-
-my_board_extracted_kernel := true
-endif # BOARD_KERNEL_VERSION
-endif # BOARD_KERNEL_CONFIG_FILE
-
-ifneq ($(my_board_extracted_kernel),true)
 # Tools for decompression that is not in PATH.
 # Check $(EXTRACT_KERNEL) for decompression algorithms supported by the script.
 # Algorithms that are in the script but not in this list will be found in PATH.
 my_decompress_tools := \
     lz4:$(HOST_OUT_EXECUTABLES)/lz4 \
 
-endif # my_board_extracted_kernel
+
+# BOARD_KERNEL_CONFIG_FILE and BOARD_KERNEL_VERSION can be used to override the values extracted
+# from INSTALLED_KERNEL_TARGET.
+ifdef BOARD_KERNEL_VERSION
+$(BUILT_KERNEL_VERSION_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
+$(BUILT_KERNEL_VERSION_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
+$(BUILT_KERNEL_VERSION_FILE): $(EXTRACT_KERNEL) $(firstword $(INSTALLED_KERNEL_TARGET))
+	KERNEL_RELEASE=`$(EXTRACT_KERNEL) --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(firstword $(INSTALLED_KERNEL_TARGET)) \
+	  --output-release` ;\
+  if [ "$$KERNEL_RELEASE" != '$(BOARD_KERNEL_VERSION)' ]; then \
+    echo "Specified kernel version '$(BOARD_KERNEL_VERSION)' does not match actual kernel version '$$KERNEL_RELEASE' " ; exit 1; fi;
+	echo '$(BOARD_KERNEL_VERSION)' > $@
+
+ifdef BOARD_KERNEL_CONFIG_FILE
+$(BUILT_KERNEL_CONFIGS_FILE): $(BOARD_KERNEL_CONFIG_FILE)
+	cp $< $@
+
+$(call declare-license-metadata,$(BUILT_KERNEL_CONFIGS_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
+$(call declare-license-metadata,$(BUILT_KERNEL_VERSION_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
+
+my_board_extracted_kernel := true
+endif # BOARD_KERNEL_CONFIG_FILE
+endif # BOARD_KERNEL_VERSION
+
 
 ifneq ($(my_board_extracted_kernel),true)
 ifdef INSTALLED_KERNEL_TARGET
+ifndef BOARD_KERNEL_VERSION
 $(BUILT_KERNEL_CONFIGS_FILE): .KATI_IMPLICIT_OUTPUTS := $(BUILT_KERNEL_VERSION_FILE)
+endif
 $(BUILT_KERNEL_CONFIGS_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
 $(BUILT_KERNEL_CONFIGS_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
 $(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(firstword $(INSTALLED_KERNEL_TARGET))
 	$< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(firstword $(INSTALLED_KERNEL_TARGET)) \
 	  --output-configs $@ \
-	  --output-release $(BUILT_KERNEL_VERSION_FILE)
+	  $(if $(BOARD_KERNEL_VERSION),,--output-release $(BUILT_KERNEL_VERSION_FILE))
 
 $(call declare-license-metadata,$(BUILT_KERNEL_CONFIGS_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
 
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 4dd66c9..6d64f97 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -111,6 +111,7 @@
 # default.
 INDIVIDUALLY_TOGGLEABLE_PREBUILT_MODULES := \
   btservices \
+  devicelock \
   permission \
   rkpd \
   uwb \
@@ -154,13 +155,16 @@
 $(call add_soong_config_var_value,ANDROID,avf_kernel_modules_enabled,$(PRODUCT_AVF_KERNEL_MODULES_ENABLED))
 endif
 
-$(call add_soong_config_var_value,ANDROID,release_avf_enable_dice_changes,$(RELEASE_AVF_ENABLE_LLPVM_CHANGES))
-$(call add_soong_config_var_value,ANDROID,release_avf_enable_remote_attestation,$(RELEASE_AVF_ENABLE_REMOTE_ATTESTATION))
-$(call add_soong_config_var_value,ANDROID,release_avf_enable_multi_tenant_microdroid_vm,$(RELEASE_AVF_ENABLE_MULTI_TENANT_MICRODROID_VM))
+$(call add_soong_config_var_value,ANDROID,release_avf_allow_preinstalled_apps,$(RELEASE_AVF_ALLOW_PREINSTALLED_APPS))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_device_assignment,$(RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_dice_changes,$(RELEASE_AVF_ENABLE_DICE_CHANGES))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_llpvm_changes,$(RELEASE_AVF_ENABLE_LLPVM_CHANGES))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_multi_tenant_microdroid_vm,$(RELEASE_AVF_ENABLE_MULTI_TENANT_MICRODROID_VM))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_remote_attestation,$(RELEASE_AVF_ENABLE_REMOTE_ATTESTATION))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_vendor_modules,$(RELEASE_AVF_ENABLE_VENDOR_MODULES))
 
+$(call add_soong_config_var_value,ANDROID,release_binder_death_recipient_weak_from_jni,$(RELEASE_BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI))
+
 # Enable system_server optimizations by default unless explicitly set or if
 # there may be dependent runtime jars.
 # TODO(b/240588226): Remove the off-by-default exceptions after handling
diff --git a/core/combo/HOST_darwin-x86_64.mk b/core/combo/HOST_darwin.mk
similarity index 97%
rename from core/combo/HOST_darwin-x86_64.mk
rename to core/combo/HOST_darwin.mk
index dac3bbf..11063e6 100644
--- a/core/combo/HOST_darwin-x86_64.mk
+++ b/core/combo/HOST_darwin.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-# Configuration for Darwin (Mac OS X) on x86_64.
+# Configuration for Darwin (Mac OS X).
 # Included by combo/select.mk
 
 define $(combo_var_prefix)transform-shared-lib-to-toc
diff --git a/core/combo/HOST_linux-x86_64.mk b/core/combo/HOST_linux-x86_64.mk
deleted file mode 100644
index 845733f..0000000
--- a/core/combo/HOST_linux-x86_64.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2006 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Configuration for builds hosted on linux-x86_64.
-# Included by combo/select.mk
-
-define $(combo_var_prefix)transform-shared-lib-to-toc
-$(call _gen_toc_command_for_elf,$(1),$(2))
-endef
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux.mk
similarity index 94%
rename from core/combo/HOST_linux-x86.mk
rename to core/combo/HOST_linux.mk
index 3f4ec0a..bfdd3eb 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux.mk
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-# Configuration for builds hosted on linux-x86.
+# Configuration for builds hosted on linux.
 # Included by combo/select.mk
 
 define $(combo_var_prefix)transform-shared-lib-to-toc
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 9c7e69e..a836ed8 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -21,8 +21,12 @@
 #	combo_2nd_arch_prefix -- it's defined if this is loaded for the 2nd arch.
 #
 
-# Build a target string like "linux-arm" or "darwin-x86".
-combo_os_arch := $($(combo_target)OS)-$($(combo_target)$(combo_2nd_arch_prefix)ARCH)
+ifeq ($(combo_target),HOST_)
+  combo_os_arch := $(HOST_OS)
+else
+  # Build a target string like "linux-arm" or "darwin-x86".
+  combo_os_arch := $($(combo_target)OS)-$($(combo_target)$(combo_2nd_arch_prefix)ARCH)
+endif
 
 combo_var_prefix := $(combo_2nd_arch_prefix)$(combo_target)
 
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 6ac169b..6791125 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -90,8 +90,8 @@
 # The input variables are written by build/soong/java/dexpreopt_bootjars.go. Examples can be found
 # at the bottom of build/soong/java/dexpreopt_config_testing.go.
 dexpreopt_root_dir := $(dir $(patsubst %/,%,$(dir $(firstword $(bootclasspath_jars)))))
-booclasspath_arg := $(subst $(space),:,$(patsubst $(dexpreopt_root_dir)%,%,$(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)))
-booclasspath_locations_arg := $(subst $(space),:,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
+bootclasspath_arg := $(subst $(space),:,$(patsubst $(dexpreopt_root_dir)%,%,$(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)))
+bootclasspath_locations_arg := $(subst $(space),:,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
 boot_images := $(subst :,$(space),$(DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE$(DEXPREOPT_INFIX)))
 boot_image_arg := $(subst $(space),:,$(patsubst /%,%,$(boot_images)))
 dex2oat_extra_args := $(if $(filter true,$(ENABLE_UFFD_GC)),--runtime-arg -Xgc:CMC)
@@ -99,8 +99,8 @@
 boot_zip_metadata_txt := $(dir $(boot_zip))boot_zip/METADATA.txt
 $(boot_zip_metadata_txt):
 	rm -f $@
-	echo "booclasspath = $(booclasspath_arg)" >> $@
-	echo "booclasspath-locations = $(booclasspath_locations_arg)" >> $@
+	echo "bootclasspath = $(bootclasspath_arg)" >> $@
+	echo "bootclasspath-locations = $(bootclasspath_locations_arg)" >> $@
 	echo "boot-image = $(boot_image_arg)" >> $@
 	echo "extra-args = $(dex2oat_extra_args)" >> $@
 
diff --git a/core/main.mk b/core/main.mk
index d42c8ad..7c25862 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -220,7 +220,7 @@
 # property_overrides_split_enabled is true. Otherwise it will be installed in
 # /system/build.prop
 ifdef BOARD_VNDK_VERSION
-  ifneq ($(KEEP_VNDK),false)
+  ifeq ($(KEEP_VNDK),true)
   ifeq ($(BOARD_VNDK_VERSION),current)
     ADDITIONAL_VENDOR_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION)
   else
@@ -339,7 +339,7 @@
 # modules. It uses the version in PRODUCT_PRODUCT_VNDK_VERSION. If the value
 # is "current", use PLATFORM_VNDK_VERSION.
 ifdef PRODUCT_PRODUCT_VNDK_VERSION
-ifneq ($(KEEP_VNDK),false)
+ifeq ($(KEEP_VNDK),true)
 ifeq ($(PRODUCT_PRODUCT_VNDK_VERSION),current)
 ADDITIONAL_PRODUCT_PROPERTIES += ro.product.vndk.version=$(PLATFORM_VNDK_VERSION)
 else
@@ -1235,7 +1235,8 @@
 # Returns modules included automatically as a result of certain BoardConfig
 # variables being set.
 define auto-included-modules
-  $(if $(BOARD_VNDK_VERSION),vndk_package) \
+  $(if $(and $(BOARD_VNDK_VERSION),$(filter true,$(KEEP_VNDK))),vndk_package) \
+  $(if $(filter true,$(KEEP_VNDK)),,llndk_in_system) \
   $(if $(DEVICE_MANIFEST_FILE),vendor_manifest.xml) \
   $(if $(DEVICE_MANIFEST_SKUS),$(foreach sku, $(DEVICE_MANIFEST_SKUS),vendor_manifest_$(sku).xml)) \
   $(if $(ODM_MANIFEST_FILES),odm_manifest.xml) \
diff --git a/core/product.mk b/core/product.mk
index c268f4d..ca65948 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -445,6 +445,8 @@
 
 _product_list_vars += PRODUCT_AFDO_PROFILES
 
+_product_single_value_vars += PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API
+
 .KATI_READONLY := _product_single_value_vars _product_list_vars
 _product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
 
diff --git a/core/release_config.mk b/core/release_config.mk
index 4f9daaf..b72ee89 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -76,12 +76,6 @@
 ifeq ($(filter $(_all_release_configs), $(TARGET_RELEASE)),)
     $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(_all_release_configs))
 else
-# TODO(b/294161396): Remove this logic
-ifeq ($(TARGET_RELEASE),next)
-ifndef TESTING_TARGET_RELEASE_NEXT
-   $(error "next" releases are not supported yet.  b/294161396)
-endif
-endif
     # Choose flag files
     # Don't sort this, use it in the order they gave us.
     flag_value_files := $(_all_release_configs.$(TARGET_RELEASE).FILES)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index e00447a..b172ec2 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -319,6 +319,68 @@
 
 $(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
 
+$(call add_json_map, PartitionVarsForBazelMigrationOnlyDoNotUse)
+  $(call add_json_str,  ProductDirectory,    $(dir $(INTERNAL_PRODUCT)))
+
+  $(call add_json_map,PartitionQualifiedVariables)
+  $(foreach image_type,SYSTEM VENDOR CACHE USERDATA PRODUCT SYSTEM_EXT OEM ODM VENDOR_DLKM ODM_DLKM SYSTEM_DLKM, \
+    $(call add_json_map,$(call to-lower,$(image_type))) \
+    $(call add_json_bool, BuildingImage, $(filter true,$(BUILDING_$(image_type)_IMAGE))) \
+    $(call add_json_str, BoardErofsCompressor, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESSOR)) \
+    $(call add_json_str, BoardErofsCompressHints, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESS_HINTS)) \
+    $(call add_json_str, BoardErofsPclusterSize, $(BOARD_$(image_type)IMAGE_EROFS_PCLUSTER_SIZE)) \
+    $(call add_json_str, BoardExtfsInodeCount, $(BOARD_$(image_type)IMAGE_EXTFS_INODE_COUNT)) \
+    $(call add_json_str, BoardExtfsRsvPct, $(BOARD_$(image_type)IMAGE_EXTFS_RSV_PCT)) \
+    $(call add_json_str, BoardF2fsSloadCompressFlags, $(BOARD_$(image_type)IMAGE_F2FS_SLOAD_COMPRESS_FLAGS)) \
+    $(call add_json_str, BoardFileSystemCompress, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_COMPRESS)) \
+    $(call add_json_str, BoardFileSystemType, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_TYPE)) \
+    $(call add_json_str, BoardJournalSize, $(BOARD_$(image_type)IMAGE_JOURNAL_SIZE)) \
+    $(call add_json_str, BoardPartitionReservedSize, $(BOARD_$(image_type)IMAGE_PARTITION_RESERVED_SIZE)) \
+    $(call add_json_str, BoardPartitionSize, $(BOARD_$(image_type)IMAGE_PARTITION_SIZE)) \
+    $(call add_json_str, BoardSquashfsBlockSize, $(BOARD_$(image_type)IMAGE_SQUASHFS_BLOCK_SIZE)) \
+    $(call add_json_str, BoardSquashfsCompressor, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR)) \
+    $(call add_json_str, BoardSquashfsCompressorOpt, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR_OPT)) \
+    $(call add_json_str, BoardSquashfsDisable4kAlign, $(BOARD_$(image_type)IMAGE_SQUASHFS_DISABLE_4K_ALIGN)) \
+    $(call add_json_str, ProductBaseFsPath, $(PRODUCT_$(image_type)_BASE_FS_PATH)) \
+    $(call add_json_str, ProductHeadroom, $(PRODUCT_$(image_type)_HEADROOM)) \
+    $(call add_json_str, ProductVerityPartition, $(PRODUCT_$(image_type)_VERITY_PARTITION)) \
+    $(call add_json_str, BoardAvbAddHashtreeFooterArgs, $(BOARD_AVB_$(image_type)_ADD_HASHTREE_FOOTER_ARGS)) \
+    $(call add_json_str, BoardAvbKeyPath, $(BOARD_AVB_$(image_type)_KEY_PATH)) \
+    $(call add_json_str, BoardAvbAlgorithm, $(BOARD_AVB_$(image_type)_ALGORITHM)) \
+    $(call add_json_str, BoardAvbRollbackIndex, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX)) \
+    $(call add_json_str, BoardAvbRollbackIndexLocation, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX_LOCATION)) \
+    $(call end_json_map) \
+  )
+  $(call end_json_map)
+
+  $(call add_json_bool, TargetUserimagesUseExt2, $(filter true,$(TARGET_USERIMAGES_USE_EXT2)))
+  $(call add_json_bool, TargetUserimagesUseExt3, $(filter true,$(TARGET_USERIMAGES_USE_EXT3)))
+  $(call add_json_bool, TargetUserimagesUseExt4, $(filter true,$(TARGET_USERIMAGES_USE_EXT4)))
+
+  $(call add_json_bool, TargetUserimagesSparseExtDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)))
+  $(call add_json_bool, TargetUserimagesSparseErofsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EROFS_DISABLED)))
+  $(call add_json_bool, TargetUserimagesSparseSquashfsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED)))
+  $(call add_json_bool, TargetUserimagesSparseF2fsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_F2FS_DISABLED)))
+
+  $(call add_json_str, BoardErofsCompressor, $(BOARD_EROFS_COMPRESSOR))
+  $(call add_json_str, BoardErofsCompressorHints, $(BOARD_EROFS_COMPRESS_HINTS))
+  $(call add_json_str, BoardErofsPclusterSize, $(BOARD_EROFS_PCLUSTER_SIZE))
+  $(call add_json_str, BoardErofsShareDupBlocks, $(BOARD_EROFS_SHARE_DUP_BLOCKS))
+  $(call add_json_str, BoardErofsUseLegacyCompression, $(BOARD_EROFS_USE_LEGACY_COMPRESSION))
+  $(call add_json_str, BoardExt4ShareDupBlocks, $(BOARD_EXT4_SHARE_DUP_BLOCKS))
+  $(call add_json_str, BoardFlashLogicalBlockSize, $(BOARD_FLASH_LOGICAL_BLOCK_SIZE))
+  $(call add_json_str, BoardFlashEraseBlockSize, $(BOARD_FLASH_ERASE_BLOCK_SIZE))
+
+  $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
+  $(call add_json_bool, BoardBuildGkiBootImageWithoutRamdisk, $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)))
+  $(call add_json_bool, ProductUseDynamicPartitionSize, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)))
+  $(call add_json_bool, CopyImagesForTargetFilesZip, $(filter true,$(COPY_IMAGES_FOR_TARGET_FILES_ZIP)))
+
+  $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
+$(call end_json_map)
+
+$(call add_json_bool, NextReleaseHideFlaggedApi, $(filter true,$(PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API)))
+
 $(call json_end)
 
 $(file >$(SOONG_VARIABLES).tmp,$(json_contents))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index 4536e5f..a37fd05 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -186,15 +186,8 @@
 # BUILD_FINGERPRINT is used used to uniquely identify the combined build and
 # product; used by the OTA server.
 ifeq (,$(strip $(BUILD_FINGERPRINT)))
-  ifeq ($(strip $(HAS_BUILD_NUMBER)),false)
-    BF_BUILD_NUMBER := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M)
-  else
-    BF_BUILD_NUMBER := $(BUILD_NUMBER_FROM_FILE)
-  endif
-  BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+  BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
 endif
-# unset it for safety.
-BF_BUILD_NUMBER :=
 
 BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
 ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE)))
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 21c0c10..decc345 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -10,15 +10,29 @@
 # device we're building for.  This file is typically packaged up
 # with everything else.
 #
-# If TARGET_BOARD_INFO_FILE (which can be set in BoardConfig.mk) is
-# defined, it is used, otherwise board-info.txt is looked for in
-# $(TARGET_DEVICE_DIR).
+# The following logic is used to find the contents of the info file:
+#   1. TARGET_BOARD_INFO_FILES (can be set in BoardConfig.mk) will be combined.
+#   2. TARGET_BOARD_INFO_FILE (can be set in BoardConfig.mk) will be used.
+#   3. $(TARGET_DEVICE_DIR)/board-info.txt will be used if present.
+#
+# Specifying both TARGET_BOARD_INFO_FILES and TARGET_BOARD_INFO_FILE is an
+# error.
 #
 INSTALLED_ANDROID_INFO_TXT_TARGET := $(PRODUCT_OUT)/android-info.txt
-board_info_txt := $(TARGET_BOARD_INFO_FILE)
-ifndef board_info_txt
-board_info_txt := $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt)
+ifdef TARGET_BOARD_INFO_FILES
+  ifdef TARGET_BOARD_INFO_FILE
+    $(warning Both TARGET_BOARD_INFO_FILES and TARGET_BOARD_INFO_FILE are defined.)
+    $(warning Using $(TARGET_BOARD_INFO_FILES) rather than $(TARGET_BOARD_INFO_FILE) for android-info.txt)
+  endif
+  board_info_txt := $(call intermediates-dir-for,PACKAGING,board-info)/board-info.txt
+$(board_info_txt): $(TARGET_BOARD_INFO_FILES)
+	$(hide) cat $(TARGET_BOARD_INFO_FILES) > $@
+else ifdef TARGET_BOARD_INFO_FILE
+  board_info_txt := $(TARGET_BOARD_INFO_FILE)
+else
+  board_info_txt := $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt)
 endif
+
 CHECK_RADIO_VERSIONS := $(HOST_OUT_EXECUTABLES)/check_radio_versions$(HOST_EXECUTABLE_SUFFIX)
 $(INSTALLED_ANDROID_INFO_TXT_TARGET): $(board_info_txt) $(CHECK_RADIO_VERSIONS)
 	$(hide) $(CHECK_RADIO_VERSIONS) \
diff --git a/target/board/emulator_arm64/BoardConfig.mk b/target/board/emulator_arm64/BoardConfig.mk
index 963e558..c16e61b 100644
--- a/target/board/emulator_arm64/BoardConfig.mk
+++ b/target/board/emulator_arm64/BoardConfig.mk
@@ -51,9 +51,6 @@
 include build/make/target/board/BoardConfigGsiCommon.mk
 include build/make/target/board/BoardConfigEmuCommon.mk
 
-TARGET_NO_KERNEL := false
-BOARD_USES_RECOVERY_AS_BOOT := true
-
 BOARD_BOOTIMAGE_PARTITION_SIZE := 0x02000000
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
 
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index c74d0a3..29e4ecd 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -22,7 +22,6 @@
     android.hidl.base-V1.0-java \
     android.hidl.manager-V1.0-java \
     android.hidl.memory@1.0-impl \
-    android.hidl.memory@1.0-impl.vendor \
     android.system.suspend-service \
     android.test.base \
     android.test.mock \
@@ -236,6 +235,7 @@
     pm \
     pppd \
     preinstalled-packages-platform.xml \
+    printflags \
     privapp-permissions-platform.xml \
     prng_seeder \
     racoon \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 3c4d62e..b6e5370 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -46,7 +46,8 @@
 
 # Base modules and settings for the vendor partition.
 PRODUCT_PACKAGES += \
-    android.hardware.cas-service.example \
+    android.hidl.memory@1.0-impl.vendor \
+    com.android.hardware.cas \
     boringssl_self_test_vendor \
     dumpsys_vendor \
     fs_config_files_nonsystem \
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index 3ca4187..2f32199 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -68,6 +68,7 @@
     com.android.ipsec:android.net.ipsec.ike \
     com.android.media:updatable-media \
     com.android.mediaprovider:framework-mediaprovider \
+    com.android.mediaprovider:framework-pdf \
     com.android.ondevicepersonalization:framework-ondevicepersonalization \
     com.android.os.statsd:framework-statsd \
     com.android.permission:framework-permission \
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index 15752aa..563712a 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -188,8 +188,7 @@
 LOCAL_LICENSE_CONDITIONS := notice
 LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
 # Filter LLNDK libs moved to APEX to avoid pulling them into /system/LIB
-LOCAL_REQUIRED_MODULES := \
-    $(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES))
+LOCAL_REQUIRED_MODULES := llndk_in_system
 
 ifneq ($(TARGET_SKIP_CURRENT_VNDK),true)
 LOCAL_REQUIRED_MODULES += \
@@ -226,6 +225,21 @@
 _vndk_versions :=
 
 #####################################################################
+# Define Phony module to install LLNDK modules which are installed in
+# the system image
+include $(CLEAR_VARS)
+LOCAL_MODULE := llndk_in_system
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
+
+# Filter LLNDK libs moved to APEX to avoid pulling them into /system/LIB
+LOCAL_REQUIRED_MODULES := \
+    $(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES))
+
+include $(BUILD_PHONY_PACKAGE)
+
+#####################################################################
 # skip_mount.cfg, read by init to skip mounting some partitions when GSI is used.
 
 include $(CLEAR_VARS)
diff --git a/target/product/mainline_sdk.mk b/target/product/mainline_sdk.mk
index 343aed6..0ea72cc 100644
--- a/target/product/mainline_sdk.mk
+++ b/target/product/mainline_sdk.mk
@@ -16,3 +16,5 @@
 PRODUCT_NAME := mainline_sdk
 PRODUCT_BRAND := Android
 PRODUCT_DEVICE := mainline_sdk
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_arm64.mk b/target/product/sdk_arm64.mk
index 497f673..3eb9304 100644
--- a/target/product/sdk_arm64.mk
+++ b/target/product/sdk_arm64.mk
@@ -22,3 +22,5 @@
 PRODUCT_NAME := sdk_arm64
 PRODUCT_BRAND := Android
 PRODUCT_DEVICE := mainline_arm64
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk
index 3f81615..c16c403 100644
--- a/target/product/sdk_phone_arm64.mk
+++ b/target/product/sdk_phone_arm64.mk
@@ -63,4 +63,4 @@
 # library name, so the check fails.
 PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
 
-
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk
index 48a0e3b..293b1ea 100644
--- a/target/product/sdk_phone_armv7.mk
+++ b/target/product/sdk_phone_armv7.mk
@@ -62,3 +62,5 @@
 # RadioConfigLib), which makes it impossible to translate their module names to
 # library name, so the check fails.
 PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index 0f8b508..90cd8d5 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -57,3 +57,5 @@
 # RadioConfigLib), which makes it impossible to translate their module names to
 # library name, so the check fails.
 PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index f5d9028..b2e14a5 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -58,3 +58,5 @@
 # RadioConfigLib), which makes it impossible to translate their module names to
 # library name, so the check fails.
 PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_x86.mk b/target/product/sdk_x86.mk
index 843321f..a6e3bcd 100644
--- a/target/product/sdk_x86.mk
+++ b/target/product/sdk_x86.mk
@@ -22,3 +22,5 @@
 PRODUCT_NAME := sdk_x86_64
 PRODUCT_BRAND := Android
 PRODUCT_DEVICE := mainline_x86
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_x86_64.mk b/target/product/sdk_x86_64.mk
index c1caf7e..af73007 100644
--- a/target/product/sdk_x86_64.mk
+++ b/target/product/sdk_x86_64.mk
@@ -25,3 +25,5 @@
 PRODUCT_NAME := sdk_x86_64
 PRODUCT_BRAND := Android
 PRODUCT_DEVICE := mainline_x86_64
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/tools/Android.bp b/tools/Android.bp
index bea0602..b8ab162 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -82,3 +82,17 @@
       }
     }
 }
+
+python_test_host {
+    name: "auto_gen_test_config_test",
+    main: "auto_gen_test_config_test.py",
+    srcs: [
+        "auto_gen_test_config.py",
+        "auto_gen_test_config_test.py",
+    ],
+    auto_gen_config: true,
+    test_suites: ["general-tests"],
+    test_options: {
+        unit_test: true,
+    },
+}
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
index 2dbb585..9ec0dce 100644
--- a/tools/BUILD.bazel
+++ b/tools/BUILD.bazel
@@ -26,3 +26,10 @@
     python_version = "PY3",
     visibility = ["//visibility:public"],
 )
+
+py_binary(
+    name = "auto_gen_test_config",
+    srcs = ["auto_gen_test_config.py"],
+    python_version = "PY3",
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/aconfig/Android.bp b/tools/aconfig/Android.bp
index 28bf8a5..02fc57c 100644
--- a/tools/aconfig/Android.bp
+++ b/tools/aconfig/Android.bp
@@ -34,12 +34,13 @@
 
 // host binary: aconfig
 
-rust_protobuf_host {
+rust_protobuf {
     name: "libaconfig_protos",
     protos: ["protos/aconfig.proto"],
     crate_name: "aconfig_protos",
     source_stem: "aconfig_protos",
     use_protobuf3: true,
+    host_supported: true,
 }
 
 rust_defaults {
@@ -192,4 +193,4 @@
     rustlibs: [
         "libaconfig_test_rust_library_with_test_mode",
     ],
-}
\ No newline at end of file
+}
diff --git a/tools/aconfig/printflags/Android.bp b/tools/aconfig/printflags/Android.bp
new file mode 100644
index 0000000..da18cdc
--- /dev/null
+++ b/tools/aconfig/printflags/Android.bp
@@ -0,0 +1,27 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "printflags.defaults",
+    edition: "2021",
+    clippy_lints: "android",
+    lints: "android",
+    srcs: ["src/main.rs"],
+    rustlibs: [
+        "libaconfig_protos",
+        "libanyhow",
+        "libprotobuf",
+        "libregex",
+    ],
+}
+
+rust_binary {
+    name: "printflags",
+    defaults: ["printflags.defaults"],
+}
+
+rust_test_host {
+    name: "printflags.test",
+    defaults: ["printflags.defaults"],
+}
diff --git a/tools/aconfig/printflags/src/main.rs b/tools/aconfig/printflags/src/main.rs
new file mode 100644
index 0000000..88fdea9
--- /dev/null
+++ b/tools/aconfig/printflags/src/main.rs
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+//! `printflags` is a device binary to print feature flags.
+
+use aconfig_protos::aconfig::Flag_state as State;
+use aconfig_protos::aconfig::Parsed_flags as ProtoParsedFlags;
+use anyhow::{bail, Result};
+use regex::Regex;
+use std::collections::HashMap;
+use std::process::Command;
+use std::{fs, str};
+
+fn parse_device_config(raw: &str) -> HashMap<String, String> {
+    let mut flags = HashMap::new();
+    let regex = Regex::new(r"(?m)^([[[:alnum:]]_]+/[[[:alnum:]]_\.]+)=(true|false)$").unwrap();
+    for capture in regex.captures_iter(raw) {
+        let key = capture.get(1).unwrap().as_str().to_string();
+        let value = match capture.get(2).unwrap().as_str() {
+            "true" => format!("{:?} (device_config)", State::ENABLED),
+            "false" => format!("{:?} (device_config)", State::DISABLED),
+            _ => panic!(),
+        };
+        flags.insert(key, value);
+    }
+    flags
+}
+
+fn main() -> Result<()> {
+    // read device_config
+    let output = Command::new("/system/bin/device_config").arg("list").output()?;
+    if !output.status.success() {
+        let reason = match output.status.code() {
+            Some(code) => format!("exit code {}", code),
+            None => "terminated by signal".to_string(),
+        };
+        bail!("failed to execute device_config: {}", reason);
+    }
+    let dc_stdout = str::from_utf8(&output.stdout)?;
+    let device_config_flags = parse_device_config(dc_stdout);
+
+    // read aconfig_flags.pb files
+    let mut flags: HashMap<String, Vec<String>> = HashMap::new();
+    for partition in ["system", "system_ext", "product", "vendor"] {
+        let path = format!("/{}/etc/aconfig_flags.pb", partition);
+        let Ok(bytes) = fs::read(&path) else {
+            eprintln!("warning: failed to read {}", path);
+            continue;
+        };
+        let parsed_flags: ProtoParsedFlags = protobuf::Message::parse_from_bytes(&bytes)?;
+        for flag in parsed_flags.parsed_flag {
+            let key = format!("{}/{}.{}", flag.namespace(), flag.package(), flag.name());
+            let value = format!("{:?} + {:?} ({})", flag.permission(), flag.state(), partition);
+            flags.entry(key).or_default().push(value);
+        }
+    }
+
+    // print flags
+    for (key, mut value) in flags {
+        let (_, package_and_name) = key.split_once('/').unwrap();
+        if let Some(dc_value) = device_config_flags.get(&key) {
+            value.push(dc_value.to_string());
+        }
+        println!("{}: {}", package_and_name, value.join(", "));
+    }
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_foo() {
+        let input = r#"
+namespace_one/com.foo.bar.flag_one=true
+namespace_one/com.foo.bar.flag_two=false
+random_noise;
+namespace_two/android.flag_one=true
+namespace_two/android.flag_two=nonsense
+"#;
+        let expected = HashMap::from([
+            (
+                "namespace_one/com.foo.bar.flag_one".to_string(),
+                "ENABLED (device_config)".to_string(),
+            ),
+            (
+                "namespace_one/com.foo.bar.flag_two".to_string(),
+                "DISABLED (device_config)".to_string(),
+            ),
+            ("namespace_two/android.flag_one".to_string(), "ENABLED (device_config)".to_string()),
+        ]);
+        let actual = parse_device_config(input);
+        assert_eq!(expected, actual);
+    }
+}
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index e4baa82..7b05147 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -260,7 +260,7 @@
         DumpFormat::Text => {
             for parsed_flag in parsed_flags.parsed_flag.into_iter() {
                 let line = format!(
-                    "{}/{}: {:?} + {:?}\n",
+                    "{}.{}: {:?} + {:?}\n",
                     parsed_flag.package(),
                     parsed_flag.name(),
                     parsed_flag.permission(),
@@ -274,7 +274,7 @@
                 let sources: Vec<_> =
                     parsed_flag.trace.iter().map(|tracepoint| tracepoint.source()).collect();
                 let line = format!(
-                    "{}/{}: {:?} + {:?} ({})\n",
+                    "{}.{}: {:?} + {:?} ({})\n",
                     parsed_flag.package(),
                     parsed_flag.name(),
                     parsed_flag.permission(),
@@ -449,7 +449,7 @@
         let input = parse_test_flags_as_input();
         let bytes = dump_parsed_flags(vec![input], DumpFormat::Text).unwrap();
         let text = std::str::from_utf8(&bytes).unwrap();
-        assert!(text.contains("com.android.aconfig.test/disabled_ro: READ_ONLY + DISABLED"));
+        assert!(text.contains("com.android.aconfig.test.disabled_ro: READ_ONLY + DISABLED"));
     }
 
     #[test]
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
index ce64160..8ee599a 100755
--- a/tools/auto_gen_test_config.py
+++ b/tools/auto_gen_test_config.py
@@ -17,6 +17,8 @@
 """A tool to generate TradeFed test config file.
 """
 
+import argparse
+import re
 import os
 import shutil
 import sys
@@ -42,42 +44,85 @@
   Returns:
     0 if no error, otherwise 1.
   """
-  if len(argv) != 4 and len(argv) != 6:
-    sys.stderr.write(
-        'Invalid arguments. The script requires 4 arguments for file paths: '
-        'target_config android_manifest empty_config '
-        'instrumentation_test_config_template '
-        'and 2 optional arguments for extra configs: '
-        '--extra-configs \'EXTRA_CONFIGS\'.\n')
-    return 1
 
-  target_config = argv[0]
-  android_manifest = argv[1]
-  empty_config = argv[2]
-  instrumentation_test_config_template = argv[3]
-  extra_configs = '\n'.join(argv[5].split('\\n')) if len(argv) == 6 else ''
+  parser = argparse.ArgumentParser()
+  parser.add_argument(
+      "target_config",
+      help="Path to the generated output config.")
+  parser.add_argument(
+      "android_manifest",
+      help="Path to AndroidManifest.xml or output of 'aapt2 dump xmltree' with .xmltree extension.")
+  parser.add_argument(
+      "empty_config",
+      help="Path to the empty config template.")
+  parser.add_argument(
+      "instrumentation_test_config_template",
+      help="Path to the instrumentation test config template.")
+  parser.add_argument("--extra-configs", default="")
+  args = parser.parse_args(argv)
 
-  manifest = parse(android_manifest)
-  instrumentation_elements = manifest.getElementsByTagName('instrumentation')
-  manifest_elements = manifest.getElementsByTagName('manifest')
-  if len(instrumentation_elements) != 1 or len(manifest_elements) != 1:
-    # Failed to locate instrumentation or manifest element in AndroidManifest.
-    # file. Empty test config file will be created.
-    shutil.copyfile(empty_config, target_config)
-    return 0
+  target_config = args.target_config
+  android_manifest = args.android_manifest
+  empty_config = args.empty_config
+  instrumentation_test_config_template = args.instrumentation_test_config_template
+  extra_configs = '\n'.join(args.extra_configs.split('\\n'))
 
   module = os.path.splitext(os.path.basename(target_config))[0]
-  instrumentation = instrumentation_elements[0]
-  manifest = manifest_elements[0]
-  if ATTRIBUTE_LABEL in instrumentation.attributes:
-    label = instrumentation.attributes[ATTRIBUTE_LABEL].value
-  else:
+
+  # If the AndroidManifest.xml is not available, but the APK is, this tool also
+  # accepts the output of `aapt2 dump xmltree <apk> AndroidManifest.xml` written
+  # into a file. This is a custom structured aapt2 output - not raw XML!
+  if android_manifest.endswith(".xmltree"):
     label = module
-  runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
-  package = manifest.attributes[ATTRIBUTE_PACKAGE].value
+    with open(android_manifest, encoding="utf-8") as manifest:
+      # e.g. A: package="android.test.example.helloworld" (Raw: "android.test.example.helloworld")
+      #                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      pattern = re.compile(r"\(Raw:\s\"(.*)\"\)$")
+      curr_element = None
+      for line in manifest:
+        curr_line = line.strip()
+        if curr_line.startswith("E:"):
+          # e.g. "E: instrumentation (line=9)"
+          #          ^^^^^^^^^^^^^^^
+          curr_element = curr_line.split(" ")[1]
+        if curr_element == "instrumentation":
+          if ATTRIBUTE_RUNNER in curr_line:
+            runner =  re.findall(pattern, curr_line)[0]
+          if ATTRIBUTE_LABEL in curr_line:
+            label = re.findall(pattern, curr_line)[0]
+        if curr_element == "manifest":
+          if ATTRIBUTE_PACKAGE in curr_line:
+            package = re.findall(pattern, curr_line)[0]
+
+    if not (runner and label and package):
+      # Failed to locate instrumentation or manifest element in AndroidManifest.
+      # file. Empty test config file will be created.
+      shutil.copyfile(empty_config, target_config)
+      return 0
+
+  else:
+    # If the AndroidManifest.xml file is directly available, read it as an XML file.
+    manifest = parse(android_manifest)
+    instrumentation_elements = manifest.getElementsByTagName('instrumentation')
+    manifest_elements = manifest.getElementsByTagName('manifest')
+    if len(instrumentation_elements) != 1 or len(manifest_elements) != 1:
+      # Failed to locate instrumentation or manifest element in AndroidManifest.
+      # file. Empty test config file will be created.
+      shutil.copyfile(empty_config, target_config)
+      return 0
+
+    instrumentation = instrumentation_elements[0]
+    manifest = manifest_elements[0]
+    if ATTRIBUTE_LABEL in instrumentation.attributes:
+      label = instrumentation.attributes[ATTRIBUTE_LABEL].value
+    else:
+      label = module
+    runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
+    package = manifest.attributes[ATTRIBUTE_PACKAGE].value
+
   test_type = ('InstrumentationTest'
-               if runner.endswith('.InstrumentationTestRunner')
-               else 'AndroidJUnitTest')
+              if runner.endswith('.InstrumentationTestRunner')
+              else 'AndroidJUnitTest')
 
   with open(instrumentation_test_config_template) as template:
     config = template.read()
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
index 51a8583..ce97723 100644
--- a/tools/auto_gen_test_config_test.py
+++ b/tools/auto_gen_test_config_test.py
@@ -30,6 +30,24 @@
 </manifest>
 """
 
+XMLTREE_JUNIT_TEST = """N: android=http://schemas.android.com/apk/res/android (line=2)
+  E: manifest (line=2)
+    A: package="com.android.my.tests.x" (Raw: "com.android.my.tests.x")
+      E: instrumentation (line=9)
+        A: http://schemas.android.com/apk/res/android:label(0x01010001)="TestModule" (Raw: "TestModule")
+        A: http://schemas.android.com/apk/res/android:name(0x01010003)="androidx.test.runner.AndroidJUnitRunner" (Raw: "androidx.test.runner.AndroidJUnitRunner")
+        A: http://schemas.android.com/apk/res/android:targetPackage(0x01010021)="com.android.my.tests" (Raw: "com.android.my.tests")
+"""
+
+XMLTREE_INSTRUMENTATION_TEST = """N: android=http://schemas.android.com/apk/res/android (line=2)
+  E: manifest (line=2)
+    A: package="com.android.my.tests.x" (Raw: "com.android.my.tests.x")
+      E: instrumentation (line=9)
+        A: http://schemas.android.com/apk/res/android:label(0x01010001)="TestModule" (Raw: "TestModule")
+        A: http://schemas.android.com/apk/res/android:name(0x01010003)="android.test.InstrumentationTestRunner" (Raw: "android.test.InstrumentationTestRunner")
+        A: http://schemas.android.com/apk/res/android:targetPackage(0x01010021)="com.android.my.tests" (Raw: "com.android.my.tests")
+"""
+
 MANIFEST_JUNIT_TEST = """<?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.android.my.tests.x">
@@ -45,12 +63,12 @@
     <instrumentation
         android:name="android.test.InstrumentationTestRunner"
         android:targetPackage="com.android.my.tests"
-        android:label="My Tests" />
+        android:label="TestModule" />
 </manifest>
 """
 
 EXPECTED_JUNIT_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2023 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.
@@ -66,19 +84,23 @@
 -->
 <!-- This test config file is auto-generated. -->
 <configuration description="Runs TestModule.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="TestModule.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.my.tests.x" />
+        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="com.android.my.tests.x" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
 """
 
 EXPECTED_INSTRUMENTATION_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2023 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.
@@ -93,23 +115,74 @@
      limitations under the License.
 -->
 <!-- This test config file is auto-generated. -->
-<configuration description="Runs My Tests.">
+<configuration description="Runs TestModule.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="TestModule.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.InstrumentationTest" >
-        <option name="package" value="com.android.my.tests.x" />
+        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="com.android.my.tests.x" />
         <option name="runner" value="android.test.InstrumentationTestRunner" />
     </test>
 </configuration>
 """
 
-TOOLS_DIR = os.path.dirname(os.path.dirname(__file__))
-EMPTY_TEST_CONFIG = os.path.join(
-    TOOLS_DIR, '..', 'core', 'empty_test_config.xml')
-INSTRUMENTATION_TEST_CONFIG_TEMPLATE = os.path.join(
-    TOOLS_DIR, '..', 'core', 'instrumentation_test_config_template.xml')
+EMPTY_TEST_CONFIG_CONTENT = """<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- No AndroidTest.xml was provided and the manifest does not include
+     instrumentation, hence this apk is not instrumentable.
+-->
+<configuration description="Empty Configuration" />
+"""
+
+INSTRUMENTATION_TEST_CONFIG_TEMPLATE_CONTENT = """<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {LABEL}.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+{EXTRA_CONFIGS}
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="{MODULE}.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
+        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="{PACKAGE}" />
+        <option name="runner" value="{RUNNER}" />
+    </test>
+</configuration>
+"""
 
 
 class AutoGenTestConfigUnittests(unittest.TestCase):
@@ -120,6 +193,16 @@
     self.test_dir = tempfile.mkdtemp()
     self.config_file = os.path.join(self.test_dir, TEST_MODULE + '.config')
     self.manifest_file = os.path.join(self.test_dir, 'AndroidManifest.xml')
+    self.xmltree_file = os.path.join(self.test_dir, TEST_MODULE + '.xmltree')
+    self.empty_test_config_file = os.path.join(self.test_dir, 'empty.config')
+    self.instrumentation_test_config_template_file = os.path.join(
+        self.test_dir, 'instrumentation.config')
+
+    with open(self.empty_test_config_file, 'w') as f:
+      f.write(EMPTY_TEST_CONFIG_CONTENT)
+
+    with open(self.instrumentation_test_config_template_file, 'w') as f:
+      f.write(INSTRUMENTATION_TEST_CONFIG_TEMPLATE_CONTENT)
 
   def tearDown(self):
     """Cleanup the test directory."""
@@ -133,11 +216,11 @@
 
     argv = [self.config_file,
             self.manifest_file,
-            EMPTY_TEST_CONFIG,
-            INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+            self.empty_test_config_file,
+            self.instrumentation_test_config_template_file]
     auto_gen_test_config.main(argv)
     with open(self.config_file) as config_file:
-      with open(EMPTY_TEST_CONFIG) as empty_config:
+      with open(self.empty_test_config_file) as empty_config:
         self.assertEqual(config_file.read(), empty_config.read())
 
   def testCreateJUnitTestConfig(self):
@@ -148,8 +231,8 @@
 
     argv = [self.config_file,
             self.manifest_file,
-            EMPTY_TEST_CONFIG,
-            INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+            self.empty_test_config_file,
+            self.instrumentation_test_config_template_file]
     auto_gen_test_config.main(argv)
     with open(self.config_file) as config_file:
       self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
@@ -162,8 +245,37 @@
 
     argv = [self.config_file,
             self.manifest_file,
-            EMPTY_TEST_CONFIG,
-            INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+            self.empty_test_config_file,
+            self.instrumentation_test_config_template_file]
+    auto_gen_test_config.main(argv)
+    with open(self.config_file) as config_file:
+      self.assertEqual(
+          config_file.read(), EXPECTED_INSTRUMENTATION_TEST_CONFIG)
+
+  def testCreateJUnitTestConfigWithXMLTree(self):
+    """Test creating test config for AndroidJUnitTest.
+    """
+    with open(self.xmltree_file, 'w') as f:
+      f.write(XMLTREE_JUNIT_TEST)
+
+    argv = [self.config_file,
+            self.xmltree_file,
+            self.empty_test_config_file,
+            self.instrumentation_test_config_template_file]
+    auto_gen_test_config.main(argv)
+    with open(self.config_file) as config_file:
+      self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
+
+  def testCreateInstrumentationTestConfigWithXMLTree(self):
+    """Test creating test config for InstrumentationTest.
+    """
+    with open(self.xmltree_file, 'w') as f:
+      f.write(XMLTREE_INSTRUMENTATION_TEST)
+
+    argv = [self.config_file,
+            self.xmltree_file,
+            self.empty_test_config_file,
+            self.instrumentation_test_config_template_file]
     auto_gen_test_config.main(argv)
     with open(self.config_file) as config_file:
       self.assertEqual(
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 4bcb8fc..a3daca5 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -450,6 +450,11 @@
     return system_prop and system_prop.GetProp("ro.build.version.release") == "11"
 
   @property
+  def is_release_key(self):
+    system_prop = self.info_dict.get("build.prop")
+    return system_prop and system_prop.GetProp("ro.build.tags") == "release-key"
+
+  @property
   def vabc_compression_param(self):
     return self.get("virtual_ab_compression_method", "")
 
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 56ec929..d4420c9 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -728,47 +728,33 @@
   return input_file
 
 
-def GetTargetFilesZipForCustomImagesUpdates(input_file, custom_images):
+def GetTargetFilesZipForCustomImagesUpdates(input_file, custom_images: dict):
   """Returns a target-files.zip for custom partitions update.
 
   This function modifies ab_partitions list with the desired custom partitions
   and puts the custom images into the target target-files.zip.
 
   Args:
-    input_file: The input target-files.zip filename.
+    input_file: The input target-files extracted directory
     custom_images: A map of custom partitions and custom images.
 
   Returns:
-    The filename of a target-files.zip which has renamed the custom images in
-    the IMAGES/ to their partition names.
+    The extracted dir of a target-files.zip which has renamed the custom images
+    in the IMAGES/ to their partition names.
   """
+  for custom_image in custom_images.values():
+    if not os.path.exists(os.path.join(input_file, "IMAGES", custom_image)):
+      raise ValueError("Specified custom image {} not found in target files {}, available images are {}",
+                       custom_image, input_file, os.listdir(os.path.join(input_file, "IMAGES")))
 
-  # First pass: use zip2zip to copy the target files contents, excluding
-  # the "custom" images that will be replaced.
-  target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
-  cmd = ['zip2zip', '-i', input_file, '-o', target_file]
-
-  images = {}
   for custom_partition, custom_image in custom_images.items():
     default_custom_image = '{}.img'.format(custom_partition)
     if default_custom_image != custom_image:
-      src = 'IMAGES/' + custom_image
-      dst = 'IMAGES/' + default_custom_image
-      cmd.extend(['-x', dst])
-      images[dst] = src
+      src = os.path.join(input_file, 'IMAGES', custom_image)
+      dst = os.path.join(input_file, 'IMAGES', default_custom_image)
+      os.rename(src, dst)
 
-  common.RunAndCheckOutput(cmd)
-
-  # Second pass: write {custom_image}.img as {custom_partition}.img.
-  with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
-    with zipfile.ZipFile(target_file, 'a', allowZip64=True) as output_zip:
-      for dst, src in images.items():
-        data = input_zip.read(src)
-        logger.info("Update custom partition '%s'", dst)
-        common.ZipWriteStr(output_zip, dst, data)
-      output_zip.close()
-
-  return target_file
+  return input_file
 
 
 def GeneratePartitionTimestampFlags(partition_state):
@@ -845,6 +831,10 @@
   """Generates an Android OTA package that has A/B update payload."""
   # If input target_files are directories, create a copy so that we can modify
   # them directly
+  target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
+  if OPTIONS.disable_vabc and target_info.is_release_key:
+    raise ValueError("Disabling VABC on release-key builds is not supported.")
+
   target_file = ExtractOrCopyTargetFiles(target_file)
   if source_file is not None:
     source_file = ExtractOrCopyTargetFiles(source_file)
@@ -888,7 +878,6 @@
   else:
     assert "ab_partitions" in OPTIONS.info_dict, \
         "META/ab_partitions.txt is required for ab_update."
-    target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
     source_info = None
     if target_info.vabc_compression_param:
       minimum_api_level_required = VABC_COMPRESSION_PARAM_SUPPORT[
@@ -1238,7 +1227,7 @@
       if len(words) == 2:
         if not words[1].isdigit():
           raise ValueError("Cannot parse value %r for option $COMPRESSION_LEVEL - only "
-                         "integers are allowed." % words[1])
+                           "integers are allowed." % words[1])
     elif o == "--security_patch_level":
       OPTIONS.security_patch_level = a
     elif o in ("--max_threads"):
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 9b3367e..5c70223 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -755,12 +755,10 @@
 
 
 def LocatePartitionPath(target_files_dir: str, partition: str, allow_empty):
-  path = os.path.join(target_files_dir, "RADIO", partition + ".img")
-  if os.path.exists(path):
-    return path
-  path = os.path.join(target_files_dir, "IMAGES", partition + ".img")
-  if os.path.exists(path):
-    return path
+  for subdir in TARGET_FILES_IMAGES_SUBDIR:
+    path = os.path.join(target_files_dir, subdir, partition + ".img")
+    if os.path.exists(path):
+      return path
   if allow_empty:
     return ""
   raise common.ExternalError(
@@ -773,12 +771,10 @@
 
 
 def LocatePartitionMap(target_files_dir: str, partition: str):
-  path = os.path.join(target_files_dir, "RADIO", partition + ".map")
-  if os.path.exists(path):
-    return path
-  path = os.path.join(target_files_dir, "IMAGES", partition + ".map")
-  if os.path.exists(path):
-    return path
+  for subdir in TARGET_FILES_IMAGES_SUBDIR:
+    path = os.path.join(target_files_dir, subdir, partition + ".map")
+    if os.path.exists(path):
+      return path
   return ""
 
 
@@ -1061,7 +1057,7 @@
     if common.IsSparseImage(src):
       return common.UnsparseImage(src, dst)
     else:
-      return os.link(src, dst)
+      return os.symlink(os.path.realpath(src), dst)
 
   for subdir in TARGET_FILES_IMAGES_SUBDIR:
     if not os.path.exists(os.path.join(input_dir, subdir)):