Merge "Add warning for modifying the vendor api level." into main
diff --git a/core/Makefile b/core/Makefile
index dd79dd2..150f5bc 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -800,7 +800,7 @@
 	  $(if $(filter true,$(BUILDING_SYSTEM_EXT_IMAGE)),\
             $(call _apkcerts_write_line,BuildManifestSystemExt,$(FSVERITY_APK_KEY_PATH).x509.pem,$(FSVERITY_APK_KEY_PATH).pk8,,system_ext,$@)))
 	# In case value of PACKAGES is empty.
-	$(hide) touch $@
+	$(hide) touch $@ && sort -u -o $@ $@
 
 $(call declare-0p-target,$(APKCERTS_FILE))
 
@@ -5743,64 +5743,6 @@
 .PHONY: otatools
 otatools: $(INTERNAL_OTATOOLS_FILES)
 
-# For each module, recursively resolve its host shared library dependencies. Then we have a full
-# list of modules whose installed files need to be packed.
-INTERNAL_OTATOOLS_MODULES_WITH_DEPS := \
-  $(sort $(INTERNAL_OTATOOLS_MODULES) \
-      $(foreach m,$(INTERNAL_OTATOOLS_MODULES),$(call get-all-shared-libs-deps,$(m))))
-
-INTERNAL_OTATOOLS_PACKAGE_FILES := \
-  $(filter $(HOST_OUT)/%,$(call module-installed-files,$(INTERNAL_OTATOOLS_MODULES_WITH_DEPS)))
-
-INTERNAL_OTATOOLS_PACKAGE_FILES += \
-  $(sort $(shell find build/make/target/product/security -type f -name "*.x509.pem" -o \
-      -name "*.pk8"))
-
-ifneq (,$(wildcard packages/modules))
-INTERNAL_OTATOOLS_PACKAGE_FILES += \
-  $(sort $(shell find packages/modules -type f -name "*.x509.pem" -o -name "*.pk8" -o -name \
-      "key.pem"))
-endif
-
-ifneq (,$(wildcard device))
-INTERNAL_OTATOOLS_PACKAGE_FILES += \
-  $(sort $(shell find device $(wildcard vendor) -type f -name "*.pk8" -o -name "verifiedboot*" -o \
-      -name "*.pem" -o -name "oem*.prop" -o -name "*.avbpubkey"))
-endif
-ifneq (,$(wildcard external/avb))
-INTERNAL_OTATOOLS_PACKAGE_FILES += \
-  $(sort $(shell find external/avb/test/data -type f -name "testkey_*.pem" -o \
-      -name "atx_metadata.bin"))
-endif
-
-INTERNAL_OTATOOLS_RELEASETOOLS := \
-  $(shell find build/make/tools/releasetools -name "*.pyc" -prune -o \
-      \( -type f -o -type l \) -print | sort)
-
-BUILT_OTATOOLS_PACKAGE := $(PRODUCT_OUT)/otatools.zip
-$(BUILT_OTATOOLS_PACKAGE): PRIVATE_ZIP_ROOT := $(call intermediates-dir-for,PACKAGING,otatools)/otatools
-$(BUILT_OTATOOLS_PACKAGE): PRIVATE_OTATOOLS_PACKAGE_FILES := $(INTERNAL_OTATOOLS_PACKAGE_FILES)
-$(BUILT_OTATOOLS_PACKAGE): PRIVATE_OTATOOLS_RELEASETOOLS := $(INTERNAL_OTATOOLS_RELEASETOOLS)
-$(BUILT_OTATOOLS_PACKAGE): $(INTERNAL_OTATOOLS_PACKAGE_FILES) $(INTERNAL_OTATOOLS_RELEASETOOLS)
-$(BUILT_OTATOOLS_PACKAGE): $(SOONG_ZIP) $(ZIP2ZIP)
-	@echo "Package OTA tools: $@"
-	rm -rf $@ $(PRIVATE_ZIP_ROOT)
-	mkdir -p $(dir $@)
-	$(call copy-files-with-structure,$(PRIVATE_OTATOOLS_PACKAGE_FILES),$(HOST_OUT)/,$(PRIVATE_ZIP_ROOT))
-	$(call copy-files-with-structure,$(PRIVATE_OTATOOLS_RELEASETOOLS),build/make/tools/,$(PRIVATE_ZIP_ROOT))
-	cp $(SOONG_ZIP) $(ZIP2ZIP) $(MERGE_ZIPS) $(PRIVATE_ZIP_ROOT)/bin/
-	$(SOONG_ZIP) -o $@ -C $(PRIVATE_ZIP_ROOT) -D $(PRIVATE_ZIP_ROOT)
-
-$(call declare-1p-container,$(BUILT_OTATOOLS_PACKAGE),build)
-$(call declare-container-license-deps,$(INTERNAL_OTATOOLS_PACKAGE_FILES) $(INTERNAL_OTATOOLS_RELEASETOOLS),$(BUILT_OTATOOLS_PACKAGE):)
-
-.PHONY: otatools-package
-otatools-package: $(BUILT_OTATOOLS_PACKAGE)
-
-$(call dist-for-goals, otatools-package, \
-  $(BUILT_OTATOOLS_PACKAGE) \
-)
-
 endif # build_otatools_package
 
 # -----------------------------------------------------------------
@@ -7988,6 +7930,7 @@
 # -----------------------------------------------------------------
 # Desktop pack common variables.
 PACK_IMAGE_SCRIPT := $(HOST_OUT_EXECUTABLES)/pack_image
+UPDATE_PARTITION_SCRIPT := $(HOST_OUT_EXECUTABLES)/update-partition
 IMAGES := $(INSTALLED_BOOTIMAGE_TARGET) \
 	$(INSTALLED_SUPERIMAGE_TARGET) \
 	$(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
@@ -8050,6 +7993,32 @@
 .PHONY: pack-recovery-image
 pack-recovery-image: $(PACK_RECOVERY_IMAGE_TARGET)
 
+RECOVERY_SWAP_KERNEL_TARGET := $(PRODUCT_OUT)/recovery-kernel-swap
+
+# Has swap kernel for insecure recovery image.
+ifeq ($(BOARD_USES_DESKTOP_RECOVERY_SWAP_KERNEL),true)
+
+$(call dist-for-goals,dist_files,$(RECOVERY_SWAP_KERNEL_TARGET))
+
+PACK_INSECURE_RECOVERY_IMAGE_TARGET := $(PRODUCT_OUT)/android-desktop_insecure_recovery_image.bin
+
+$(PACK_INSECURE_RECOVERY_IMAGE_TARGET): PRIVATE_SGDISK := $(HOST_OUT_EXECUTABLES)/sgdisk
+$(PACK_INSECURE_RECOVERY_IMAGE_TARGET): $(PACK_RECOVERY_IMAGE_TARGET) $(UPDATE_PARTITION_SCRIPT) $(RECOVERY_SWAP_KERNEL_TARGET)
+	@cp -f $< $@
+	(export SGDISK=$(PRIVATE_SGDISK); $(UPDATE_PARTITION_SCRIPT) KERN-A $@ $(RECOVERY_SWAP_KERNEL_TARGET))
+
+PACKED_INSECURE_RECOVERY_IMAGE_ARCHIVE_TARGET := $(PACK_INSECURE_RECOVERY_IMAGE_TARGET).gz
+
+$(PACKED_INSECURE_RECOVERY_IMAGE_ARCHIVE_TARGET): $(PACK_INSECURE_RECOVERY_IMAGE_TARGET) | $(GZIP)
+	$(GZIP) -fk $(PACK_INSECURE_RECOVERY_IMAGE_TARGET)
+
+$(call dist-for-goals,dist_files,$(PACKED_INSECURE_RECOVERY_IMAGE_ARCHIVE_TARGET))
+
+.PHONY: pack-insecure-recovery-image
+pack-insecure-recovery-image: $(PACK_INSECURE_RECOVERY_IMAGE_TARGET)
+
+endif # BOARD_USES_DESKTOP_RECOVERY_SWAP_KERNEL
+
 endif # BOARD_USES_DESKTOP_RECOVERY_IMAGE
 
 # -----------------------------------------------------------------
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 1a40ccc..377d6e8 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -370,3 +370,11 @@
 
 # Flags used in GTVS_GTV prebuilt apps
 $(call soong_config_set_bool,GTVS_GTV,PRODUCT_USE_PREBUILT_GTVS_GTV,$(if $(findstring $(PRODUCT_USE_PREBUILT_GTVS_GTV),true yes),true,false))
+
+# Check modules to be built in "otatools-package".
+ifneq ($(wildcard vendor/google/tools/build_mixed_kernels_ramdisk),)
+  $(call soong_config_set_bool,otatools,use_build_mixed_kernels_ramdisk,true)
+endif
+ifneq ($(wildcard bootable/deprecated-ota/applypatch),)
+  $(call soong_config_set_bool,otatools,use_bootable_deprecated_ota_applypatch,true)
+endif
diff --git a/core/board_config.mk b/core/board_config.mk
index 16cf863..4bd473e 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -933,6 +933,12 @@
 endif
 .KATI_READONLY := BOARD_USES_DESKTOP_RECOVERY_IMAGE
 
+BOARD_USES_DESKTOP_RECOVERY_SWAP_KERNEL :=
+ifeq ($(PRODUCT_USES_DESKTOP_RECOVERY_SWAP_KERNEL),true)
+  BOARD_USES_DESKTOP_RECOVERY_SWAP_KERNEL := true
+endif
+.KATI_READONLY := BOARD_USES_DESKTOP_RECOVERY_SWAP_KERNEL
+
 BOARD_USES_DESKTOP_UPDATE_IMAGE :=
 ifeq ($(PRODUCT_BUILD_DESKTOP_UPDATE_IMAGE),true)
   BOARD_USES_DESKTOP_UPDATE_IMAGE := true
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 11c1944..35a62fa 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -58,12 +58,10 @@
   $(error TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT must be set)
 endif
 
-TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_$(combo_2nd_arch_prefix)ARCH)/$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT).mk
-ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
-  $(error Unknown ARM architecture version: $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
-endif
-
-include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
+# NEON is mandatory, see: https://developer.android.com/ndk/guides/abis#v7a
+ARCH_ARM_HAVE_VFP               := true
+ARCH_ARM_HAVE_VFP_D32           := true
+ARCH_ARM_HAVE_NEON              := true
 
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
diff --git a/core/combo/TARGET_linux-arm64.mk b/core/combo/TARGET_linux-arm64.mk
index 5d481cb..992dce8 100644
--- a/core/combo/TARGET_linux-arm64.mk
+++ b/core/combo/TARGET_linux-arm64.mk
@@ -33,13 +33,6 @@
 TARGET_ARCH_VARIANT := armv8
 endif
 
-TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
-ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
-$(error Unknown ARM architecture version: $(TARGET_ARCH_VARIANT))
-endif
-
-include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
diff --git a/core/combo/TARGET_linux-riscv64.mk b/core/combo/TARGET_linux-riscv64.mk
index 8f8fd3c..0a6cfa4 100644
--- a/core/combo/TARGET_linux-riscv64.mk
+++ b/core/combo/TARGET_linux-riscv64.mk
@@ -22,17 +22,6 @@
 TARGET_ARCH_VARIANT := riscv64
 endif
 
-# Include the arch-variant-specific configuration file.
-# Its role is to define various ARCH_X86_HAVE_XXX feature macros,
-# plus initial values for TARGET_GLOBAL_CFLAGS
-#
-TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
-ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
-$(error Unknown $(TARGET_ARCH) architecture version: $(TARGET_ARCH_VARIANT))
-endif
-
-include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
index acbae51..9ab6880 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -22,17 +22,6 @@
 TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := x86
 endif
 
-# Include the arch-variant-specific configuration file.
-# Its role is to define various ARCH_X86_HAVE_XXX feature macros,
-# plus initial values for TARGET_GLOBAL_CFLAGS
-#
-TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_$(combo_2nd_arch_prefix)ARCH)/$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT).mk
-ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
-$(error Unknown $(TARGET_$(combo_2nd_arch_prefix)ARCH) architecture version: $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
-endif
-
-include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
diff --git a/core/combo/TARGET_linux-x86_64.mk b/core/combo/TARGET_linux-x86_64.mk
index 9e7e363..6dd7b03 100644
--- a/core/combo/TARGET_linux-x86_64.mk
+++ b/core/combo/TARGET_linux-x86_64.mk
@@ -22,17 +22,6 @@
 TARGET_ARCH_VARIANT := x86_64
 endif
 
-# Include the arch-variant-specific configuration file.
-# Its role is to define various ARCH_X86_HAVE_XXX feature macros,
-# plus initial values for TARGET_GLOBAL_CFLAGS
-#
-TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
-ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
-$(error Unknown $(TARGET_ARCH) architecture version: $(TARGET_ARCH_VARIANT))
-endif
-
-include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
diff --git a/core/combo/arch/arm/armv7-a-neon.mk b/core/combo/arch/arm/armv7-a-neon.mk
deleted file mode 100644
index 0c01ac3..0000000
--- a/core/combo/arch/arm/armv7-a-neon.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on ARM.
-# Generating binaries for the ARMv7-a architecture and higher with NEON
-#
-ARCH_ARM_HAVE_VFP               := true
-ARCH_ARM_HAVE_VFP_D32           := true
-ARCH_ARM_HAVE_NEON              := true
diff --git a/core/combo/arch/arm/armv8-2a.mk b/core/combo/arch/arm/armv8-2a.mk
deleted file mode 100644
index 7e2ca18..0000000
--- a/core/combo/arch/arm/armv8-2a.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Linux on ARM.
-# Generating binaries for the ARMv8-2a architecture
-#
-# Many libraries are not aware of armv8-2a, and AArch32 is (almost) a superset
-# of armv7-a-neon. So just let them think we are just like v7.
-ARCH_ARM_HAVE_VFP               := true
-ARCH_ARM_HAVE_VFP_D32           := true
-ARCH_ARM_HAVE_NEON              := true
diff --git a/core/combo/arch/arm/armv8-a.mk b/core/combo/arch/arm/armv8-a.mk
deleted file mode 100644
index 19bc014..0000000
--- a/core/combo/arch/arm/armv8-a.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Linux on ARM.
-# Generating binaries for the ARMv8-a architecture
-#
-# Many libraries are not aware of armv8-a, and AArch32 is (almost) a superset
-# of armv7-a-neon. So just let them think we are just like v7.
-ARCH_ARM_HAVE_VFP               := true
-ARCH_ARM_HAVE_VFP_D32           := true
-ARCH_ARM_HAVE_NEON              := true
diff --git a/core/combo/arch/arm64/armv8-2a-dotprod.mk b/core/combo/arch/arm64/armv8-2a-dotprod.mk
deleted file mode 100644
index c775cf7..0000000
--- a/core/combo/arch/arm64/armv8-2a-dotprod.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# .mk file required to support build for the new armv8-2a-dotprod Arm64 arch
-# variant. The file just needs to be present but does not require to contain
-# anything
diff --git a/core/combo/arch/arm64/armv8-2a.mk b/core/combo/arch/arm64/armv8-2a.mk
deleted file mode 100644
index e69de29..0000000
--- a/core/combo/arch/arm64/armv8-2a.mk
+++ /dev/null
diff --git a/core/combo/arch/arm64/armv8-a-branchprot.mk b/core/combo/arch/arm64/armv8-a-branchprot.mk
deleted file mode 100644
index 77f3535..0000000
--- a/core/combo/arch/arm64/armv8-a-branchprot.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2021 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.
-#
-
-# .mk file required to support build for the new armv8-a-branchprot Arm64 arch
-# variant. The file just needs to be present but does not require to contain
-# anything
diff --git a/core/combo/arch/arm64/armv8-a.mk b/core/combo/arch/arm64/armv8-a.mk
deleted file mode 100644
index e69de29..0000000
--- a/core/combo/arch/arm64/armv8-a.mk
+++ /dev/null
diff --git a/core/combo/arch/arm64/armv9-2a.mk b/core/combo/arch/arm64/armv9-2a.mk
deleted file mode 100644
index 69ffde0..0000000
--- a/core/combo/arch/arm64/armv9-2a.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# 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.
-#
-
-# .mk file required to support build for the ARMv9.2-A arch variant.
-# The file just needs to be present, it does not need to contain anything.
diff --git a/core/combo/arch/arm64/armv9-3a.mk b/core/combo/arch/arm64/armv9-3a.mk
deleted file mode 100644
index 0f2c620..0000000
--- a/core/combo/arch/arm64/armv9-3a.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2025 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.
-#
-
-# .mk file required to support build for the ARMv9.3-A arch variant.
-# The file just needs to be present, it does not need to contain anything.
diff --git a/core/combo/arch/arm64/armv9-4a.mk b/core/combo/arch/arm64/armv9-4a.mk
deleted file mode 100644
index 6ab3bed..0000000
--- a/core/combo/arch/arm64/armv9-4a.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2025 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.
-#
-
-# .mk file required to support build for the ARMv9.4-A arch variant.
-# The file just needs to be present, it does not need to contain anything.
diff --git a/core/combo/arch/arm64/armv9-a.mk b/core/combo/arch/arm64/armv9-a.mk
deleted file mode 100644
index de0760a..0000000
--- a/core/combo/arch/arm64/armv9-a.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
-# .mk file required to support build for the new armv9-a Arm64 arch
-# variant. The file just needs to be present but does not require to contain
-# anything
diff --git a/core/combo/arch/riscv64/riscv64.mk b/core/combo/arch/riscv64/riscv64.mk
deleted file mode 100644
index 0505541..0000000
--- a/core/combo/arch/riscv64/riscv64.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file contains feature macro definitions specific to the
-# base 'riscv64' platform ABI.
diff --git a/core/combo/arch/x86/alderlake.mk b/core/combo/arch/x86/alderlake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86/alderlake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/amberlake.mk b/core/combo/arch/x86/amberlake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86/amberlake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/atom.mk b/core/combo/arch/x86/atom.mk
deleted file mode 100644
index bae7946..0000000
--- a/core/combo/arch/x86/atom.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file contains feature macro definitions specific to the
-# 'x86-atom' arch variant. This is an extension of the 'x86' base variant
-# that adds Atom-specific features.
-#
-# See build/make/core/combo/arch/x86/x86.mk for differences.
-#
diff --git a/core/combo/arch/x86/broadwell.mk b/core/combo/arch/x86/broadwell.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86/broadwell.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/goldmont-plus.mk b/core/combo/arch/x86/goldmont-plus.mk
deleted file mode 100644
index 4ce2053..0000000
--- a/core/combo/arch/x86/goldmont-plus.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# goldmont-plus arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/goldmont-without-sha-xsaves.mk b/core/combo/arch/x86/goldmont-without-sha-xsaves.mk
deleted file mode 100644
index 1b93c17..0000000
--- a/core/combo/arch/x86/goldmont-without-sha-xsaves.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# goldmont-without-xsaves arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/goldmont.mk b/core/combo/arch/x86/goldmont.mk
deleted file mode 100644
index b5a6ff2..0000000
--- a/core/combo/arch/x86/goldmont.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# goldmont arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/haswell.mk b/core/combo/arch/x86/haswell.mk
deleted file mode 100644
index ffa3bac..0000000
--- a/core/combo/arch/x86/haswell.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for Haswell processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/icelake.mk b/core/combo/arch/x86/icelake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86/icelake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/ivybridge.mk b/core/combo/arch/x86/ivybridge.mk
deleted file mode 100644
index a1358e6..0000000
--- a/core/combo/arch/x86/ivybridge.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for Ivy Bridge processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/kabylake.mk b/core/combo/arch/x86/kabylake.mk
deleted file mode 100644
index 9906259..0000000
--- a/core/combo/arch/x86/kabylake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors.
-# that support AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/sandybridge.mk b/core/combo/arch/x86/sandybridge.mk
deleted file mode 100644
index d6552ab..0000000
--- a/core/combo/arch/x86/sandybridge.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for SandyBridge processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/silvermont.mk b/core/combo/arch/x86/silvermont.mk
deleted file mode 100644
index 8ac2b98..0000000
--- a/core/combo/arch/x86/silvermont.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# silvermont arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/skylake.mk b/core/combo/arch/x86/skylake.mk
deleted file mode 100644
index 9906259..0000000
--- a/core/combo/arch/x86/skylake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors.
-# that support AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/stoneyridge.mk b/core/combo/arch/x86/stoneyridge.mk
deleted file mode 100644
index 05ff77a..0000000
--- a/core/combo/arch/x86/stoneyridge.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for Stoney Ridge processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/tigerlake.mk b/core/combo/arch/x86/tigerlake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86/tigerlake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/tremont.mk b/core/combo/arch/x86/tremont.mk
deleted file mode 100644
index b80d228..0000000
--- a/core/combo/arch/x86/tremont.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# tremont arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/whiskeylake.mk b/core/combo/arch/x86/whiskeylake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86/whiskeylake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86/x86.mk b/core/combo/arch/x86/x86.mk
deleted file mode 100644
index 066f66a..0000000
--- a/core/combo/arch/x86/x86.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file contains feature macro definitions specific to the
-# base 'x86' platform ABI.
-#
-# It is also used to build full_x86-eng / sdk_x86-eng platform images that
-# are run in the emulator under KVM emulation (i.e. running directly on
-# the host development machine's CPU).
-
-# These features are optional and shall not be included in the base platform
-# Otherwise, sdk_x86-eng system images might fail to run on some
-# developer machines.
diff --git a/core/combo/arch/x86/x86_64.mk b/core/combo/arch/x86/x86_64.mk
deleted file mode 100644
index eff406b..0000000
--- a/core/combo/arch/x86/x86_64.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is used as the second (32-bit) architecture when building a generic
-# x86_64 64-bit platform image. (full_x86_64-eng / sdk_x86_64-eng)
-#
-# The generic 'x86' variant cannot be used, since it resets some flags used
-# by the 'x86_64' variant.
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/alderlake.mk b/core/combo/arch/x86_64/alderlake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/alderlake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/amberlake.mk b/core/combo/arch/x86_64/amberlake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/amberlake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/broadwell.mk b/core/combo/arch/x86_64/broadwell.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/broadwell.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/goldmont-plus.mk b/core/combo/arch/x86_64/goldmont-plus.mk
deleted file mode 100644
index 4ce2053..0000000
--- a/core/combo/arch/x86_64/goldmont-plus.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# goldmont-plus arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/goldmont-without-sha-xsaves.mk b/core/combo/arch/x86_64/goldmont-without-sha-xsaves.mk
deleted file mode 100644
index 1b93c17..0000000
--- a/core/combo/arch/x86_64/goldmont-without-sha-xsaves.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# goldmont-without-xsaves arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/goldmont.mk b/core/combo/arch/x86_64/goldmont.mk
deleted file mode 100644
index b5a6ff2..0000000
--- a/core/combo/arch/x86_64/goldmont.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# goldmont arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/haswell.mk b/core/combo/arch/x86_64/haswell.mk
deleted file mode 100644
index faf12fa..0000000
--- a/core/combo/arch/x86_64/haswell.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86_64.
-# Generating binaries for Haswell processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/icelake.mk b/core/combo/arch/x86_64/icelake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/icelake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/ivybridge.mk b/core/combo/arch/x86_64/ivybridge.mk
deleted file mode 100644
index 464fa98..0000000
--- a/core/combo/arch/x86_64/ivybridge.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86_64.
-# Generating binaries for Ivy Bridge processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/kabylake.mk b/core/combo/arch/x86_64/kabylake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/kabylake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/sandybridge.mk b/core/combo/arch/x86_64/sandybridge.mk
deleted file mode 100644
index a09db2a..0000000
--- a/core/combo/arch/x86_64/sandybridge.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86_64.
-# Generating binaries for SandyBridge processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/silvermont.mk b/core/combo/arch/x86_64/silvermont.mk
deleted file mode 100644
index 8ac2b98..0000000
--- a/core/combo/arch/x86_64/silvermont.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# silvermont arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/skylake.mk b/core/combo/arch/x86_64/skylake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/skylake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/stoneyridge.mk b/core/combo/arch/x86_64/stoneyridge.mk
deleted file mode 100644
index 5950d9a..0000000
--- a/core/combo/arch/x86_64/stoneyridge.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on x86_64.
-# Generating binaries for Stoney Ridge processors.
-#
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/tigerlake.mk b/core/combo/arch/x86_64/tigerlake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/tigerlake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/tremont.mk b/core/combo/arch/x86_64/tremont.mk
deleted file mode 100644
index b80d228..0000000
--- a/core/combo/arch/x86_64/tremont.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file contains feature macro definitions specific to the
-# tremont arch variant.
-#
-# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/whiskeylake.mk b/core/combo/arch/x86_64/whiskeylake.mk
deleted file mode 100644
index a7ae6ed..0000000
--- a/core/combo/arch/x86_64/whiskeylake.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration for Linux on x86.
-# Generating binaries for processors
-# that have AVX2 feature flag
-#
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/combo/arch/x86_64/x86_64.mk b/core/combo/arch/x86_64/x86_64.mk
deleted file mode 100755
index 17413c7..0000000
--- a/core/combo/arch/x86_64/x86_64.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file contains feature macro definitions specific to the
-# base 'x86_64' platform ABI.
-#
-# It is also used to build full_x86_64-eng / sdk_x86_64-eng  platform images
-# that are run in the emulator under KVM emulation (i.e. running directly on
-# the host development machine's CPU).
-
-ARCH_X86_HAVE_SSE4_1 := true
diff --git a/core/main.mk b/core/main.mk
index aed3fa2..a7a1aed 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1556,7 +1556,6 @@
   # sources in a droidcore full build.
 
   $(call dist-for-goals, droidcore, \
-    $(BUILT_OTATOOLS_PACKAGE) \
     $(APPCOMPAT_ZIP) \
   )
 
@@ -1757,7 +1756,8 @@
   $(PRODUCT_OUT)/apex/% \
   $(PRODUCT_OUT)/fake_packages/% \
   $(PRODUCT_OUT)/testcases/% \
-  $(dest_files_without_source)
+  $(dest_files_without_source) \
+  $(PRODUCT_OUT)/required_images
 # Check if each partition image is built, if not filter out all its installed files
 # Also check if a partition uses prebuilt image file, save the info if prebuilt image is used.
 PREBUILT_PARTITION_COPY_FILES :=
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index d5261f4..5dfc6c1 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -39,6 +39,11 @@
 
 LOCAL_CHECKED_MODULE := $(my_prebuilt_src_file)
 
+ifneq (,$(LOCAL_APKCERTS_FILE))
+  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
+  PACKAGES.$(LOCAL_MODULE).APKCERTS_FILE := $(LOCAL_APKCERTS_FILE)
+endif
+
 ifneq (APPS,$(LOCAL_MODULE_CLASS))
 ifdef LOCAL_COMPRESSED_MODULE
 $(error $(LOCAL_MODULE) : LOCAL_COMPRESSED_MODULE can only be defined for module class APPS)
diff --git a/envsetup.sh b/envsetup.sh
index c040311..444048f 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -520,7 +520,8 @@
         echo "Note that the previous interactive menu and list of hard-coded"
         echo "list of curated targets has been removed. If you would like the"
         echo "list of products, release configs for a particular product, or"
-        echo "variants, run list_products list_releases or list_variants"
+        echo "variants, run the following as individual commands:"
+        echo "list_products, list_releases, or list_variants"
         echo "respectively."
         echo
     ) 1>&2
diff --git a/tools/aconfig/aconfig/Android.bp b/tools/aconfig/aconfig/Android.bp
index 7bdec58..c2775c2 100644
--- a/tools/aconfig/aconfig/Android.bp
+++ b/tools/aconfig/aconfig/Android.bp
@@ -23,6 +23,10 @@
         "libtinytemplate",
         "libconvert_finalized_flags",
     ],
+    cfgs: select(release_flag("RELEASE_ACONFIG_FINGERPRINT_RUST"), {
+        true: ["enable_fingerprint_rust"],
+        default: [],
+    }),
 }
 
 rust_binary_host {
diff --git a/tools/aconfig/aconfig/Cargo.toml b/tools/aconfig/aconfig/Cargo.toml
index 7e4bdf2..e535b81 100644
--- a/tools/aconfig/aconfig/Cargo.toml
+++ b/tools/aconfig/aconfig/Cargo.toml
@@ -25,3 +25,6 @@
 serde = { version = "1.0.152", features = ["derive"] }
 serde_json = "1.0.93"
 convert_finalized_flags = { path = "../convert_finalized_flags" }
+
+[lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(enable_fingerprint_rust)'] }
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index 2ee5f36..412b711 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -31,6 +31,7 @@
     flag_ids: HashMap<String, u16>,
     parsed_flags_iter: I,
     codegen_mode: CodegenMode,
+    package_fingerprint: Option<u64>,
 ) -> Result<OutputFile>
 where
     I: Iterator<Item = ProtoParsedFlag>,
@@ -40,12 +41,15 @@
         .collect();
     let has_readwrite = template_flags.iter().any(|item| item.readwrite);
     let container = (template_flags.first().expect("zero template flags").container).to_string();
+    let use_package_fingerprint = package_fingerprint.is_some();
     let context = TemplateContext {
         package: package.to_string(),
         template_flags,
         modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
         has_readwrite,
         container,
+        use_package_fingerprint,
+        package_fingerprint: package_fingerprint.unwrap_or_default(),
     };
     let mut template = TinyTemplate::new();
     template.add_template(
@@ -69,6 +73,8 @@
     pub modules: Vec<String>,
     pub has_readwrite: bool,
     pub container: String,
+    pub use_package_fingerprint: bool,
+    pub package_fingerprint: u64,
 }
 
 #[derive(Serialize)]
@@ -131,10 +137,9 @@
 /// flag provider
 pub struct FlagProvider;
 
-static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe {
+static PACKAGE_CONTEXT: LazyLock<Result<Option<PackageReadContext>, AconfigStorageError>> = LazyLock::new(|| unsafe {
     get_mapped_storage_file("system", StorageFileType::PackageMap)
     .and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
-    .map(|context| context.map(|c| c.boolean_start_index))
 });
 
 static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe {
@@ -153,13 +158,13 @@
         .as_ref()
         .map_err(|err| format!("failed to get flag val map: {err}"))
         .and_then(|flag_val_map| {
-            PACKAGE_OFFSET
-               .as_ref()
-               .map_err(|err| format!("failed to get package read offset: {err}"))
-               .and_then(|package_offset| {
-                   match package_offset {
-                       Some(offset) => {
-                           get_boolean_flag_value(&flag_val_map, offset + 0)
+            PACKAGE_CONTEXT
+              .as_ref()
+               .map_err(|err| format!("failed to get package read context: {err}"))
+               .and_then(|package_context| {
+                   match package_context {
+                       Some(context) => {
+                           get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 0)
                                .map_err(|err| format!("failed to get flag: {err}"))
                        },
                        None => {
@@ -193,13 +198,13 @@
             .as_ref()
             .map_err(|err| format!("failed to get flag val map: {err}"))
             .and_then(|flag_val_map| {
-                PACKAGE_OFFSET
+                PACKAGE_CONTEXT
                     .as_ref()
-                    .map_err(|err| format!("failed to get package read offset: {err}"))
-                    .and_then(|package_offset| {
-                        match package_offset {
-                            Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 1)
+                .map_err(|err| format!("failed to get package read context: {err}"))
+                .and_then(|package_context| {
+                    match package_context {
+                        Some(context) => {
+                           get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 1)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -233,13 +238,13 @@
             .as_ref()
             .map_err(|err| format!("failed to get flag val map: {err}"))
             .and_then(|flag_val_map| {
-                PACKAGE_OFFSET
+                PACKAGE_CONTEXT
                     .as_ref()
-                    .map_err(|err| format!("failed to get package read offset: {err}"))
-                    .and_then(|package_offset| {
-                        match package_offset {
-                            Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 2)
+                .map_err(|err| format!("failed to get package read context: {err}"))
+                .and_then(|package_context| {
+                    match package_context {
+                        Some(context) => {
+                           get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 2)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -274,14 +279,14 @@
             .as_ref()
             .map_err(|err| format!("failed to get flag val map: {err}"))
             .and_then(|flag_val_map| {
-                PACKAGE_OFFSET
+                PACKAGE_CONTEXT
                     .as_ref()
-                    .map_err(|err| format!("failed to get package read offset: {err}"))
-                    .and_then(|package_offset| {
-                        match package_offset {
-                            Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 7)
-                                    .map_err(|err| format!("failed to get flag: {err}"))
+                    .map_err(|err| format!("failed to get package read context: {err}"))
+                    .and_then(|package_context| {
+                      match package_context {
+                            Some(context) => {
+                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 7)
+                                      .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
                                 log!(Level::Error, "no context found for package com.android.aconfig.test");
@@ -426,10 +431,9 @@
     overrides: BTreeMap<&'static str, bool>,
 }
 
-static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe {
+static PACKAGE_CONTEXT: LazyLock<Result<Option<PackageReadContext>, AconfigStorageError>> = LazyLock::new(|| unsafe {
     get_mapped_storage_file("system", StorageFileType::PackageMap)
     .and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
-    .map(|context| context.map(|c| c.boolean_start_index))
 });
 
 static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe {
@@ -448,13 +452,13 @@
         .as_ref()
         .map_err(|err| format!("failed to get flag val map: {err}"))
         .and_then(|flag_val_map| {
-            PACKAGE_OFFSET
+            PACKAGE_CONTEXT
                .as_ref()
-               .map_err(|err| format!("failed to get package read offset: {err}"))
-               .and_then(|package_offset| {
-                   match package_offset {
-                       Some(offset) => {
-                           get_boolean_flag_value(&flag_val_map, offset + 0)
+                    .map_err(|err| format!("failed to get package read context: {err}"))
+                    .and_then(|package_context| {
+                      match package_context {
+                            Some(context) => {
+                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 0)
                                .map_err(|err| format!("failed to get flag: {err}"))
                        },
                        None => {
@@ -488,13 +492,13 @@
             .as_ref()
             .map_err(|err| format!("failed to get flag val map: {err}"))
             .and_then(|flag_val_map| {
-                PACKAGE_OFFSET
+                PACKAGE_CONTEXT
                     .as_ref()
-                    .map_err(|err| format!("failed to get package read offset: {err}"))
-                    .and_then(|package_offset| {
-                        match package_offset {
-                            Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 1)
+                    .map_err(|err| format!("failed to get package read context: {err}"))
+                    .and_then(|package_context| {
+                      match package_context {
+                            Some(context) => {
+                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 1)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -528,13 +532,13 @@
             .as_ref()
             .map_err(|err| format!("failed to get flag val map: {err}"))
             .and_then(|flag_val_map| {
-                PACKAGE_OFFSET
+                PACKAGE_CONTEXT
                     .as_ref()
-                    .map_err(|err| format!("failed to get package read offset: {err}"))
-                    .and_then(|package_offset| {
-                        match package_offset {
-                            Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 2)
+                    .map_err(|err| format!("failed to get package read context: {err}"))
+                    .and_then(|package_context| {
+                      match package_context {
+                            Some(context) => {
+                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 2)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -569,13 +573,13 @@
             .as_ref()
             .map_err(|err| format!("failed to get flag val map: {err}"))
             .and_then(|flag_val_map| {
-                PACKAGE_OFFSET
+                PACKAGE_CONTEXT
                     .as_ref()
-                    .map_err(|err| format!("failed to get package read offset: {err}"))
-                    .and_then(|package_offset| {
-                        match package_offset {
-                            Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 7)
+                    .map_err(|err| format!("failed to get package read context: {err}"))
+                    .and_then(|package_context| {
+                      match package_context {
+                            Some(context) => {
+                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 7)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -926,15 +930,13 @@
             flag_ids,
             modified_parsed_flags.into_iter(),
             mode,
+            None,
         )
         .unwrap();
         assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
-        assert_eq!(
-            None,
-            crate::test::first_significant_code_diff(
-                expected,
-                &String::from_utf8(generated.contents).unwrap()
-            )
+        crate::test::assert_no_significant_code_diff(
+            expected,
+            &String::from_utf8(generated.contents).unwrap(),
         );
     }
 
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 14a98f0..623d875 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -258,13 +258,28 @@
         "Exported mode for generated rust flag library is disabled"
     );
     let parsed_flags = input.try_parse_flags()?;
-    let modified_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, codegen_mode)?;
+    let modified_parsed_flags =
+        modify_parsed_flags_based_on_mode(parsed_flags.clone(), codegen_mode)?;
     let Some(package) = find_unique_package(&modified_parsed_flags) else {
         bail!("no parsed flags, or the parsed flags use different packages");
     };
     let package = package.to_string();
+
+    let package_fingerprint: Option<u64> = if cfg!(enable_fingerprint_rust) {
+        let mut flag_names = extract_flag_names(parsed_flags)?;
+        Some(compute_flags_fingerprint(&mut flag_names))
+    } else {
+        None
+    };
+
     let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
-    generate_rust_code(&package, flag_ids, modified_parsed_flags.into_iter(), codegen_mode)
+    generate_rust_code(
+        &package,
+        flag_ids,
+        modified_parsed_flags.into_iter(),
+        codegen_mode,
+        package_fingerprint,
+    )
 }
 
 pub fn create_storage(
diff --git a/tools/aconfig/aconfig/src/test.rs b/tools/aconfig/aconfig/src/test.rs
index 10da252..af2acda 100644
--- a/tools/aconfig/aconfig/src/test.rs
+++ b/tools/aconfig/aconfig/src/test.rs
@@ -333,6 +333,30 @@
         }
     }
 
+    /// Asserts that the two strings are equivalent. For use in tests. Fails
+    /// with formatted error message for easier debugging.
+    pub fn assert_no_significant_code_diff(expected: &str, actual: &str) {
+        let expected =
+            expected.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
+        let actual = actual.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
+        let fail_message: Option<String> =
+            match itertools::diff_with(expected, actual, |left, right| left == right) {
+                Some(itertools::Diff::FirstMismatch(_, mut left, mut right)) => Some(format!(
+                    "DOES NOT MATCH: 1) expected, 2) actual:\n{}\n{}",
+                    left.next().unwrap(),
+                    right.next().unwrap()
+                )),
+                Some(itertools::Diff::Shorter(_, mut left)) => {
+                    Some(format!("LHS trailing data: '{}'", left.next().unwrap()))
+                }
+                Some(itertools::Diff::Longer(_, mut right)) => {
+                    Some(format!("RHS trailing data: '{}'", right.next().unwrap()))
+                }
+                None => None,
+            };
+        assert!(fail_message.is_none(), "{}", fail_message.unwrap());
+    }
+
     #[test]
     fn test_first_significant_code_diff() {
         assert!(first_significant_code_diff("", "").is_none());
diff --git a/tools/aconfig/aconfig/templates/rust.template b/tools/aconfig/aconfig/templates/rust.template
index 56323e2..292beae 100644
--- a/tools/aconfig/aconfig/templates/rust.template
+++ b/tools/aconfig/aconfig/templates/rust.template
@@ -9,10 +9,9 @@
 pub struct FlagProvider;
 
 {{ if has_readwrite- }}
-static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe \{
+static PACKAGE_CONTEXT: LazyLock<Result<Option<PackageReadContext>, AconfigStorageError>> = LazyLock::new(|| unsafe \{
     get_mapped_storage_file("{container}", StorageFileType::PackageMap)
     .and_then(|package_map| get_package_read_context(&package_map, "{package}"))
-    .map(|context| context.map(|c| c.boolean_start_index))
 });
 
 static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe \{
@@ -30,17 +29,38 @@
             .with_tag_on_device("aconfig_rust_codegen")
             .with_max_level(LevelFilter::Info));
 
+    {{ -if use_package_fingerprint }}
+    let fingerprint_check_failed: bool = PACKAGE_CONTEXT
+        .as_ref()
+        .is_ok_and(|package_context| \{
+              match package_context \{
+                Some(context) => \{
+                        return context.fingerprint != {package_fingerprint}
+                    },
+                    None => \{
+                        log!(Level::Info, "aconfig_rust_codegen: missing fingerprint; performing lookup.");
+                        false
+                    }
+                  }
+                });
+
+    if fingerprint_check_failed \{
+      log!(Level::Error, "Fingerprint mismatch for package {package}; returning flag default ({flag.default_value}) for {flag.name}.");
+      return {flag.default_value};
+    }
+    {{ -endif }}
+
     let flag_value_result = FLAG_VAL_MAP
         .as_ref()
         .map_err(|err| format!("failed to get flag val map: \{err}"))
         .and_then(|flag_val_map| \{
-            PACKAGE_OFFSET
+            PACKAGE_CONTEXT
                 .as_ref()
-                .map_err(|err| format!("failed to get package read offset: \{err}"))
-                .and_then(|package_offset| \{
-                    match package_offset \{
-                        Some(offset) => \{
-                            get_boolean_flag_value(&flag_val_map, offset + {flag.flag_offset})
+                .map_err(|err| format!("failed to get package read context: \{err}"))
+                .and_then(|package_context| \{
+                    match package_context \{
+                        Some(context) => \{
+                            get_boolean_flag_value(&flag_val_map, context.boolean_start_index + {flag.flag_offset})
                                 .map_err(|err| format!("failed to get flag: \{err}"))
                         },
                         None => \{
diff --git a/tools/aconfig/aconfig/templates/rust_test.template b/tools/aconfig/aconfig/templates/rust_test.template
index 139a5ec..66f7817 100644
--- a/tools/aconfig/aconfig/templates/rust_test.template
+++ b/tools/aconfig/aconfig/templates/rust_test.template
@@ -12,10 +12,9 @@
 }
 
 {{ if has_readwrite- }}
-static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe \{
+static PACKAGE_CONTEXT: LazyLock<Result<Option<PackageReadContext>, AconfigStorageError>> = LazyLock::new(|| unsafe \{
     get_mapped_storage_file("{container}", StorageFileType::PackageMap)
     .and_then(|package_map| get_package_read_context(&package_map, "{package}"))
-    .map(|context| context.map(|c| c.boolean_start_index))
 });
 
 static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe \{
@@ -33,17 +32,38 @@
             .with_tag_on_device("aconfig_rust_codegen")
             .with_max_level(LevelFilter::Info));
 
+    {{ -if use_package_fingerprint }}
+    let fingerprint_check_failed: bool = PACKAGE_CONTEXT
+        .as_ref()
+        .is_ok_and(|package_context| \{
+              match package_context \{
+                Some(context) => \{
+                        return context.fingerprint != {package_fingerprint}
+                    },
+                    None => \{
+                        log!(Level::Info, "aconfig_rust_codegen: missing fingerprint; performing lookup.");
+                        false
+                    }
+                  }
+                });
+
+    if fingerprint_check_failed \{
+      log!(Level::Error, "Fingerprint mismatch for package {package}; returning flag default ({flag.default_value}) for {flag.name}.");
+      return {flag.default_value};
+    }
+    {{ -endif }}
+
     let flag_value_result = FLAG_VAL_MAP
         .as_ref()
         .map_err(|err| format!("failed to get flag val map: \{err}"))
         .and_then(|flag_val_map| \{
-            PACKAGE_OFFSET
+            PACKAGE_CONTEXT
                 .as_ref()
-                .map_err(|err| format!("failed to get package read offset: \{err}"))
-                .and_then(|package_offset| \{
-                    match package_offset \{
-                        Some(offset) => \{
-                            get_boolean_flag_value(&flag_val_map, offset + {flag.flag_offset})
+                .map_err(|err| format!("failed to get package read context: \{err}"))
+                .and_then(|package_context| \{
+                    match package_context \{
+                        Some(context) => \{
+                            get_boolean_flag_value(&flag_val_map, context.boolean_start_index + {flag.flag_offset})
                                 .map_err(|err| format!("failed to get flag: \{err}"))
                         },
                         None => \{
diff --git a/tools/otatools_package/Android.bp b/tools/otatools_package/Android.bp
index dea3d82..c9c4794 100644
--- a/tools/otatools_package/Android.bp
+++ b/tools/otatools_package/Android.bp
@@ -33,21 +33,177 @@
     out: ["otatools_package_dep_jars.zip"],
 }
 
+cc_genrule {
+    name: "otatools_package_dep_libs",
+    host_supported: true,
+    device_supported: false,
+    compile_multilib: "first",
+    tools: ["soong_zip"],
+    cmd: "mkdir -p $(genDir)/$$CC_MULTILIB &&" +
+        "cp $(in) $(genDir)/$$CC_MULTILIB && " +
+        "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)/$$CC_MULTILIB",
+    srcs: [
+        ":libbase",
+        ":libbrillo",
+        ":libbrillo-stream",
+        ":libc++",
+        "//external/libchrome:libchrome",
+        ":libconscrypt_openjdk_jni",
+        ":libcrypto",
+        ":libcrypto_utils",
+        ":libcutils",
+        ":libevent",
+        ":libext2_blkid",
+        ":libext2_com_err",
+        ":libext2_e2p",
+        ":libext2_quota",
+        ":libext2_uuid",
+        ":libext2fs",
+        ":libext4_utils",
+        ":libfec",
+        ":libhidl-gen-utils",
+        ":libhidlmetadata",
+        ":libicui18n",
+        ":libicuuc",
+        ":liblog",
+        ":liblp",
+        ":liblz4",
+        ":libpcre2",
+        ":libprocessgroup",
+        ":libprotobuf-cpp-lite",
+        ":libselinux",
+        ":libsparse",
+        ":libsqlite",
+        ":libsquashfs_utils",
+        ":libssl",
+        ":libz",
+        ":libziparchive",
+    ],
+    out: ["otatools_package_dep_libs.zip"],
+}
+
+cc_genrule {
+    name: "otatools_package_dep_bins",
+    host_supported: true,
+    device_supported: false,
+    compile_multilib: "first",
+    tools: [
+        "apksigner",
+        "boot_signer",
+        "merge_zips",
+        "signapk",
+        "verity_signer",
+    ],
+    cmd: "mkdir -p $(genDir)/bin && " +
+        "cp $(in) $(genDir)/bin && " +
+        "cp $(location apksigner) $(location boot_signer) $(location merge_zips) $(location signapk) $(location verity_signer) $(genDir)/bin && " +
+        "$(location :soong_zip) -o $(out) -C $(genDir) -D $(genDir)/bin",
+    srcs: [
+        ":aapt2",
+        ":add_img_to_target_files",
+        ":apex_compression_tool",
+        ":apexd_host",
+        ":apexer",
+        ":append2simg",
+        ":avbtool",
+        ":blk_alloc_to_base_fs",
+        ":brillo_update_payload",
+        ":brotli",
+        ":bsdiff",
+        ":build_image",
+        ":build_super_image",
+        ":build_verity_metadata",
+        ":build_verity_tree",
+        ":care_map_generator",
+        ":check_ota_package_signature",
+        ":check_target_files_signatures",
+        ":check_target_files_vintf",
+        ":checkvintf",
+        ":create_brick_ota",
+        ":deapexer",
+        ":debugfs_static",
+        ":delta_generator",
+        ":e2fsck",
+        ":e2fsdroid",
+        ":fc_sort",
+        ":fec",
+        ":fs_config",
+        ":fsck.erofs",
+        ":fsck.f2fs",
+        ":generate_verity_key",
+        ":host_init_verifier",
+        ":img2simg",
+        ":img_from_target_files",
+        ":initrd_bootconfig",
+        ":lpmake",
+        ":lpunpack",
+        ":lz4",
+        ":make_f2fs",
+        ":make_f2fs_casefold",
+        ":merge_ota",
+        ":merge_target_files",
+        "//device/generic/goldfish:mk_combined_img",
+        ":mkbootfs",
+        ":mkbootimg",
+        ":mke2fs",
+        ":mkf2fsuserimg",
+        ":mkfs.erofs",
+        ":mksquashfs",
+        ":mksquashfsimage",
+        ":mkuserimg_mke2fs",
+        ":ota_extractor",
+        ":ota_from_target_files",
+        ":repack_bootimg",
+        ":resize2fs",
+        ":secilc",
+        ":sefcontext_compile",
+        ":sgdisk",
+        ":shflags",
+        ":sign_apex",
+        ":sign_target_files_apks",
+        ":sign_virt_apex",
+        ":simg2img",
+        ":sload_f2fs",
+        ":soong_zip",
+        ":toybox",
+        ":tune2fs",
+        ":unpack_bootimg",
+        ":update_device",
+        ":validate_target_files",
+        ":verity_verifier",
+        ":zip2zip",
+        ":zipalign",
+        ":zucchini",
+    ] + select(soong_config_variable("otatools", "use_build_mixed_kernels_ramdisk"), {
+        true: [":build_mixed_kernels_ramdisk_host"],
+        default: [],
+    }) + select(soong_config_variable("otatools", "use_bootable_deprecated_ota_applypatch"), {
+        true: [
+            ":imgdiff",
+            ":update_host_simulator",
+        ],
+        default: [],
+    }),
+    out: ["otatools_package_dep_bins.zip"],
+}
+
 java_genrule_host {
-    name: "otatools_package",
+    name: "otatools-package",
     tools: ["merge_zips"],
     compile_multilib: "first",
     cmd: "$(location merge_zips) $(out) $(in)",
     srcs: [
         ":otatools_package_cert_files",
+        ":otatools_package_dep_bins",
         ":otatools_package_dep_jars",
+        ":otatools_package_dep_libs",
         ":otatools_package_releasetools",
     ],
-    // TODO: Rename as "otatools.zip" when the rest files are ready.
-    out: ["otatools_temp.zip"],
+    out: ["otatools.zip"],
     dist: {
         targets: [
-            "otatools-package-temp",
+            "droidcore",
+            "otatools-package",
         ],
     },
 }