Merge "Revert^2 "Install CAS HAL APEX"" into main
diff --git a/Changes.md b/Changes.md
index 6836528..6c0cf70 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,4 +1,19 @@
-# Build System Changes for Android.mk Writers
+# Build System Changes for Android.mk/Android.bp Writers
+
+## Partitions are no longer affected by previous builds
+
+Partition builds used to include everything in their staging directories, and building an
+individual module will install it to the staging directory. Thus, previously, `m mymodule` followed
+by `m` would cause `mymodule` to be presinstalled on the device, even if it wasn't listed in
+`PRODUCT_PACKAGES`.
+
+This behavior has been changed, and now the partition images only include what they'd have if you
+did a clean build. This behavior can be disabled by setting the
+`BUILD_BROKEN_INCORRECT_PARTITION_IMAGES` environment variable or board config variable.
+
+Manually adding make rules that build to the staging directories without going through the make
+module system will not be compatible with this change. This includes many usages of
+`LOCAL_POST_INSTALL_CMD`.
 
 ## Perform validation of Soong plugins
 
@@ -29,6 +44,7 @@
 variable to `true`.
 
 Python 2 is slated for complete removal in V.
+
 ## Stop referencing sysprop_library directly from cc modules
 
 For the migration to Bazel, we are no longer mapping sysprop_library targets
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/cogsetup.sh b/cogsetup.sh
new file mode 100644
index 0000000..02fcc8f
--- /dev/null
+++ b/cogsetup.sh
@@ -0,0 +1,89 @@
+#
+# 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 file is executed by build/envsetup.sh, and can use anything
+# defined in envsetup.sh.
+function _create_out_symlink_for_cog() {
+  if [[ "${OUT_DIR}" == "" ]]; then
+    OUT_DIR="out"
+  fi
+
+  if [[ -L "${OUT_DIR}" ]]; then
+    return
+  fi
+  if [ -d "${OUT_DIR}" ]; then
+    echo -e "\tOutput directory ${OUT_DIR} cannot be present in a Cog workspace."
+    echo -e "\tDelete \"${OUT_DIR}\" or create a symlink from \"${OUT_DIR}\" to a directory outside your workspace."
+    return 1
+  fi
+
+  DEFAULT_OUTPUT_DIR="${HOME}/.cog/android-build-out"
+  mkdir -p ${DEFAULT_OUTPUT_DIR}
+  ln -s ${DEFAULT_OUTPUT_DIR} `pwd`/out
+}
+
+# This function moves the reclient binaries into a directory that exists in a
+# non-cog part of the overall filesystem.  This is to workaround the problem
+# described in b/289391270.
+function _copy_reclient_binaries_from_cog() {
+  local NONCOG_RECLIENT_BIN_DIR="${HOME}/.cog/reclient/bin"
+  if [ ! -d "$NONCOG_RECLIENT_BIN_DIR" ]; then
+    # Create the non cog directory if it doesn't exist.
+    mkdir -p ${NONCOG_RECLIENT_BIN_DIR}
+  else
+    # Clear out the non cog directory if it does exist.
+    rm -f ${NONCOG_RECLIENT_BIN_DIR}/*
+  fi
+
+  local TOP=$(gettop)
+
+  # Copy the binaries out of live.
+  cp $TOP/prebuilts/remoteexecution-client/live/* $NONCOG_RECLIENT_BIN_DIR
+
+  # Finally set the RBE_DIR env var to point to the out-of-cog directory.
+  export RBE_DIR=$NONCOG_RECLIENT_BIN_DIR
+}
+
+# This function sets up the build environment to be appropriate for Cog.
+function _setup_cog_env() {
+  _create_out_symlink_for_cog
+  if [ "$?" -eq "1" ]; then
+    echo -e "\e[0;33mWARNING:\e[00m Cog environment setup failed!"
+    return 1
+  fi
+  _copy_reclient_binaries_from_cog
+
+  export ANDROID_BUILD_ENVIRONMENT_CONFIG="googler-cog"
+
+  # Running repo command within Cog workspaces is not supported, so override
+  # it with this function. If the user is running repo within a Cog workspace,
+  # we'll fail with an error, otherwise, we run the original repo command with
+  # the given args.
+  ORIG_REPO_PATH=`which repo`
+  function repo {
+    if [[ "${PWD}" == /google/cog/* ]]; then
+      echo "\e[01;31mERROR:\e[0mrepo command is disallowed within Cog workspaces."
+      return 1
+    fi
+    ${ORIG_REPO_PATH} "$@"
+  }
+}
+
+if [[ "${PWD}" != /google/cog/* ]]; then
+  echo -e "\e[01;31mERROR:\e[0m This script must be run from a Cog workspace."
+fi
+
+_setup_cog_env
\ No newline at end of file
diff --git a/core/Makefile b/core/Makefile
index 82545de..a591fbb 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -3425,14 +3425,22 @@
 .PHONY: installed-file-list
 installed-file-list: $(INSTALLED_FILES_FILE)
 
-systemimage_intermediates := \
-    $(call intermediates-dir-for,PACKAGING,systemimage)
-BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
+systemimage_intermediates :=$= $(call intermediates-dir-for,PACKAGING,systemimage)
+BUILT_SYSTEMIMAGE :=$= $(systemimage_intermediates)/system.img
+
 
 # Used by the bazel sandwich to request the staging dir be built
 $(systemimage_intermediates)/staging_dir.stamp: $(FULL_SYSTEMIMAGE_DEPS)
 	touch $@
 
+define write-file-lines
+$(1):
+	@echo Writing $$@
+	rm -f $$@
+	echo -n > $$@
+	$$(foreach f,$(2),echo "$$(f)" >> $$@$$(newline))
+endef
+
 # $(1): output file
 define build-systemimage-target
   @echo "Target system fs image: $(1)"
@@ -3441,16 +3449,19 @@
       skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(systemimage_intermediates)/file_list.txt) \
           $(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) $(TARGET_OUT) \
           || ( mkdir -p $${DIST_DIR}; \
                cp $(INSTALLED_FILES_FILE) $${DIST_DIR}/installed-files-rescued.txt; \
                exit 1 )
 endef
 
+$(eval $(call write-file-lines,$(systemimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT)/,,$(filter $(TARGET_OUT)/%,$(FULL_SYSTEMIMAGE_DEPS)))))
+
 ifeq ($(BOARD_AVB_ENABLE),true)
 $(BUILT_SYSTEMIMAGE): $(BOARD_AVB_SYSTEM_KEY_PATH)
 endif
-$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
+$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(systemimage_intermediates)/file_list.txt
 	$(call build-systemimage-target,$@)
 
 $(call declare-1p-container,$(BUILT_SYSTEMIMAGE),system/extras)
@@ -3506,7 +3517,7 @@
 
 .PHONY: systemimage-nodeps snod
 systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \
-	            | $(INTERNAL_USERIMAGES_DEPS)
+	            | $(INTERNAL_USERIMAGES_DEPS) $(systemimage_intermediates)/file_list.txt
 	@echo "make $@: ignoring dependencies"
 	$(call build-systemimage-target,$(INSTALLED_SYSTEMIMAGE_TARGET))
 	$(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
@@ -3547,6 +3558,7 @@
   $(call generate-image-prop-dictionary, $(userdataimage_intermediates)/userdata_image_info.txt,userdata,skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(userdataimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_DATA) $(userdataimage_intermediates)/userdata_image_info.txt \
           $(INSTALLED_USERDATAIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE))
@@ -3557,7 +3569,10 @@
 INSTALLED_USERDATAIMAGE_TARGET_DEPS := \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_USERDATAIMAGE_FILES)
-$(INSTALLED_USERDATAIMAGE_TARGET): $(INSTALLED_USERDATAIMAGE_TARGET_DEPS)
+
+$(eval $(call write-file-lines,$(userdataimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_DATA)/,,$(filter $(TARGET_OUT_DATA)/%,$(INSTALLED_USERDATAIMAGE_TARGET_DEPS)))))
+
+$(INSTALLED_USERDATAIMAGE_TARGET): $(INSTALLED_USERDATAIMAGE_TARGET_DEPS) $(userdataimage_intermediates)/file_list.txt
 	$(build-userdataimage-target)
 
 $(call declare-1p-container,$(INSTALLED_USERDATAIMAGE_TARGET),)
@@ -3566,7 +3581,7 @@
 UNMOUNTED_NOTICE_VENDOR_DEPS+= $(INSTALLED_USERDATAIMAGE_TARGET)
 
 .PHONY: userdataimage-nodeps
-userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) $(userdataimage_intermediates)/file_list.txt
 	$(build-userdataimage-target)
 
 endif # BUILDING_USERDATA_IMAGE
@@ -3602,14 +3617,17 @@
   $(call generate-image-prop-dictionary, $(cacheimage_intermediates)/cache_image_info.txt,cache,skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(cacheimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_CACHE) $(cacheimage_intermediates)/cache_image_info.txt \
           $(INSTALLED_CACHEIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(cacheimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_CACHE)/,,$(filter $(TARGET_OUT_CACHE)/%,$(INTERNAL_CACHEIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_CACHEIMAGE_TARGET := $(BUILT_CACHEIMAGE_TARGET)
-$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES)
+$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES) $(cacheimage_intermediates)/file_list.txt
 	$(build-cacheimage-target)
 
 $(call declare-1p-container,$(INSTALLED_CACHEIMAGE_TARGET),)
@@ -3618,7 +3636,7 @@
 UNMOUNTED_NOTICE_VENDOR_DEPS+= $(INSTALLED_CACHEIMAGE_TARGET)
 
 .PHONY: cacheimage-nodeps
-cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) $(cacheimage_intermediates)/file_list.txt
 	$(build-cacheimage-target)
 
 else # BUILDING_CACHE_IMAGE
@@ -3683,16 +3701,19 @@
   $(call generate-image-prop-dictionary, $(systemotherimage_intermediates)/system_other_image_info.txt,system,skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(systemotherimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_SYSTEM_OTHER) $(systemotherimage_intermediates)/system_other_image_info.txt \
           $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(systemotherimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_OTHER)/,,$(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(INTERNAL_SYSTEMOTHERIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_SYSTEMOTHERIMAGE_TARGET := $(BUILT_SYSTEMOTHERIMAGE_TARGET)
 ifneq (true,$(SANITIZE_LITE))
 # Only create system_other when not building the second stage of a SANITIZE_LITE build.
-$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER)
+$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER) $(systemotherimage_intermediates)/file_list.txt
 	$(build-systemotherimage-target)
 
 $(call declare-1p-container,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),)
@@ -3702,7 +3723,7 @@
 endif
 
 .PHONY: systemotherimage-nodeps
-systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) $(systemotherimage_intermediates)/file_list.txt
 	$(build-systemotherimage-target)
 
 endif # BUILDING_SYSTEM_OTHER_IMAGE
@@ -3783,18 +3804,22 @@
   $(call generate-image-prop-dictionary, $(vendorimage_intermediates)/vendor_image_info.txt,vendor,skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(vendorimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_VENDOR) $(vendorimage_intermediates)/vendor_image_info.txt \
           $(INSTALLED_VENDORIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET) $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_VENDORIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(vendorimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR)/,,$(filter $(TARGET_OUT_VENDOR)/%,$(INTERNAL_VENDORIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_VENDORIMAGE_TARGET := $(BUILT_VENDORIMAGE_TARGET)
 $(INSTALLED_VENDORIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_VENDORIMAGE_FILES) \
     $(INSTALLED_FILES_FILE_VENDOR) \
-    $(RECOVERY_FROM_BOOT_PATCH)
+    $(RECOVERY_FROM_BOOT_PATCH) \
+    $(vendorimage_intermediates)/file_list.txt
 	$(build-vendorimage-target)
 
 VENDOR_NOTICE_DEPS += $(INSTALLED_VENDORIMAGE_TARGET)
@@ -3803,7 +3828,7 @@
 $(call declare-container-license-deps,$(INSTALLED_VENDORIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDORIMAGE_FILES) $(RECOVERY_FROM_BOOT_PATH),$(PRODUCT_OUT)/:/)
 
 .PHONY: vendorimage-nodeps vnod
-vendorimage-nodeps vnod: | $(INTERNAL_USERIMAGES_DEPS)
+vendorimage-nodeps vnod: | $(INTERNAL_USERIMAGES_DEPS) $(vendorimage_intermediates)/file_list.txt
 	$(build-vendorimage-target)
 
 .PHONY: sync_vendor
@@ -3849,17 +3874,21 @@
   $(call generate-image-prop-dictionary, $(productimage_intermediates)/product_image_info.txt,product,skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(productimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_PRODUCT) $(productimage_intermediates)/product_image_info.txt \
           $(INSTALLED_PRODUCTIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_PRODUCTIMAGE_TARGET),$(BOARD_PRODUCTIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(productimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_PRODUCT)/,,$(filter $(TARGET_OUT_PRODUCT)/%,$(INTERNAL_PRODUCTIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_PRODUCTIMAGE_TARGET := $(BUILT_PRODUCTIMAGE_TARGET)
 $(INSTALLED_PRODUCTIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_PRODUCTIMAGE_FILES) \
-    $(INSTALLED_FILES_FILE_PRODUCT)
+    $(INSTALLED_FILES_FILE_PRODUCT) \
+    $(productimage_intermediates)/file_list.txt
 	$(build-productimage-target)
 
 PRODUCT_NOTICE_DEPS += $(INSTALLED_PRODUCTIMAGE_TARGET)
@@ -3868,7 +3897,7 @@
 $(call declare-container-license-deps,$(INSTALLED_PRODUCTIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_PRODUCTIMAGE_FILES) $(INSTALLED_FILES_FILE_PRODUCT),$(PRODUCT_OUT)/:/)
 
 .PHONY: productimage-nodeps pnod
-productimage-nodeps pnod: | $(INTERNAL_USERIMAGES_DEPS)
+productimage-nodeps pnod: | $(INTERNAL_USERIMAGES_DEPS) $(productimage_intermediates)/file_list.txt
 	$(build-productimage-target)
 
 .PHONY: sync_product
@@ -3910,6 +3939,7 @@
   $(call generate-image-prop-dictionary, $(system_extimage_intermediates)/system_ext_image_info.txt,system_ext, skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(system_extimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_SYSTEM_EXT) \
           $(system_extimage_intermediates)/system_ext_image_info.txt \
           $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
@@ -3917,12 +3947,15 @@
   $(call assert-max-image-size,$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET),$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(system_extimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_EXT)/,,$(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(INTERNAL_SYSTEM_EXTIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_SYSTEM_EXTIMAGE_TARGET := $(BUILT_SYSTEM_EXTIMAGE_TARGET)
 $(INSTALLED_SYSTEM_EXTIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_SYSTEM_EXTIMAGE_FILES) \
-    $(INSTALLED_FILES_FILE_SYSTEM_EXT)
+    $(INSTALLED_FILES_FILE_SYSTEM_EXT) \
+    $(system_extimage_intermediates)/file_list.txt
 	$(build-system_extimage-target)
 
 SYSTEM_EXT_NOTICE_DEPS += $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
@@ -3931,7 +3964,7 @@
 $(call declare-container-license-deps,$(INSTALLED_SYSTEM_EXTIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEM_EXTIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEM_EXT),$(PRODUCT_OUT)/:/)
 
 .PHONY: systemextimage-nodeps senod
-systemextimage-nodeps senod: | $(INTERNAL_USERIMAGES_DEPS)
+systemextimage-nodeps senod: | $(INTERNAL_USERIMAGES_DEPS) $(system_extimage_intermediates)/file_list.txt
 	$(build-system_extimage-target)
 
 .PHONY: sync_system_ext
@@ -3994,17 +4027,21 @@
 	  skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(odmimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_ODM) $(odmimage_intermediates)/odm_image_info.txt \
           $(INSTALLED_ODMIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_ODMIMAGE_TARGET),$(BOARD_ODMIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(odmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM)/,,$(filter $(TARGET_OUT_ODM)/%,$(INTERNAL_ODMIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_ODMIMAGE_TARGET := $(BUILT_ODMIMAGE_TARGET)
 $(INSTALLED_ODMIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_ODMIMAGE_FILES) \
-    $(INSTALLED_FILES_FILE_ODM)
+    $(INSTALLED_FILES_FILE_ODM) \
+    $(odmimage_intermediates)/file_list.txt
 	$(build-odmimage-target)
 
 ODM_NOTICE_DEPS += $(INSTALLED_ODMIMAGE_TARGET)
@@ -4013,7 +4050,7 @@
 $(call declare-container-license-deps,$(INSTALLED_ODMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_ODMIMAGE_FILES) $(INSTALLED_FILES_FILE_ODM),$(PRODUCT_OUT)/:/)
 
 .PHONY: odmimage-nodeps onod
-odmimage-nodeps onod: | $(INTERNAL_USERIMAGES_DEPS)
+odmimage-nodeps onod: | $(INTERNAL_USERIMAGES_DEPS) $(odmimage_intermediates)/file_list.txt
 	$(build-odmimage-target)
 
 .PHONY: sync_odm
@@ -4056,17 +4093,21 @@
 	  vendor_dlkm, skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(vendor_dlkmimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_VENDOR_DLKM) $(vendor_dlkmimage_intermediates)/vendor_dlkm_image_info.txt \
           $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(vendor_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR_DLKM)/,,$(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(INTERNAL_VENDOR_DLKMIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_VENDOR_DLKMIMAGE_TARGET := $(BUILT_VENDOR_DLKMIMAGE_TARGET)
 $(INSTALLED_VENDOR_DLKMIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_VENDOR_DLKMIMAGE_FILES) \
-    $(INSTALLED_FILES_FILE_VENDOR_DLKM)
+    $(INSTALLED_FILES_FILE_VENDOR_DLKM) \
+    $(vendor_dlkmimage_intermediates)/file_list.txt
 	$(build-vendor_dlkmimage-target)
 
 VENDOR_DLKM_NOTICE_DEPS += $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)
@@ -4075,7 +4116,7 @@
 $(call declare-container-license-deps,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDOR_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_VENDOR_DLKM),$(PRODUCT_OUT)/:/)
 
 .PHONY: vendor_dlkmimage-nodeps vdnod
-vendor_dlkmimage-nodeps vdnod: | $(INTERNAL_USERIMAGES_DEPS)
+vendor_dlkmimage-nodeps vdnod: | $(INTERNAL_USERIMAGES_DEPS) $(vendor_dlkmimage_intermediates)/file_list.txt
 	$(build-vendor_dlkmimage-target)
 
 .PHONY: sync_vendor_dlkm
@@ -4118,17 +4159,21 @@
 	  odm_dlkm, skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(odm_dlkmimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_ODM_DLKM) $(odm_dlkmimage_intermediates)/odm_dlkm_image_info.txt \
           $(INSTALLED_ODM_DLKMIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(odm_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM_DLKM)/,,$(filter $(TARGET_OUT_ODM_DLKM)/%,$(INTERNAL_ODM_DLKMIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_ODM_DLKMIMAGE_TARGET := $(BUILT_ODM_DLKMIMAGE_TARGET)
 $(INSTALLED_ODM_DLKMIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_ODM_DLKMIMAGE_FILES) \
-    $(INSTALLED_FILES_FILE_ODM_DLKM)
+    $(INSTALLED_FILES_FILE_ODM_DLKM) \
+    $(odm_dlkmimage_intermediates)/file_list.txt
 	$(build-odm_dlkmimage-target)
 
 ODM_DLKM_NOTICE_DEPS += $(INSTALLED_ODM_DLKMIMAGE_TARGET)
@@ -4137,7 +4182,7 @@
 $(call declare-container-license-deps,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_ODM_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_ODM_DLKM),$(PRODUCT_OUT)/:/)
 
 .PHONY: odm_dlkmimage-nodeps odnod
-odm_dlkmimage-nodeps odnod: | $(INTERNAL_USERIMAGES_DEPS)
+odm_dlkmimage-nodeps odnod: | $(INTERNAL_USERIMAGES_DEPS) $(odm_dlkmimage_intermediates)/file_list.txt
 	$(build-odm_dlkmimage-target)
 
 .PHONY: sync_odm_dlkm
@@ -4182,17 +4227,21 @@
 	  system_dlkm, skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       $(BUILD_IMAGE) \
+          $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(system_dlkmimage_intermediates)/file_list.txt) \
           $(TARGET_OUT_SYSTEM_DLKM) $(system_dlkmimage_intermediates)/system_dlkm_image_info.txt \
           $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET) $(TARGET_OUT)
   $(call assert-max-image-size,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),$(BOARD_SYSTEM_DLKMIMAGE_PARTITION_SIZE))
 endef
 
+$(eval $(call write-file-lines,$(system_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_DLKM)/,,$(filter $(TARGET_OUT_SYSTEM_DLKM)/%,$(INTERNAL_SYSTEM_DLKMIMAGE_FILES)))))
+
 # We just build this directly to the install location.
 INSTALLED_SYSTEM_DLKMIMAGE_TARGET := $(BUILT_SYSTEM_DLKMIMAGE_TARGET)
 $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET): \
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_SYSTEM_DLKMIMAGE_FILES) \
-    $(INSTALLED_FILES_FILE_SYSTEM_DLKM)
+    $(INSTALLED_FILES_FILE_SYSTEM_DLKM) \
+    $(system_dlkmimage_intermediates)/file_list.txt
 	$(build-system_dlkmimage-target)
 
 SYSTEM_DLKM_NOTICE_DEPS += $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET)
@@ -4201,7 +4250,7 @@
 $(call declare-container-license-deps,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEM_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEM_DLKM),$(PRODUCT_OUT)/:/)
 
 .PHONY: system_dlkmimage-nodeps sdnod
-system_dlkmimage-nodeps sdnod: | $(INTERNAL_USERIMAGES_DEPS)
+system_dlkmimage-nodeps sdnod: | $(INTERNAL_USERIMAGES_DEPS) $(system_dlkmimage_intermediates)/file_list.txt
 	$(build-system_dlkmimage-target)
 
 .PHONY: sync_system_dlkm
@@ -4930,6 +4979,50 @@
     $(INTERNAL_PVMFWIMAGE_FILES) \
 
 # -----------------------------------------------------------------
+# Run apex_sepolicy_tests for all installed APEXes
+
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+intermediate := $(call intermediates-dir-for,PACKAGING,apex_sepolicy_tests)
+apex_dirs := \
+  $(TARGET_OUT)/apex/% \
+  $(TARGET_OUT_SYSTEM_EXT)/apex/% \
+  $(TARGET_OUT_VENDOR)/apex/% \
+  $(TARGET_OUT_PRODUCT)/apex/% \
+
+apex_files := $(sort $(filter $(apex_dirs), $(INTERNAL_ALLIMAGES_FILES)))
+apex_dirs :=
+
+# $1: apex file
+# $2: output file
+define _run_apex_sepolicy_tests
+$2: $1 \
+    $(HOST_OUT_EXECUTABLES)/apex_sepolicy_tests \
+    $(HOST_OUT_EXECUTABLES)/deapexer \
+    $(HOST_OUT_EXECUTABLES)/debugfs_static
+	@rm -rf $$@
+	@mkdir -p $(dir $$@)
+	$(HOST_OUT_EXECUTABLES)/apex_sepolicy_tests --all -f <($(HOST_OUT_EXECUTABLES)/deapexer --debugfs_path $(HOST_OUT_EXECUTABLES)/debugfs_static list -Z $$<)
+	@touch $$@
+endef
+
+# $1: apex file list
+define run_apex_sepolicy_tests
+$(foreach apex_file,$1, \
+  $(eval passfile := $(patsubst $(PRODUCT_OUT)/%,$(intermediate)/%.pass,$(apex_file))) \
+  $(eval $(call _run_apex_sepolicy_tests,$(apex_file),$(passfile))) \
+  $(passfile))
+endef
+
+.PHONY: run_apex_sepolicy_tests
+run_apex_sepolicy_tests: $(call run_apex_sepolicy_tests,$(apex_files))
+
+droid_targets: run_apex_sepolicy_tests
+
+apex_files :=
+intermediate :=
+endif # TARGET_BUILD_UNBUNDLED
+
+# -----------------------------------------------------------------
 # Check VINTF of build
 
 # Note: vendor_dlkm, odm_dlkm, and system_dlkm does not have VINTF files.
@@ -5539,7 +5632,7 @@
 	$(hide) echo "flash vbmeta_system" >> $@
 endif
 ifneq (,$(strip $(BOARD_AVB_VBMETA_VENDOR)))
-	$(hide) echo "flash --apply-vbmeta vbmeta_vendor" >> $@
+	$(hide) echo "flash vbmeta_vendor" >> $@
 endif
 ifneq (,$(strip $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS)))
 	$(hide) $(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS), \
diff --git a/core/OWNERS b/core/OWNERS
index eb1d5c3..88f6d06 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -5,3 +5,5 @@
 # For version updates
 per-file version_defaults.mk = aseaton@google.com,lubomir@google.com,pscovanner@google.com,bkhalife@google.com,jainne@google.com
 
+# For sdk extensions version updates
+per-file version_defaults.mk = amhk@google.com,gurpreetgs@google.com,mkhokhlova@google.com,robertogil@google.com
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 66d96b1..4dd66c9 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -154,7 +154,12 @@
 $(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_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_vendor_modules,$(RELEASE_AVF_ENABLE_VENDOR_MODULES))
 
 # Enable system_server optimizations by default unless explicitly set or if
 # there may be dependent runtime jars.
diff --git a/core/board_config.mk b/core/board_config.mk
index 2699512..eb4c5ec 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -187,6 +187,7 @@
   BUILD_BROKEN_USES_NETWORK \
   BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE \
   BUILD_BROKEN_VINTF_PRODUCT_COPY_FILES \
+  BUILD_BROKEN_INCORRECT_PARTITION_IMAGES \
 
 _build_broken_var_list += \
   $(foreach m,$(AVAILABLE_BUILD_MODULE_TYPES) \
diff --git a/core/config.mk b/core/config.mk
index 8ff85cf..c339590 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1224,8 +1224,12 @@
 TARGET_AVAILABLE_SDK_VERSIONS := $(filter-out %/module-lib %/system-server,$(TARGET_AVAILABLE_SDK_VERSIONS))
 TARGET_AVAIALBLE_SDK_VERSIONS := $(call numerically_sort,$(TARGET_AVAILABLE_SDK_VERSIONS))
 
-TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT := $(call numbers_less_than,24,$(TARGET_AVAILABLE_SDK_VERSIONS))
-TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT := $(call numbers_less_than,30,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_8_SUPPORT := $(call numbers_less_than,24,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_9_SUPPORT := $(call numbers_less_than,30,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_11_SUPPORT := $(call numbers_less_than,32,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_17_SUPPORT := $(call numbers_less_than,34,$(TARGET_AVAILABLE_SDK_VERSIONS))
+
+JAVA_LANGUAGE_VERSIONS_WITHOUT_SYSTEM_MODULES := 1.7 1.8
 
 # This is the standard way to name a directory containing prebuilt target
 # objects. E.g., prebuilt/$(TARGET_PREBUILT_TAG)/libc.so
diff --git a/core/definitions.mk b/core/definitions.mk
index 909357c..b6b0d69 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -3422,6 +3422,10 @@
 # $(2): path in symbols directory
 # $(3): file type (elf or r8)
 # $(4): path in the mappings directory
+#
+# Regarding the restats at the end: I think you should only need to use KATI_RESTAT on $(2), but
+# there appears to be a bug in kati where it was not adding restat=true in the ninja file unless we
+# also added 4 to KATI_RESTAT.
 define _copy-symbols-file-with-mapping
 $(2): .KATI_IMPLICIT_OUTPUTS := $(4)
 $(2): $(SYMBOLS_MAP)
@@ -3430,6 +3434,7 @@
 	$$(copy-file-to-target)
 	$(SYMBOLS_MAP) -$(strip $(3)) $(2) -write_if_changed $(4)
 .KATI_RESTAT: $(2)
+.KATI_RESTAT: $(4)
 endef
 
 
diff --git a/core/java_common.mk b/core/java_common.mk
index 0e03d0b..a5ed057 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -25,15 +25,19 @@
     # Host modules always default to 1.9
     LOCAL_JAVA_LANGUAGE_VERSION := 1.9
   else
-    ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT)))
+    ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_8_SUPPORT)))
       LOCAL_JAVA_LANGUAGE_VERSION := 1.7
-    else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT)))
+    else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_9_SUPPORT)))
       LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+    else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_11_SUPPORT)))
+      LOCAL_JAVA_LANGUAGE_VERSION := 1.9
+    else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_17_SUPPORT)))
+      LOCAL_JAVA_LANGUAGE_VERSION := 11
     else ifneq (,$(LOCAL_SDK_VERSION)$(TARGET_BUILD_USE_PREBUILT_SDKS))
       # TODO(ccross): allow 1.9 for current and unbundled once we have SDK system modules
       LOCAL_JAVA_LANGUAGE_VERSION := 1.8
     else
-      LOCAL_JAVA_LANGUAGE_VERSION := 1.9
+      LOCAL_JAVA_LANGUAGE_VERSION := 17
     endif
   endif
 endif
@@ -410,7 +414,7 @@
 full_java_system_modules_deps :=
 my_system_modules_dir :=
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_USE_SYSTEM_MODULES :=
-ifeq ($(LOCAL_JAVA_LANGUAGE_VERSION),1.9)
+ifeq (,$(filter $(LOCAL_JAVA_LANGUAGE_VERSION),$(JAVA_LANGUAGE_VERSIONS_WITHOUT_SYSTEM_MODULES)))
   $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_USE_SYSTEM_MODULES := true
   ifdef my_system_modules
     ifneq ($(my_system_modules),none)
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index 697fe24..ca319ce 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -69,31 +69,45 @@
 # Aconfig Flags
 
 # Create a summary file of build flags for each partition
-# $(1): built aconfig flags textprot file (out)
-# $(2): installed aconfig flags textprot file (out)
+# $(1): built aconfig flags file (out)
+# $(2): installed aconfig flags file (out)
 # $(3): input aconfig files for the partition (in)
+# $(4): file format, passed to `aconfig dump` (in)
+# $(5): text placed in aconfig file when no flags present (out)
 define generate-partition-aconfig-flag-file
 $(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
 $(eval $(strip $(1)): PRIVATE_IN := $(strip $(3)))
 $(strip $(1)): $(ACONFIG) $(strip $(3))
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
-		$$(ACONFIG) dump --format textproto --out $$(PRIVATE_OUT) \
+		$$(ACONFIG) dump --format $(4) --out $$(PRIVATE_OUT) \
 			$$(addprefix --cache ,$$(PRIVATE_IN)), \
-		echo "# No aconfig flags" > $$(PRIVATE_OUT) \
+		echo $(5) > $$(PRIVATE_OUT) \
 	)
 $(call copy-one-file, $(1), $(2))
 endef
 
 
 $(foreach partition, $(_FLAG_PARTITIONS), \
-	$(eval aconfig_flag_summaries.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.textproto) \
+	$(eval aconfig_flag_summaries_textproto.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.textproto) \
+	$(eval aconfig_flag_summaries_protobuf.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.pb) \
 	$(eval $(call generate-partition-aconfig-flag-file, \
 				$(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.textproto, \
-				$(aconfig_flag_summaries.$(partition)), \
+				$(aconfig_flag_summaries_textproto.$(partition)), \
 				$(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
 					$(ALL_MODULES.$(m).ACONFIG_FILES) \
-				)) \
+				)), \
+				textproto, \
+				"# No aconfig flags" \
+	)) \
+	$(eval $(call generate-partition-aconfig-flag-file, \
+				$(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.pb, \
+				$(aconfig_flag_summaries_protobuf.$(partition)), \
+				$(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
+					$(ALL_MODULES.$(m).ACONFIG_FILES) \
+				)), \
+				protobuf, \
+				"" \
 	)) \
 )
 
@@ -103,7 +117,8 @@
 required_flags_files := \
 		$(sort $(foreach partition, $(filter $(IMAGES_TO_BUILD), $(_FLAG_PARTITIONS)), \
 			$(build_flag_summaries.$(partition)) \
-			$(aconfig_flag_summaries.$(partition)) \
+			$(aconfig_flag_summaries_textproto.$(partition)) \
+			$(aconfig_flag_summaries_protobuf.$(partition)) \
 		))
 
 ALL_DEFAULT_INSTALLED_MODULES += $(required_flags_files)
@@ -118,6 +133,7 @@
 required_flags_files:=
 $(foreach partition, $(_FLAG_PARTITIONS), \
 	$(eval build_flag_summaries.$(partition):=) \
-	$(eval aconfig_flag_summaries.$(partition):=) \
+	$(eval aconfig_flag_summaries_textproto.$(partition):=) \
+	$(eval aconfig_flag_summaries_protobuf.$(partition):=) \
 )
 
diff --git a/core/product_config.mk b/core/product_config.mk
index 9f0cf25..b475d75 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -282,7 +282,11 @@
 
 #############################################################################
 # Check product include tag allowlist
-BLUEPRINT_INCLUDE_TAGS_ALLOWLIST := com.android.mainline_go com.android.mainline
+BLUEPRINT_INCLUDE_TAGS_ALLOWLIST := \
+  com.android.mainline_go \
+  com.android.mainline \
+  mainline_module_prebuilt_nightly \
+  mainline_module_prebuilt_monthly_release
 .KATI_READONLY := BLUEPRINT_INCLUDE_TAGS_ALLOWLIST
 $(foreach include_tag,$(PRODUCT_INCLUDE_TAGS), \
 	$(if $(filter $(include_tag),$(BLUEPRINT_INCLUDE_TAGS_ALLOWLIST)),,\
@@ -293,7 +297,8 @@
 # we still analyse it.
 # This means that in setups where we two have two prebuilts of module_sdk, we need a "default" to use in analysis
 # This should be a no-op in aosp and internal since no Android.bp file contains blueprint_package_includes
-PRODUCT_INCLUDE_TAGS += com.android.mainline # Use the big android one by default
+# Use the big android one and main-based prebuilts by default
+PRODUCT_INCLUDE_TAGS += com.android.mainline mainline_module_prebuilt_nightly
 endif
 
 #############################################################################
@@ -546,30 +551,12 @@
 
 $(KATI_obsolete_var OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE,Use PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE instead)
 
-# If build command defines PRODUCT_USE_PRODUCT_VNDK_OVERRIDE as `false`,
-# PRODUCT_PRODUCT_VNDK_VERSION will not be defined automatically.
-# PRODUCT_USE_PRODUCT_VNDK_OVERRIDE can be used for testing only.
-PRODUCT_USE_PRODUCT_VNDK := false
-ifneq ($(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE),)
-  PRODUCT_USE_PRODUCT_VNDK := $(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE)
-else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),)
-  # No shipping level defined. Enforce the product interface by default.
-  PRODUCT_USE_PRODUCT_VNDK := true
-else ifeq ($(call math_gt,$(PRODUCT_SHIPPING_API_LEVEL),29),true)
-  # Enforce product interface for VNDK if PRODUCT_SHIPPING_API_LEVEL is greater
-  # than 29.
-  PRODUCT_USE_PRODUCT_VNDK := true
+# From Android V, Define PRODUCT_PRODUCT_VNDK_VERSION as current by default.
+# This is required to make all devices have product variants.
+ifndef PRODUCT_PRODUCT_VNDK_VERSION
+  PRODUCT_PRODUCT_VNDK_VERSION := current
 endif
 
-ifeq ($(PRODUCT_USE_PRODUCT_VNDK),true)
-  ifndef PRODUCT_PRODUCT_VNDK_VERSION
-    PRODUCT_PRODUCT_VNDK_VERSION := current
-  endif
-endif
-
-$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK,Use PRODUCT_PRODUCT_VNDK_VERSION instead)
-$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK_OVERRIDE,Use PRODUCT_PRODUCT_VNDK_VERSION instead)
-
 ifdef PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS
     $(error PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS is deprecated, consider using RRO for \
       $(PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS))
diff --git a/core/release_config.bzl b/core/release_config.bzl
index 805106f..a2f59e6 100644
--- a/core/release_config.bzl
+++ b/core/release_config.bzl
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("//build/bazel/utils:schema_validation.bzl", "validate")
+
 # Partitions that get build system flag summaries
 _flag_partitions = [
     "product",
@@ -28,6 +30,48 @@
 
 _valid_types = ["NoneType", "bool", "list", "string", "int"]
 
+_all_flags_schema = {
+    "type": "list",
+    "of": {
+        "type": "dict",
+        "required_keys": {
+            "name": {"type": "string"},
+            "partitions": {
+                "type": "list",
+                "of": {
+                    "type": "string",
+                    "choices": _flag_partitions + ["all"],
+                },
+                "unique": True,
+            },
+            "default": {
+                "or": [
+                    {"type": t}
+                    for t in _valid_types
+                ],
+            },
+            "declared_in": {"type": "string"},
+        },
+    },
+}
+
+_all_values_schema = {
+    "type": "list",
+    "of": {
+        "type": "dict",
+        "required_keys": {
+            "name": {"type": "string"},
+            "value": {
+                "or": [
+                    {"type": t}
+                    for t in _valid_types
+                ],
+            },
+            "set_in": {"type": "string"},
+        },
+    },
+}
+
 def flag(name, partitions, default):
     "Declare a flag."
     if not partitions:
@@ -69,6 +113,8 @@
 
 def release_config(all_flags, all_values):
     "Return the make variables that should be set for this release config."
+    validate(all_flags, _all_flags_schema)
+    validate(all_values, _all_values_schema)
 
     # Validate flags
     flag_names = []
@@ -82,6 +128,8 @@
     for flag in all_flags:
         for partition in flag["partitions"]:
             if partition == "all":
+                if len(flag["partitions"]) > 1:
+                    fail("\"all\" can't be combined with other partitions: " + str(flag["partitions"]))
                 for partition in _flag_partitions:
                     partitions.setdefault(partition, []).append(flag["name"])
             else:
@@ -105,8 +153,6 @@
         if flag["name"] in values:
             val = values[flag["name"]]["value"]
             set_in = values[flag["name"]]["set_in"]
-            if type(val) not in _valid_types:
-                fail("Invalid type of value for flag \"" + flag["name"] + "\" (" + type(val) + ")")
         else:
             val = flag["default"]
             set_in = flag["declared_in"]
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 73f4f82..e00447a 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -275,16 +275,17 @@
 
 $(call add_json_str,  ShippingApiLevel, $(PRODUCT_SHIPPING_API_LEVEL))
 
-$(call add_json_list, BuildBrokenPluginValidation,        $(BUILD_BROKEN_PLUGIN_VALIDATION))
-$(call add_json_bool, BuildBrokenClangProperty,           $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
-$(call add_json_bool, BuildBrokenClangAsFlags,            $(filter true,$(BUILD_BROKEN_CLANG_ASFLAGS)))
-$(call add_json_bool, BuildBrokenClangCFlags,             $(filter true,$(BUILD_BROKEN_CLANG_CFLAGS)))
-$(call add_json_bool, GenruleSandboxing,                  $(filter true,$(GENRULE_SANDBOXING)))
-$(call add_json_bool, BuildBrokenEnforceSyspropOwner,     $(filter true,$(BUILD_BROKEN_ENFORCE_SYSPROP_OWNER)))
-$(call add_json_bool, BuildBrokenTrebleSyspropNeverallow, $(filter true,$(BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW)))
-$(call add_json_bool, BuildBrokenUsesSoongPython2Modules, $(filter true,$(BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES)))
-$(call add_json_bool, BuildBrokenVendorPropertyNamespace, $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
-$(call add_json_list, BuildBrokenInputDirModules, $(BUILD_BROKEN_INPUT_DIR_MODULES))
+$(call add_json_list, BuildBrokenPluginValidation,         $(BUILD_BROKEN_PLUGIN_VALIDATION))
+$(call add_json_bool, BuildBrokenClangProperty,            $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
+$(call add_json_bool, BuildBrokenClangAsFlags,             $(filter true,$(BUILD_BROKEN_CLANG_ASFLAGS)))
+$(call add_json_bool, BuildBrokenClangCFlags,              $(filter true,$(BUILD_BROKEN_CLANG_CFLAGS)))
+$(call add_json_bool, GenruleSandboxing,                   $(filter true,$(GENRULE_SANDBOXING)))
+$(call add_json_bool, BuildBrokenEnforceSyspropOwner,      $(filter true,$(BUILD_BROKEN_ENFORCE_SYSPROP_OWNER)))
+$(call add_json_bool, BuildBrokenTrebleSyspropNeverallow,  $(filter true,$(BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW)))
+$(call add_json_bool, BuildBrokenUsesSoongPython2Modules,  $(filter true,$(BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES)))
+$(call add_json_bool, BuildBrokenVendorPropertyNamespace,  $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
+$(call add_json_bool, BuildBrokenIncorrectPartitionImages, $(filter true,$(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES)))
+$(call add_json_list, BuildBrokenInputDirModules,          $(BUILD_BROKEN_INPUT_DIR_MODULES))
 
 $(call add_json_list, BuildWarningBadOptionalUsesLibsAllowlist,    $(BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST))
 
@@ -311,7 +312,7 @@
 $(call add_json_list, BuildVersionTags,    $(BUILD_VERSION_TAGS))
 
 $(call add_json_str, ReleaseVersion,    $(_RELEASE_VERSION))
-$(call add_json_list, ReleaseAconfigValueSets,    $(RELEASE_ACONFIG_VALUE_SETS))
+$(call add_json_str, ReleaseAconfigValueSets,    $(RELEASE_ACONFIG_VALUE_SETS))
 $(call add_json_str, ReleaseAconfigFlagDefaultPermission,    $(RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION))
 
 $(call add_json_bool, KeepVndk, $(filter true,$(KEEP_VNDK)))
diff --git a/core/version_util.mk b/core/version_util.mk
index 457f0f7..dca7482 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -169,17 +169,14 @@
 
 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.
+  # With trunk stable, VNDK will not be frozen but deprecated.
+  # This version will be removed with the VNDK deprecation.
   ifeq (REL,$(PLATFORM_VERSION_CODENAME))
-    PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
+    ifdef RELEASE_PLATFORM_VNDK_VERSION
+      PLATFORM_VNDK_VERSION := $(RELEASE_PLATFORM_VNDK_VERSION)
+    else
+      PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
+    endif
   else
     PLATFORM_VNDK_VERSION := $(PLATFORM_VERSION_CODENAME)
   endif
diff --git a/envsetup.sh b/envsetup.sh
index 0a90460..63837ec 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -2006,6 +2006,11 @@
             fi
         done
     done
+
+    if [[ "${PWD}" == /google/cog/* ]]; then
+        f="build/make/cogsetup.sh"
+        echo "including $f"; . "$T/$f"
+    fi
 }
 
 function showcommands() {
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index adeb159..15752aa 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -1,5 +1,14 @@
 LOCAL_PATH:= $(call my-dir)
 
+# VNDK will not be frozen if the PLATFORM_VNDK_VERSION is a codename or greater than 34
+ifeq ($(call math_is_number,$(PLATFORM_VNDK_VERSION)),)
+UNFROZEN_VNDK := true
+else
+ifeq ($(call math_gt,$(PLATFORM_VNDK_VERSION),34),true)
+UNFROZEN_VNDK := true
+endif
+endif
+
 #####################################################################
 # list of vndk libraries from the source code.
 INTERNAL_VNDK_LIB_LIST := $(SOONG_VNDK_LIBRARIES_FILE)
@@ -9,10 +18,14 @@
 # TODO(b/62012285): the lib list should be stored somewhere under
 # /prebuilts/vndk
 ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ifndef UNFROZEN_VNDK
 LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/$(PLATFORM_VNDK_VERSION).txt
 ifeq ($(wildcard $(LATEST_VNDK_LIB_LIST)),)
 $(error $(LATEST_VNDK_LIB_LIST) file not found. Please copy "$(LOCAL_PATH)/current.txt" to "$(LATEST_VNDK_LIB_LIST)" and commit a CL for release branch)
 endif
+else # UNFROZEN_VNDK
+LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/current.txt
+endif # UNFROZEN_VNDK
 else
 LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/current.txt
 endif
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/src/codegen_cpp.rs b/tools/aconfig/src/codegen_cpp.rs
index 8c2d7ba..5eadf2a 100644
--- a/tools/aconfig/src/codegen_cpp.rs
+++ b/tools/aconfig/src/codegen_cpp.rs
@@ -38,9 +38,9 @@
     let cpp_namespace = package.replace('.', "::");
     ensure!(codegen::is_valid_name_ident(&header));
     let context = Context {
-        header: header.clone(),
-        cpp_namespace,
-        package: package.to_string(),
+        header: &header,
+        cpp_namespace: &cpp_namespace,
+        package,
         readwrite,
         for_test: codegen_mode == CodegenMode::Test,
         class_elements,
@@ -77,10 +77,10 @@
 }
 
 #[derive(Serialize)]
-pub struct Context {
-    pub header: String,
-    pub cpp_namespace: String,
-    pub package: String,
+pub struct Context<'a> {
+    pub header: &'a str,
+    pub cpp_namespace: &'a str,
+    pub package: &'a str,
     pub readwrite: bool,
     pub for_test: bool,
     pub class_elements: Vec<ClassElement>,
@@ -364,6 +364,7 @@
     const TEST_SOURCE_FILE_EXPECTED: &str = r#"
 #include "com_android_aconfig_test.h"
 #include <server_configurable_flags/get_flags.h>
+#include <unordered_map>
 
 namespace com::android::aconfig::test {
 
@@ -517,7 +518,7 @@
         for file in generated {
             generated_files_map.insert(
                 String::from(file.path.to_str().unwrap()),
-                String::from_utf8(file.contents.clone()).unwrap(),
+                String::from_utf8(file.contents).unwrap(),
             );
         }
 
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index 7cdf486..702ef22 100644
--- a/tools/aconfig/src/codegen_java.rs
+++ b/tools/aconfig/src/codegen_java.rs
@@ -118,10 +118,14 @@
 
     const EXPECTED_FEATUREFLAGS_COMMON_CONTENT: &str = r#"
     package com.android.aconfig.test;
+    /** @hide */
     public interface FeatureFlags {
+        @com.android.aconfig.annotations.AssumeFalseForR8
         boolean disabledRo();
         boolean disabledRw();
+        @com.android.aconfig.annotations.AssumeTrueForR8
         boolean enabledFixedRo();
+        @com.android.aconfig.annotations.AssumeTrueForR8
         boolean enabledRo();
         boolean enabledRw();
     }
@@ -129,22 +133,31 @@
 
     const EXPECTED_FLAG_COMMON_CONTENT: &str = r#"
     package com.android.aconfig.test;
+    /** @hide */
     public final class Flags {
+        /** @hide */
         public static final String FLAG_DISABLED_RO = "com.android.aconfig.test.disabled_ro";
+        /** @hide */
         public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw";
+        /** @hide */
         public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro";
+        /** @hide */
         public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
+        /** @hide */
         public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
 
+        @com.android.aconfig.annotations.AssumeFalseForR8
         public static boolean disabledRo() {
             return FEATURE_FLAGS.disabledRo();
         }
         public static boolean disabledRw() {
             return FEATURE_FLAGS.disabledRw();
         }
+        @com.android.aconfig.annotations.AssumeTrueForR8
         public static boolean enabledFixedRo() {
             return FEATURE_FLAGS.enabledFixedRo();
         }
+        @com.android.aconfig.annotations.AssumeTrueForR8
         public static boolean enabledRo() {
             return FEATURE_FLAGS.enabledRo();
         }
@@ -157,29 +170,30 @@
     package com.android.aconfig.test;
     import java.util.HashMap;
     import java.util.Map;
+    /** @hide */
     public class FakeFeatureFlagsImpl implements FeatureFlags {
         public FakeFeatureFlagsImpl() {
             resetAll();
         }
         @Override
         public boolean disabledRo() {
-            return getFlag(Flags.FLAG_DISABLED_RO);
+            return getValue(Flags.FLAG_DISABLED_RO);
         }
         @Override
         public boolean disabledRw() {
-            return getFlag(Flags.FLAG_DISABLED_RW);
+            return getValue(Flags.FLAG_DISABLED_RW);
         }
         @Override
         public boolean enabledFixedRo() {
-            return getFlag(Flags.FLAG_ENABLED_FIXED_RO);
+            return getValue(Flags.FLAG_ENABLED_FIXED_RO);
         }
         @Override
         public boolean enabledRo() {
-            return getFlag(Flags.FLAG_ENABLED_RO);
+            return getValue(Flags.FLAG_ENABLED_RO);
         }
         @Override
         public boolean enabledRw() {
-            return getFlag(Flags.FLAG_ENABLED_RW);
+            return getValue(Flags.FLAG_ENABLED_RW);
         }
         public void setFlag(String flagName, boolean value) {
             if (!this.mFlagMap.containsKey(flagName)) {
@@ -192,7 +206,7 @@
                 entry.setValue(null);
             }
         }
-        private boolean getFlag(String flagName) {
+        private boolean getValue(String flagName) {
             Boolean value = this.mFlagMap.get(flagName);
             if (value == null) {
                 throw new IllegalArgumentException(flagName + " is not set");
@@ -228,6 +242,7 @@
         let expect_featureflagsimpl_content = r#"
         package com.android.aconfig.test;
         import android.provider.DeviceConfig;
+        /** @hide */
         public final class FeatureFlagsImpl implements FeatureFlags {
             @Override
             public boolean disabledRo() {
@@ -235,7 +250,7 @@
             }
             @Override
             public boolean disabledRw() {
-                return DeviceConfig.getBoolean(
+                return getValue(
                     "aconfig_test",
                     "com.android.aconfig.test.disabled_rw",
                     false
@@ -251,12 +266,33 @@
             }
             @Override
             public boolean enabledRw() {
-                return DeviceConfig.getBoolean(
+                return getValue(
                     "aconfig_test",
                     "com.android.aconfig.test.enabled_rw",
                     true
                 );
             }
+            private boolean getValue(String nameSpace,
+                String flagName, boolean defaultValue) {
+                boolean value = defaultValue;
+                try {
+                    value = DeviceConfig.getBoolean(
+                        nameSpace,
+                        flagName,
+                        defaultValue
+                    );
+                } catch (NullPointerException e) {
+                    throw new RuntimeException(
+                        "Cannot read value of flag " + flagName + " from DeviceConfig. " +
+                        "It could be that the code using flag executed " +
+                        "before SettingsProvider initialization. " +
+                        "Please use fixed read-only flag by adding " +
+                        "is_fixed_read_only: true in flag declaration.",
+                        e
+                    );
+                }
+                return value;
+            }
         }
         "#;
         let mut file_set = HashMap::from([
@@ -276,7 +312,7 @@
                 None,
                 crate::test::first_significant_code_diff(
                     file_set.get(file_path).unwrap(),
-                    &String::from_utf8(file.contents.clone()).unwrap()
+                    &String::from_utf8(file.contents).unwrap()
                 ),
                 "File {} content is not correct",
                 file_path
@@ -310,6 +346,7 @@
         "#;
         let expect_featureflagsimpl_content = r#"
         package com.android.aconfig.test;
+        /** @hide */
         public final class FeatureFlagsImpl implements FeatureFlags {
             @Override
             public boolean disabledRo() {
@@ -356,7 +393,7 @@
                 None,
                 crate::test::first_significant_code_diff(
                     file_set.get(file_path).unwrap(),
-                    &String::from_utf8(file.contents.clone()).unwrap()
+                    &String::from_utf8(file.contents).unwrap()
                 ),
                 "File {} content is not correct",
                 file_path
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 84073f7..7e44baf 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -137,14 +137,14 @@
 }
 
 fn write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()> {
-    let path = root.join(output_file.path.clone());
+    let path = root.join(&output_file.path);
     let parent = path
         .parent()
         .ok_or(anyhow!("unable to locate parent of output file {}", path.display()))?;
     fs::create_dir_all(parent)
         .with_context(|| format!("failed to create directory {}", parent.display()))?;
-    let mut file = fs::File::create(path.clone())
-        .with_context(|| format!("failed to open {}", path.display()))?;
+    let mut file =
+        fs::File::create(&path).with_context(|| format!("failed to open {}", path.display()))?;
     file.write_all(&output_file.contents)
         .with_context(|| format!("failed to write to {}", path.display()))?;
     Ok(())
diff --git a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
index 82bea81..e4a1fb7 100644
--- a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
@@ -3,6 +3,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+/** @hide */
 public class FakeFeatureFlagsImpl implements FeatureFlags \{
     public FakeFeatureFlagsImpl() \{
         resetAll();
@@ -11,7 +12,7 @@
 {{ for item in class_elements}}
     @Override
     public boolean {item.method_name}() \{
-        return getFlag(Flags.FLAG_{item.flag_name_constant_suffix});
+        return getValue(Flags.FLAG_{item.flag_name_constant_suffix});
     }
 {{ endfor}}
     public void setFlag(String flagName, boolean value) \{
@@ -27,7 +28,7 @@
         }
     }
 
-    private boolean getFlag(String flagName) \{
+    private boolean getValue(String flagName) \{
         Boolean value = this.mFlagMap.get(flagName);
         if (value == null) \{
             throw new IllegalArgumentException(flagName + " is not set");
diff --git a/tools/aconfig/templates/FeatureFlags.java.template b/tools/aconfig/templates/FeatureFlags.java.template
index e0f201f..9350d60 100644
--- a/tools/aconfig/templates/FeatureFlags.java.template
+++ b/tools/aconfig/templates/FeatureFlags.java.template
@@ -1,7 +1,15 @@
 package {package_name};
 
+/** @hide */
 public interface FeatureFlags \{
 {{ for item in class_elements}}
+{{ -if not item.is_read_write }}
+{{ -if item.default_value }}
+    @com.android.aconfig.annotations.AssumeTrueForR8
+{{ -else }}
+    @com.android.aconfig.annotations.AssumeFalseForR8
+{{ -endif- }}
+{{ endif }}
     boolean {item.method_name}();
 {{ endfor }}
 }
diff --git a/tools/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/templates/FeatureFlagsImpl.java.template
index 96de06c..3913fa4 100644
--- a/tools/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -3,12 +3,13 @@
 {{ if is_read_write- }}
 import android.provider.DeviceConfig;
 {{ endif }}
+/** @hide */
 public final class FeatureFlagsImpl implements FeatureFlags \{
 {{ for item in class_elements}}
     @Override
     public boolean {item.method_name}() \{
     {{ -if item.is_read_write }}
-        return DeviceConfig.getBoolean(
+        return getValue(
             "{item.device_config_namespace}",
             "{item.device_config_flag}",
             {item.default_value}
@@ -18,9 +19,33 @@
     {{ endif- }}
     }
 {{ endfor }}
+{{ if is_read_write- }}
+    private boolean getValue(String nameSpace,
+        String flagName, boolean defaultValue) \{
+        boolean value = defaultValue;
+        try \{
+            value = DeviceConfig.getBoolean(
+                nameSpace,
+                flagName,
+                defaultValue
+            );
+        } catch (NullPointerException e) \{
+            throw new RuntimeException(
+                "Cannot read value of flag " + flagName + " from DeviceConfig. " +
+                "It could be that the code using flag executed " +
+                "before SettingsProvider initialization. " +
+                "Please use fixed read-only flag by adding " +
+                "is_fixed_read_only: true in flag declaration.",
+                e
+            );
+        }
+        return value;
+    }
+{{ endif- }}
 }
 {{ else }}
 {#- Generate only stub if in test mode #}
+/** @hide */
 public final class FeatureFlagsImpl implements FeatureFlags \{
 {{ for item in class_elements}}
     @Override
diff --git a/tools/aconfig/templates/Flags.java.template b/tools/aconfig/templates/Flags.java.template
index 012eba6..39024a8 100644
--- a/tools/aconfig/templates/Flags.java.template
+++ b/tools/aconfig/templates/Flags.java.template
@@ -1,10 +1,19 @@
 package {package_name};
 
+/** @hide */
 public final class Flags \{
 {{- for item in class_elements}}
+    /** @hide */
     public static final String FLAG_{item.flag_name_constant_suffix} = "{item.device_config_flag}";
 {{- endfor }}
 {{ for item in class_elements}}
+{{ -if not item.is_read_write }}
+{{ -if item.default_value }}
+    @com.android.aconfig.annotations.AssumeTrueForR8
+{{ -else }}
+    @com.android.aconfig.annotations.AssumeFalseForR8
+{{ -endif- }}
+{{ endif }}
     public static boolean {item.method_name}() \{
         return FEATURE_FLAGS.{item.method_name}();
     }
@@ -17,7 +26,7 @@
     public static void unsetFeatureFlags() \{
         Flags.FEATURE_FLAGS = null;
     }
-{{ endif}}
+{{ endif }}
     private static FeatureFlags FEATURE_FLAGS{{ -if not is_test_mode }} = new FeatureFlagsImpl(){{ -endif- }};
 
 }
diff --git a/tools/aconfig/templates/cpp_source_file.template b/tools/aconfig/templates/cpp_source_file.template
index f373bc6..c0e7343 100644
--- a/tools/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/templates/cpp_source_file.template
@@ -2,6 +2,9 @@
 {{ if readwrite }}
 #include <server_configurable_flags/get_flags.h>
 {{ endif }}
+{{ if for_test }}
+#include <unordered_map>
+{{ endif }}
 
 namespace {cpp_namespace} \{
 
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
index ce64160..0bf47c6 100755
--- a/tools/auto_gen_test_config.py
+++ b/tools/auto_gen_test_config.py
@@ -17,6 +17,7 @@
 """A tool to generate TradeFed test config file.
 """
 
+import re
 import os
 import shutil
 import sys
@@ -44,9 +45,9 @@
   """
   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 '
+        f'Invalid arguments: {argv}. The script requires 4 arguments for file paths: '
+        'target_config, android_manifest (or the xmltree dump), empty_config, '
+        'instrumentation_test_config_template, '
         'and 2 optional arguments for extra configs: '
         '--extra-configs \'EXTRA_CONFIGS\'.\n')
     return 1
@@ -57,27 +58,62 @@
   instrumentation_test_config_template = argv[3]
   extra_configs = '\n'.join(argv[5].split('\\n')) if len(argv) == 6 else ''
 
-  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
-
   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.readlines():
+        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/build_image.py b/tools/releasetools/build_image.py
index 8c6d597..5e4130c 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2011 The Android Open Source Project
 #
@@ -22,9 +22,9 @@
             target_output_directory
 """
 
-from __future__ import print_function
 import datetime
 
+import argparse
 import glob
 import logging
 import os
@@ -34,6 +34,7 @@
 import shutil
 import sys
 import uuid
+import tempfile
 
 import common
 import verity_utils
@@ -919,27 +920,69 @@
   common.BuildVBMeta(output_path, partitions, name, vbmeta_partitions)
 
 
-def main(argv):
-  args = common.ParseOptions(argv, __doc__)
+def BuildImageOrVBMeta(input_directory, target_out, glob_dict, image_properties, out_file):
+  try:
+    if "vbmeta" in os.path.basename(out_file):
+      OPTIONS.info_dict = glob_dict
+      BuildVBMeta(input_directory, glob_dict, out_file)
+    else:
+      BuildImage(input_directory, image_properties, out_file, target_out)
+  except:
+    logger.error("Failed to build %s from %s", out_file, input_directory)
+    raise
 
-  if len(args) != 4:
-    print(__doc__)
-    sys.exit(1)
+
+def CopyInputDirectory(src, dst, filter_file):
+  with open(filter_file, 'r') as f:
+    for line in f:
+      line = line.strip()
+      if not line:
+        return
+      if line != os.path.normpath(line):
+        sys.exit(f"{line}: not normalized")
+      if line.startswith("../") or line.startswith('/'):
+        sys.exit(f"{line}: escapes staging directory by starting with ../ or /")
+      full_src = os.path.join(src, line)
+      full_dst = os.path.join(dst, line)
+      if os.path.isdir(full_src):
+        os.makedirs(full_dst, exist_ok=True)
+      else:
+        os.makedirs(os.path.dirname(full_dst), exist_ok=True)
+        os.link(full_src, full_dst, follow_symlinks=False)
+
+
+def main(argv):
+  parser = argparse.ArgumentParser(
+    description="Builds output_image from the given input_directory and properties_file, and "
+    "writes the image to target_output_directory.")
+  parser.add_argument("--input-directory-filter-file",
+    help="the path to a file that contains a list of all files in the input_directory. If this "
+    "option is provided, all files under the input_directory that are not listed in this file will "
+    "be deleted before building the image. This is to work around the fact that building a module "
+    "will install in by default, so there could be files in the input_directory that are not "
+    "actually supposed to be part of the partition. The paths in this file must be relative to "
+    "input_directory.")
+  parser.add_argument("input_directory",
+    help="the staging directory to be converted to an image file")
+  parser.add_argument("properties_file",
+    help="a file containing the 'global dictionary' of properties that affect how the image is "
+    "built")
+  parser.add_argument("out_file",
+    help="the output file to write")
+  parser.add_argument("target_out",
+    help="the path to $(TARGET_OUT). Certain tools will use this to look through multiple staging "
+    "directories for fs config files.")
+  args = parser.parse_args()
 
   common.InitLogging()
 
-  in_dir = args[0]
-  glob_dict_file = args[1]
-  out_file = args[2]
-  target_out = args[3]
-
-  glob_dict = LoadGlobalDict(glob_dict_file)
+  glob_dict = LoadGlobalDict(args.properties_file)
   if "mount_point" in glob_dict:
     # The caller knows the mount point and provides a dictionary needed by
     # BuildImage().
     image_properties = glob_dict
   else:
-    image_filename = os.path.basename(out_file)
+    image_filename = os.path.basename(args.out_file)
     mount_point = ""
     if image_filename == "system.img":
       mount_point = "system"
@@ -974,15 +1017,12 @@
     if "vbmeta" != mount_point:
       image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
 
-  try:
-    if "vbmeta" in os.path.basename(out_file):
-      OPTIONS.info_dict = glob_dict
-      BuildVBMeta(in_dir, glob_dict, out_file)
-    else:
-      BuildImage(in_dir, image_properties, out_file, target_out)
-  except:
-    logger.error("Failed to build %s from %s", out_file, in_dir)
-    raise
+  if args.input_directory_filter_file and not os.environ.get("BUILD_BROKEN_INCORRECT_PARTITION_IMAGES"):
+    with tempfile.TemporaryDirectory(dir=os.path.dirname(args.input_directory)) as new_input_directory:
+      CopyInputDirectory(args.input_directory, new_input_directory, args.input_directory_filter_file)
+      BuildImageOrVBMeta(new_input_directory, args.target_out, glob_dict, image_properties, args.out_file)
+  else:
+    BuildImageOrVBMeta(args.input_directory, args.target_out, glob_dict, image_properties, args.out_file)
 
 
 if __name__ == '__main__':
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index ec53a47..4bcb8fc 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -194,7 +194,7 @@
           '': {
               'handlers': ['default'],
               'propagate': True,
-              'level': 'INFO',
+              'level': 'WARNING',
           }
       }
   }
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index 5412b2a..a3e3681 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -64,7 +64,7 @@
 OPTIONS.retrofit_dap = None
 OPTIONS.build_super = None
 OPTIONS.sparse_userimages = None
-OPTIONS.use_fastboot_info = False
+OPTIONS.use_fastboot_info = True
 OPTIONS.build_super_image = None
 
 def LoadOptions(input_file):
diff --git a/tools/releasetools/merge/merge_meta.py b/tools/releasetools/merge/merge_meta.py
index 81c3510..198c973 100644
--- a/tools/releasetools/merge/merge_meta.py
+++ b/tools/releasetools/merge/merge_meta.py
@@ -53,8 +53,6 @@
 MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
 
 
-
-
 def MergeUpdateEngineConfig(input_metadir1, input_metadir2, merged_meta_dir):
   UPDATE_ENGINE_CONFIG_NAME = "update_engine_config.txt"
   config1_path = os.path.join(
@@ -74,7 +72,7 @@
         merged_meta_dir, UPDATE_ENGINE_CONFIG_NAME))
 
 
-def MergeMetaFiles(temp_dir, merged_dir):
+def MergeMetaFiles(temp_dir, merged_dir, framework_partitions):
   """Merges various files in META/*."""
 
   framework_meta_dir = os.path.join(temp_dir, 'framework_meta', 'META')
@@ -114,7 +112,8 @@
     MergeAbPartitions(
         framework_meta_dir=framework_meta_dir,
         vendor_meta_dir=vendor_meta_dir,
-        merged_meta_dir=merged_meta_dir)
+        merged_meta_dir=merged_meta_dir,
+        framework_partitions=framework_partitions)
     UpdateCareMapImageSizeProps(images_dir=os.path.join(merged_dir, 'IMAGES'))
 
   for file_name in ('apkcerts.txt', 'apexkeys.txt'):
@@ -135,13 +134,22 @@
       path=os.path.join(merged_meta_dir, 'misc_info.txt'))
 
 
-def MergeAbPartitions(framework_meta_dir, vendor_meta_dir, merged_meta_dir):
+def MergeAbPartitions(framework_meta_dir, vendor_meta_dir, merged_meta_dir,
+                      framework_partitions):
   """Merges META/ab_partitions.txt.
 
   The output contains the union of the partition names.
   """
   with open(os.path.join(framework_meta_dir, 'ab_partitions.txt')) as f:
-    framework_ab_partitions = f.read().splitlines()
+    # Filter out some partitions here to support the case that the
+    # ab_partitions.txt of framework-target-files has non-framework partitions.
+    # This case happens when we use a complete merged target files package as
+    # the framework-target-files.
+    framework_ab_partitions = [
+        partition
+        for partition in f.read().splitlines()
+        if partition in framework_partitions
+    ]
 
   with open(os.path.join(vendor_meta_dir, 'ab_partitions.txt')) as f:
     vendor_ab_partitions = f.read().splitlines()
diff --git a/tools/releasetools/merge/merge_target_files.py b/tools/releasetools/merge/merge_target_files.py
index d8f7b15..a0d3a1c 100755
--- a/tools/releasetools/merge/merge_target_files.py
+++ b/tools/releasetools/merge/merge_target_files.py
@@ -209,7 +209,9 @@
   # After this function completes successfully, all the files we need to create
   # the output target files package are in place.
   merge_meta.MergeMetaFiles(
-      temp_dir=temp_dir, merged_dir=output_target_files_temp_dir)
+      temp_dir=temp_dir,
+      merged_dir=output_target_files_temp_dir,
+      framework_partitions=OPTIONS.framework_partition_set)
 
   merge_dexopt.MergeDexopt(
       temp_dir=temp_dir, output_target_files_dir=output_target_files_temp_dir)
diff --git a/tools/releasetools/ota_from_raw_img.py b/tools/releasetools/ota_from_raw_img.py
index 63f88ea..0c1c05a 100644
--- a/tools/releasetools/ota_from_raw_img.py
+++ b/tools/releasetools/ota_from_raw_img.py
@@ -84,6 +84,7 @@
     cmd.append("--is_partial_update")
     if args.max_timestamp:
       cmd.append("--max_timestamp=" + str(args.max_timestamp))
+      cmd.append("--partition_timestamps=boot:" + str(args.max_timestamp))
     logger.info("Running %s", cmd)
 
     subprocess.check_call(cmd)
diff --git a/tools/zipalign/ZipEntry.cpp b/tools/zipalign/ZipEntry.cpp
index 689999e..0355e56 100644
--- a/tools/zipalign/ZipEntry.cpp
+++ b/tools/zipalign/ZipEntry.cpp
@@ -18,6 +18,8 @@
 // Access to entries in a Zip archive.
 //
 
+#define _POSIX_THREAD_SAFE_FUNCTIONS  // For mingw localtime_r().
+
 #define LOG_TAG "zip"
 
 #include "ZipEntry.h"
@@ -354,31 +356,29 @@
  */
 void ZipEntry::setModWhen(time_t when)
 {
-#if !defined(_WIN32)
-    struct tm tmResult;
-#endif
-    time_t even;
-    uint16_t zdate, ztime;
-
-    struct tm* ptm;
-
     /* round up to an even number of seconds */
-    even = (when & 1) ? (when + 1) : when;
+    time_t even = (when & 1) ? (when + 1) : when;
 
     /* expand */
-#if !defined(_WIN32)
-    ptm = localtime_r(&even, &tmResult);
-#else
-    ptm = localtime(&even);
-#endif
+    struct tm tmResult;
+    struct tm* ptm = localtime_r(&even, &tmResult);
 
-    int year;
-    year = ptm->tm_year;
-    if (year < 80)
-        year = 80;
+    // The earliest valid time for ZIP file entries is 1980-01-01. See:
+    // https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html.
+    // Set any time before 1980 to 1980-01-01.
+    if (ptm->tm_year < 80) {
+        ptm->tm_year = 80;
+        ptm->tm_mon = 0;
+        ptm->tm_mday = 1;
+        ptm->tm_hour = 0;
+        ptm->tm_min = 0;
+        ptm->tm_sec = 0;
+    }
 
-    zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday;
-    ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
+    uint16_t zdate = static_cast<uint16_t>(
+        (ptm->tm_year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday);
+    uint16_t ztime = static_cast<uint16_t>(
+        ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1);
 
     mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime;
     mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;